Skip to content

Commit ef5ca7b

Browse files
author
Kazuki Suzuki Przyborowski
committed
Update pycatfile.py
1 parent 94d24f9 commit ef5ca7b

1 file changed

Lines changed: 69 additions & 0 deletions

File tree

pycatfile.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)