42
42
used for the lifetime of the ``ArrayProxy``. It should be set to one of
43
43
``True``, ``False``, or ``'auto'``.
44
44
45
- If ``True``, a single file handle is created and used. If ``False``, a new
46
- file handle is created every time the image is accessed. For gzip files, if
47
- ``'auto'``, and the optional ``indexed_gzip`` dependency is present, a single
48
- file handle is created and persisted. If ``indexed_gzip`` is not available,
49
- behaviour is the same as if ``keep_file_open is False``.
45
+ Management of file handles will be performed either by ``ArrayProxy`` objects,
46
+ or by the ``indexed_gzip`` package if it is used.
47
+
48
+ If this flag is set to ``True``, a single file handle is created and used. If
49
+ ``False``, a new file handle is created every time the image is accessed. For
50
+ gzip files, if ``'auto'``, and the optional ``indexed_gzip`` dependency is
51
+ present, a single file handle is created and persisted. If ``indexed_gzip`` is
52
+ not available, behaviour is the same as if ``keep_file_open is False``.
50
53
51
54
If this is set to any other value, attempts to create an ``ArrayProxy`` without
52
55
specifying the ``keep_file_open`` flag will result in a ``ValueError`` being
@@ -160,8 +163,10 @@ def __init__(self, file_like, spec, mmap=True, keep_file_open=None):
160
163
# Permit any specifier that can be interpreted as a numpy dtype
161
164
self ._dtype = np .dtype (self ._dtype )
162
165
self ._mmap = mmap
163
- self ._keep_file_open = self ._should_keep_file_open (file_like ,
164
- keep_file_open )
166
+ # Flags to keep track of whether a single ImageOpener is created, and
167
+ # whether a single underlying file handle is created.
168
+ self ._keep_file_open , self ._persist_opener = \
169
+ self ._should_keep_file_open (file_like , keep_file_open )
165
170
self ._lock = RLock ()
166
171
167
172
def __del__ (self ):
@@ -184,16 +189,64 @@ def __setstate__(self, state):
184
189
self ._lock = RLock ()
185
190
186
191
def _should_keep_file_open (self , file_like , keep_file_open ):
187
- """Called by ``__init__``, and used to determine the final value of
188
- ``keep_file_open``.
192
+ """Called by ``__init__``.
193
+
194
+ This method determines how to manage ``ImageOpener`` instances,
195
+ and the underlying file handles - the behaviour depends on:
196
+
197
+ - whether ``file_like`` is an an open file handle, or a path to a
198
+ ``'.gz'`` file, or a path to a non-gzip file.
199
+ - whether ``indexed_gzip`` is present (see
200
+ :attr:`.openers.HAVE_INDEXED_GZIP`).
201
+
202
+ An ``ArrayProxy`` object uses two internal flags to manage
203
+ ``ImageOpener`` instances and underlying file handles.
204
+
205
+ - The ``_persist_opener`` flag controls whether a single
206
+ ``ImageOpener`` should be created and used for the lifetime of
207
+ this ``ArrayProxy``, or whether separate ``ImageOpener`` instances
208
+ should be created on each file access.
209
+
210
+ - The ``_keep_file_open`` flag controls qwhether the underlying file
211
+ handle should be kept open for the lifetime of this
212
+ ``ArrayProxy``, or whether the file handle should be (re-)opened
213
+ and closed on each file access.
214
+
215
+ The internal ``_keep_file_open`` flag is only relevant if
216
+ ``file_like`` is a ``'.gz'`` file, and the ``indexed_gzip`` library is
217
+ present.
218
+
219
+ This method returns the values to be used for the internal
220
+ ``_persist_opener`` and ``_keep_file_open`` flags; these values are
221
+ derived according to the following rules:
189
222
190
- The return value is derived from these rules:
223
+ 1. If ``file_like`` is a file(-like) object, both flags are set to
224
+ ``False``.
191
225
192
- - If ``file_like`` is a file(-like) object, ``False`` is returned.
193
- Otherwise, ``file_like`` is assumed to be a file name.
194
- - If ``keep_file_open`` is ``auto``, and ``indexed_gzip`` is
195
- not available, ``False`` is returned.
196
- - Otherwise, the value of ``keep_file_open`` is returned unchanged.
226
+ 2. If ``keep_file_open`` (as passed to :meth:``__init__``) is
227
+ ``True``, both internal flags are set to ``True``.
228
+
229
+ 3. If ``keep_file_open`` is ``False``, but ``file_like`` is not a path
230
+ to a ``.gz`` file or ``indexed_gzip`` is not present, both flags
231
+ are set to ``False``.
232
+
233
+ 4. If ``keep_file_open`` is ``False``, ``file_like`` is a path to a
234
+ ``.gz`` file, and ``indexed_gzip`` is present, ``_persist_opener``
235
+ is set to ``True``, and ``_keep_file_open`` is set to ``False``.
236
+ In this case, file handle management is delegated to the
237
+ ``indexed_gzip`` library.
238
+
239
+ 5. If ``keep_file_open`` is ``'auto'``, ``file_like`` is a path to a
240
+ ``.gz`` file, and ``indexed_gzip`` is present, both internal flags
241
+ are set to ``True``.
242
+
243
+ 6. If ``keep_file_open`` is ``'auto'``, and ``file_like`` is not a
244
+ path to a ``.gz`` file, or ``indexed_gzip`` is not present, both
245
+ internal flags are set to ``False``.
246
+
247
+ Note that a value of ``'auto'`` for ``keep_file_open`` will become
248
+ deprecated behaviour in version 2.4.0, and support for ``'auto'`` will
249
+ be removed in version 3.0.0.
197
250
198
251
Parameters
199
252
----------
@@ -206,8 +259,10 @@ def _should_keep_file_open(self, file_like, keep_file_open):
206
259
Returns
207
260
-------
208
261
209
- The value of ``keep_file_open`` that will be used by this
210
- ``ArrayProxy``, and passed through to ``ImageOpener`` instances.
262
+ A tuple containing:
263
+ - ``keep_file_open`` flag to control persistence of file handles
264
+ - ``persist_opener`` flag to control persistence of ``ImageOpener``
265
+ objects.
211
266
"""
212
267
if keep_file_open is None :
213
268
keep_file_open = KEEP_FILE_OPEN_DEFAULT
@@ -216,12 +271,15 @@ def _should_keep_file_open(self, file_like, keep_file_open):
216
271
'\' auto\' , True, False}' )
217
272
# file_like is a handle - keep_file_open is irrelevant
218
273
if hasattr (file_like , 'read' ) and hasattr (file_like , 'seek' ):
219
- return False
220
- # don't have indexed_gzip - auto -> False
221
- if keep_file_open == 'auto' and not (openers .HAVE_INDEXED_GZIP and
222
- file_like .endswith ('.gz' )):
223
- return False
224
- return keep_file_open
274
+ return False , False
275
+ # if the file is a gzip file, and we have_indexed_gzip,
276
+ have_igzip = openers .HAVE_INDEXED_GZIP and file_like .endswith ('.gz' )
277
+ if keep_file_open == 'auto' :
278
+ return have_igzip , have_igzip
279
+ elif keep_file_open :
280
+ return True , True
281
+ else :
282
+ return False , have_igzip
225
283
226
284
@property
227
285
@deprecate_with_version ('ArrayProxy.header deprecated' , '2.2' , '3.0' )
@@ -232,6 +290,10 @@ def header(self):
232
290
def shape (self ):
233
291
return self ._shape
234
292
293
+ @property
294
+ def ndim (self ):
295
+ return len (self .shape )
296
+
235
297
@property
236
298
def dtype (self ):
237
299
return self ._dtype
@@ -265,13 +327,14 @@ def _get_fileobj(self):
265
327
A newly created ``ImageOpener`` instance, or an existing one,
266
328
which provides access to the file.
267
329
"""
268
- if self ._keep_file_open :
330
+ if self ._persist_opener :
269
331
if not hasattr (self , '_opener' ):
270
332
self ._opener = openers .ImageOpener (
271
333
self .file_like , keep_open = self ._keep_file_open )
272
334
yield self ._opener
273
335
else :
274
- with openers .ImageOpener (self .file_like ) as opener :
336
+ with openers .ImageOpener (
337
+ self .file_like , keep_open = False ) as opener :
275
338
yield opener
276
339
277
340
def get_unscaled (self ):
0 commit comments