@@ -6220,6 +6220,75 @@ def __setattr__(self, name, value):
62206220 object.__setattr__(self, name, value); return
62216221 object.__setattr__(self, name, value)
62226222
6223+ # ========= shared utilities =========
6224+
6225+ def _maybe_make_mmap(fp_like, mode, use_mmap=False, mmap_size=None):
6226+ """
6227+ If use_mmap is True and fp_like ultimately has a real fileno(),
6228+ return (fp_like, mm) where mm is an mmap.mmap for the whole file (read)
6229+ or a pre-sized mapping (write). Otherwise return (fp_like, None).
6230+ """
6231+ if not use_mmap:
6232+ return fp_like, None
6233+
6234+ base = _extract_base_fp(fp_like)
6235+ if base is None:
6236+ return fp_like, None # BytesIO / compressed stream etc.
6237+
6238+ import mmap
6239+ # READ mapping: map entire file (size 0 means "whole file")
6240+ if "r" in mode and "w" not in mode and "a" not in mode and "x" not in mode:
6241+ try:
6242+ mm = mmap.mmap(base.fileno(), 0, access=mmap.ACCESS_READ)
6243+ return fp_like, mm
6244+ except Exception:
6245+ return fp_like, None
6246+
6247+ # WRITE mapping: must pre-size
6248+ if any(ch in mode for ch in "wax+"):
6249+ if not mmap_size or mmap_size <= 0:
6250+ # caller must provide a mapping length for writes
6251+ return fp_like, None
6252+ try:
6253+ # Ensure the underlying file is opened read+write
6254+ # (re-open if needed)
6255+ try:
6256+ fd = base.fileno()
6257+ except Exception:
6258+ return fp_like, None
6259+
6260+ # Make sure file is large enough
6261+ try:
6262+ base.truncate(mmap_size)
6263+ except Exception:
6264+ return fp_like, None
6265+
6266+ mm = mmap.mmap(fd, mmap_size, access=mmap.ACCESS_WRITE)
6267+ return fp_like, mm
6268+ except Exception:
6269+ return fp_like, None
6270+
6271+ return fp_like, None
6272+
6273+
6274+ def open_adapter(obj_or_path, mode="rb", use_mmap=False, mmap_size=None):
6275+ """
6276+ Universal opener:
6277+ - If given a path (str/bytes), open it with built-in open().
6278+ - If given a file-like, use it as-is.
6279+ Returns a FileLikeAdapter, optionally mmap-backed (only when possible).
6280+ """
6281+ is_path = isinstance(obj_or_path, (str, bytes))
6282+ if is_path:
6283+ fp = open(obj_or_path, mode)
6284+ fp, mm = _maybe_make_mmap(fp, mode, use_mmap=use_mmap, mmap_size=mmap_size)
6285+ return FileLikeAdapter(fp, mode=mode, mm=mm)
6286+
6287+ # file-like object
6288+ fp_like = obj_or_path
6289+ fp_like, mm = _maybe_make_mmap(fp_like, mode, use_mmap=use_mmap, mmap_size=mmap_size)
6290+ return FileLikeAdapter(fp_like, mode=mode, mm=mm)
6291+
62236292
62246293# Assumes you already have: compressionsupport, outextlistwd, MkTempFile, etc.
62256294
0 commit comments