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