5858
5959if ty.TYPE_CHECKING: # pragma: no cover
6060 import numpy.typing as npt
61+ from typing_extensions import Self # PY310
6162
6263 # Taken from numpy/__init__.pyi
6364 _DType = ty.TypeVar('_DType', bound=np.dtype[ty.Any])
@@ -212,19 +213,29 @@ def __init__(self, file_like, spec, *, mmap=True, order=None, keep_file_open=Non
212213 self.order = order
213214 # Flags to keep track of whether a single ImageOpener is created, and
214215 # whether a single underlying file handle is created.
215- self._keep_file_open, self._persist_opener = self._should_keep_file_open(
216- file_like, keep_file_open
217- )
216+ self._keep_file_open, self._persist_opener = self._should_keep_file_open(keep_file_open)
218217 self._lock = RLock()
219218
220- def copy(self):
219+ def _has_fh(self) -> bool:
220+ """Determine if our file-like is a filehandle or path"""
221+ return hasattr(self.file_like, 'read') and hasattr(self.file_like, 'seek')
222+
223+ def copy(self) -> Self:
224+ """Create a new ArrayProxy for the same file and parameters
225+
226+ If the proxied file is an open file handle, the new ArrayProxy
227+ will share a lock with the old one.
228+ """
221229 spec = self._shape, self._dtype, self._offset, self._slope, self._inter
222- return ArrayProxy (
230+ new = self.__class__ (
223231 self.file_like,
224232 spec,
225233 mmap=self._mmap,
226234 keep_file_open=self._keep_file_open,
227235 )
236+ if self._has_fh():
237+ new._lock = self._lock
238+ return new
228239
229240 def __del__(self):
230241 """If this ``ArrayProxy`` was created with ``keep_file_open=True``,
@@ -245,13 +256,13 @@ def __setstate__(self, state):
245256 self.__dict__.update(state)
246257 self._lock = RLock()
247258
248- def _should_keep_file_open(self, file_like, keep_file_open):
259+ def _should_keep_file_open(self, keep_file_open):
249260 """Called by ``__init__``.
250261
251262 This method determines how to manage ``ImageOpener`` instances,
252263 and the underlying file handles - the behaviour depends on:
253264
254- - whether ``file_like`` is an an open file handle, or a path to a
265+ - whether ``self. file_like`` is an an open file handle, or a path to a
255266 ``'.gz'`` file, or a path to a non-gzip file.
256267 - whether ``indexed_gzip`` is present (see
257268 :attr:`.openers.HAVE_INDEXED_GZIP`).
@@ -270,24 +281,24 @@ def _should_keep_file_open(self, file_like, keep_file_open):
270281 and closed on each file access.
271282
272283 The internal ``_keep_file_open`` flag is only relevant if
273- ``file_like`` is a ``'.gz'`` file, and the ``indexed_gzip`` library is
284+ ``self. file_like`` is a ``'.gz'`` file, and the ``indexed_gzip`` library is
274285 present.
275286
276287 This method returns the values to be used for the internal
277288 ``_persist_opener`` and ``_keep_file_open`` flags; these values are
278289 derived according to the following rules:
279290
280- 1. If ``file_like`` is a file(-like) object, both flags are set to
291+ 1. If ``self. file_like`` is a file(-like) object, both flags are set to
281292 ``False``.
282293
283294 2. If ``keep_file_open`` (as passed to :meth:``__init__``) is
284295 ``True``, both internal flags are set to ``True``.
285296
286- 3. If ``keep_file_open`` is ``False``, but ``file_like`` is not a path
297+ 3. If ``keep_file_open`` is ``False``, but ``self. file_like`` is not a path
287298 to a ``.gz`` file or ``indexed_gzip`` is not present, both flags
288299 are set to ``False``.
289300
290- 4. If ``keep_file_open`` is ``False``, ``file_like`` is a path to a
301+ 4. If ``keep_file_open`` is ``False``, ``self. file_like`` is a path to a
291302 ``.gz`` file, and ``indexed_gzip`` is present, ``_persist_opener``
292303 is set to ``True``, and ``_keep_file_open`` is set to ``False``.
293304 In this case, file handle management is delegated to the
@@ -296,8 +307,6 @@ def _should_keep_file_open(self, file_like, keep_file_open):
296307 Parameters
297308 ----------
298309
299- file_like : object
300- File-like object or filename, as passed to ``__init__``.
301310 keep_file_open : { True, False }
302311 Flag as passed to ``__init__``.
303312
@@ -320,10 +329,10 @@ def _should_keep_file_open(self, file_like, keep_file_open):
320329 raise ValueError('keep_file_open must be one of {None, True, False}')
321330
322331 # file_like is a handle - keep_file_open is irrelevant
323- if hasattr(file_like, 'read') and hasattr(file_like, 'seek' ):
332+ if self._has_fh( ):
324333 return False, False
325334 # if the file is a gzip file, and we have_indexed_gzip,
326- have_igzip = openers.HAVE_INDEXED_GZIP and file_like.endswith('.gz')
335+ have_igzip = openers.HAVE_INDEXED_GZIP and self. file_like.endswith('.gz')
327336
328337 persist_opener = keep_file_open or have_igzip
329338 return keep_file_open, persist_opener
0 commit comments