| 213 | __array_priority__ = -100.0 |
| 214 | |
| 215 | def __new__(cls, filename, dtype=uint8, mode='r+', offset=0, |
| 216 | shape=None, order='C'): |
| 217 | # Import here to minimize 'import numpy' overhead |
| 218 | import mmap |
| 219 | import os.path |
| 220 | try: |
| 221 | mode = mode_equivalents[mode] |
| 222 | except KeyError as e: |
| 223 | if mode not in valid_filemodes: |
| 224 | all_modes = valid_filemodes + list(mode_equivalents.keys()) |
| 225 | raise ValueError( |
| 226 | f"mode must be one of {all_modes!r} (got {mode!r})" |
| 227 | ) from None |
| 228 | |
| 229 | if mode == 'w+' and shape is None: |
| 230 | raise ValueError("shape must be given if mode == 'w+'") |
| 231 | |
| 232 | if hasattr(filename, 'read'): |
| 233 | f_ctx = nullcontext(filename) |
| 234 | else: |
| 235 | f_ctx = open( |
| 236 | os.fspath(filename), |
| 237 | ('r' if mode == 'c' else mode) + 'b' |
| 238 | ) |
| 239 | |
| 240 | with f_ctx as fid: |
| 241 | fid.seek(0, 2) |
| 242 | flen = fid.tell() |
| 243 | descr = dtypedescr(dtype) |
| 244 | _dbytes = descr.itemsize |
| 245 | |
| 246 | if shape is None: |
| 247 | bytes = flen - offset |
| 248 | if bytes % _dbytes: |
| 249 | raise ValueError("Size of available data is not a " |
| 250 | "multiple of the data-type size.") |
| 251 | size = bytes // _dbytes |
| 252 | shape = (size,) |
| 253 | else: |
| 254 | if not isinstance(shape, (tuple, list)): |
| 255 | try: |
| 256 | shape = [operator.index(shape)] |
| 257 | except TypeError: |
| 258 | pass |
| 259 | shape = tuple(shape) |
| 260 | size = np.intp(1) # avoid overflows |
| 261 | for k in shape: |
| 262 | size *= k |
| 263 | |
| 264 | bytes = int(offset + size * _dbytes) |
| 265 | |
| 266 | if mode in ('w+', 'r+'): |
| 267 | # gh-27723 |
| 268 | # if bytes == 0, we write out 1 byte to allow empty memmap. |
| 269 | bytes = max(bytes, 1) |
| 270 | if flen < bytes: |
| 271 | fid.seek(bytes - 1, 0) |
| 272 | fid.write(b'\0') |