Skip to content

Commit e2e5907

Browse files
author
Kazuki Suzuki Przyborowski
committed
Update pyarchivefile.py
1 parent 56b3df3 commit e2e5907

1 file changed

Lines changed: 68 additions & 0 deletions

File tree

pyarchivefile.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6206,6 +6206,74 @@ def __setattr__(self, name, value):
62066206
object.__setattr__(self, name, value); return
62076207
object.__setattr__(self, name, value)
62086208

6209+
# ========= shared utilities =========
6210+
6211+
def _maybe_make_mmap(fp_like, mode, use_mmap=False, mmap_size=None):
6212+
"""
6213+
If use_mmap is True and fp_like ultimately has a real fileno(),
6214+
return (fp_like, mm) where mm is an mmap.mmap for the whole file (read)
6215+
or a pre-sized mapping (write). Otherwise return (fp_like, None).
6216+
"""
6217+
if not use_mmap:
6218+
return fp_like, None
6219+
6220+
base = _extract_base_fp(fp_like)
6221+
if base is None:
6222+
return fp_like, None # BytesIO / compressed stream etc.
6223+
6224+
import mmap
6225+
# READ mapping: map entire file (size 0 means "whole file")
6226+
if "r" in mode and "w" not in mode and "a" not in mode and "x" not in mode:
6227+
try:
6228+
mm = mmap.mmap(base.fileno(), 0, access=mmap.ACCESS_READ)
6229+
return fp_like, mm
6230+
except Exception:
6231+
return fp_like, None
6232+
6233+
# WRITE mapping: must pre-size
6234+
if any(ch in mode for ch in "wax+"):
6235+
if not mmap_size or mmap_size <= 0:
6236+
# caller must provide a mapping length for writes
6237+
return fp_like, None
6238+
try:
6239+
# Ensure the underlying file is opened read+write
6240+
# (re-open if needed)
6241+
try:
6242+
fd = base.fileno()
6243+
except Exception:
6244+
return fp_like, None
6245+
6246+
# Make sure file is large enough
6247+
try:
6248+
base.truncate(mmap_size)
6249+
except Exception:
6250+
return fp_like, None
6251+
6252+
mm = mmap.mmap(fd, mmap_size, access=mmap.ACCESS_WRITE)
6253+
return fp_like, mm
6254+
except Exception:
6255+
return fp_like, None
6256+
6257+
return fp_like, None
6258+
6259+
6260+
def open_adapter(obj_or_path, mode="rb", use_mmap=False, mmap_size=None):
6261+
"""
6262+
Universal opener:
6263+
- If given a path (str/bytes), open it with built-in open().
6264+
- If given a file-like, use it as-is.
6265+
Returns a FileLikeAdapter, optionally mmap-backed (only when possible).
6266+
"""
6267+
is_path = isinstance(obj_or_path, (str, bytes))
6268+
if is_path:
6269+
fp = open(obj_or_path, mode)
6270+
fp, mm = _maybe_make_mmap(fp, mode, use_mmap=use_mmap, mmap_size=mmap_size)
6271+
return FileLikeAdapter(fp, mode=mode, mm=mm)
6272+
6273+
# file-like object
6274+
fp_like = obj_or_path
6275+
fp_like, mm = _maybe_make_mmap(fp_like, mode, use_mmap=use_mmap, mmap_size=mmap_size)
6276+
return FileLikeAdapter(fp_like, mode=mode, mm=mm)
62096277

62106278
# Assumes you already have: compressionsupport, outextlistwd, MkTempFile, etc.
62116279

0 commit comments

Comments
 (0)