Skip to content

Commit 867c280

Browse files
Merge pull request #1797 from zacharyburnett/deprecate/copy_arrays
deprecate `copy_arrays` with warning
2 parents ac7b6de + cd7d420 commit 867c280

File tree

13 files changed

+114
-90
lines changed

13 files changed

+114
-90
lines changed

CHANGES.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
to allow lazy deserialization of ASDF tagged tree nodes to
5656
custom objects. [#1733]
5757

58+
- Deprecate ``copy_arrays`` in favor of ``memmap`` [#1797]
5859

5960
3.2.0 (2024-04-05)
6061
------------------

README.rst

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,13 @@ The `open` function also works as a context handler:
185185
with asdf.open("example.asdf") as af:
186186
...
187187
188+
.. warning::
189+
The ``copy_arrays`` argument of `asdf.open()` and `AsdfFile` is deprecated,
190+
and will be removed in ASDF 4.0. It is replaced by ``memmap``, which
191+
is the opposite of ``copy_arrays`` (``memmap == not copy_arrays``).
192+
In ASDF 4.0, ``memmap`` will default to ``False``, which means arrays
193+
will no longer be memory-mapped by default.
194+
188195
To get a quick overview of the data stored in the file, use the top-level
189196
`AsdfFile.info()` method:
190197

@@ -245,12 +252,12 @@ Array data remains unloaded until it is explicitly accessed:
245252
True
246253
247254
By default, uncompressed data blocks are memory mapped for efficient
248-
access. Memory mapping can be disabled by using the ``copy_arrays``
255+
access. Memory mapping can be disabled by using the ``memmap``
249256
option of `open` when reading:
250257

251258
.. code:: python
252259
253-
af = asdf.open("example.asdf", copy_arrays=True)
260+
af = asdf.open("example.asdf", memmap=False)
254261
255262
.. _end-read-file-text:
256263

asdf/_asdf.py

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ def __init__(
7575
ignore_version_mismatch=True,
7676
ignore_unrecognized_tag=False,
7777
ignore_implicit_conversion=NotSet,
78-
copy_arrays=False,
78+
copy_arrays=NotSet,
7979
memmap=NotSet,
8080
lazy_load=True,
8181
custom_schema=None,
@@ -117,16 +117,15 @@ def __init__(
117117
as-is.
118118
119119
copy_arrays : bool, optional
120+
Deprecated; use ``memmap`` instead.
120121
When `False`, when reading files, attempt to memmap underlying data
121122
arrays when possible.
122123
123124
memmap : bool, optional
124125
When `True`, when reading files, attempt to memmap underlying data
125126
arrays when possible. When set, this argument will override
126-
``copy_arrays``. When not set, the ``copy_arrays`` will determine
127-
if arrays are memory mapped or copied. ``copy_arrays`` will be
128-
deprecated and the default will change in an upcoming asdf version
129-
which by default will not memory map arrays.
127+
``copy_arrays``. The default will change to ``False`` in an upcoming
128+
ASDF version. At the moment the default is ``True``.
130129
131130
lazy_load : bool, optional
132131
When `True` and the underlying file handle is seekable, data
@@ -135,8 +134,6 @@ def __init__(
135134
open during the lifetime of the tree. Setting to False causes
136135
all data arrays to be loaded up front, which means that they
137136
can be accessed even after the underlying file is closed.
138-
Note: even if ``lazy_load`` is `False`, ``copy_arrays`` is still taken
139-
into account.
140137
141138
custom_schema : str, optional
142139
Path to a custom schema file that will be used for a secondary
@@ -182,9 +179,16 @@ def __init__(
182179
self._closed = False
183180
self._external_asdf_by_uri = {}
184181
# if memmap is set, it overrides copy_arrays
185-
if memmap is not NotSet:
186-
copy_arrays = not memmap
187-
self._blocks = BlockManager(uri=uri, lazy_load=lazy_load, memmap=not copy_arrays)
182+
if copy_arrays is not NotSet:
183+
warnings.warn(
184+
"copy_arrays is deprecated; use memmap instead. Note that memmap will default to False in asdf 4.0.",
185+
AsdfWarning,
186+
)
187+
if memmap is NotSet:
188+
memmap = not copy_arrays
189+
elif memmap is NotSet:
190+
memmap = True
191+
self._blocks = BlockManager(uri=uri, lazy_load=lazy_load, memmap=memmap)
188192
# this message is passed into find_references to only warn if
189193
# a reference was found
190194
find_ref_warning_msg = (
@@ -1618,7 +1622,7 @@ def open_asdf(
16181622
ignore_version_mismatch=True,
16191623
ignore_unrecognized_tag=False,
16201624
_force_raw_types=False,
1621-
copy_arrays=False,
1625+
copy_arrays=NotSet,
16221626
memmap=NotSet,
16231627
lazy_tree=NotSet,
16241628
lazy_load=True,
@@ -1661,16 +1665,15 @@ def open_asdf(
16611665
`False` by default.
16621666
16631667
copy_arrays : bool, optional
1668+
Deprecated; use ``memmap`` instead.
16641669
When `False`, when reading files, attempt to memmap underlying data
16651670
arrays when possible.
16661671
16671672
memmap : bool, optional
16681673
When `True`, when reading files, attempt to memmap underlying data
16691674
arrays when possible. When set, this argument will override
1670-
``copy_arrays``. When not set, the ``copy_arrays`` will determine
1671-
if arrays are memory mapped or copied. ``copy_arrays`` will be
1672-
deprecated and the default will change in an upcoming asdf version
1673-
which by default will not memory map arrays.
1675+
``copy_arrays``. The default will change to ``False`` in an upcoming
1676+
ASDF version. At the moment the default is ``True``.
16741677
16751678
lazy_load : bool, optional
16761679
When `True` and the underlying file handle is seekable, data

asdf/_tests/_regtests/test_1334.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ def test_memmap_view_access_after_close(tmp_path):
1515
fn = tmp_path / "test.asdf"
1616
asdf.AsdfFile({"a": a}).write_to(fn)
1717

18-
with asdf.open(fn, copy_arrays=False) as af:
18+
with asdf.open(fn, memmap=True) as af:
1919
v = af["a"][:5]
2020

2121
assert np.all(v == 1)

asdf/_tests/_regtests/test_1525.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
import asdf
55

66

7-
@pytest.mark.parametrize("copy_arrays", [True, False])
8-
def test_external_blocks_always_lazy_loaded_and_memmapped(tmp_path, copy_arrays):
7+
@pytest.mark.parametrize("memmap", [True, False])
8+
def test_external_blocks_always_lazy_loaded_and_memmapped(tmp_path, memmap):
99
"""
1010
External blocks are always lazy loaded and memmapped
1111
@@ -18,13 +18,13 @@ def test_external_blocks_always_lazy_loaded_and_memmapped(tmp_path, copy_arrays)
1818
af.set_array_storage(arr, "external")
1919
af.write_to(fn)
2020

21-
with asdf.open(fn, copy_arrays=copy_arrays) as af:
21+
with asdf.open(fn, memmap=memmap) as af:
2222
# check that block is external
2323
source = af["arr"]._source
2424
assert isinstance(source, str)
2525

2626
# check if block is memmapped
27-
if copy_arrays:
27+
if not memmap:
2828
assert not isinstance(af["arr"].base, np.memmap)
2929
else:
3030
assert isinstance(af["arr"].base, np.memmap)

asdf/_tests/_regtests/test_1530.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ def test_update_with_memmapped_data_can_make_view_data_invalid(tmp_path):
2020
af = asdf.AsdfFile({"a": a, "b": b})
2121
af.write_to(fn)
2222

23-
with asdf.open(fn, mode="rw", copy_arrays=False) as af:
23+
with asdf.open(fn, mode="rw", memmap=True) as af:
2424
va = af["a"][:3]
2525
np.testing.assert_array_equal(a, af["a"])
2626
np.testing.assert_array_equal(b, af["b"])

asdf/_tests/_regtests/test_1558.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ def test_asdffile_tree_cleared_on_close(tmp_path):
1616
fn = tmp_path / "test.asdf"
1717
asdf.AsdfFile({"a": np.arange(1000), "b": np.arange(42)}).write_to(fn)
1818

19-
with asdf.open(fn, copy_arrays=True, lazy_load=False) as af:
19+
with asdf.open(fn, memmap=False, lazy_load=False) as af:
2020
array_weakref = weakref.ref(af["a"])
2121
array_ref = af["b"]
2222

asdf/_tests/tags/core/tests/test_ndarray.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -980,16 +980,16 @@ def test_memmap_write(tmp_path):
980980
# Make sure we're actually writing to an internal array for this test
981981
af.write_to(tmpfile, all_array_storage="internal")
982982

983-
with asdf.open(tmpfile, mode="rw", copy_arrays=False) as af:
983+
with asdf.open(tmpfile, mode="rw", memmap=True) as af:
984984
data = af["data"]
985985
assert data.flags.writeable is True
986986
data[0] = 42
987987
assert data[0] == 42
988988

989-
with asdf.open(tmpfile, mode="rw", copy_arrays=False) as af:
989+
with asdf.open(tmpfile, mode="rw", memmap=True) as af:
990990
assert af["data"][0] == 42
991991

992-
with asdf.open(tmpfile, mode="r", copy_arrays=False) as af:
992+
with asdf.open(tmpfile, mode="r", memmap=True) as af:
993993
assert af["data"][0] == 42
994994

995995

@@ -1008,7 +1008,7 @@ def test_readonly(tmp_path):
10081008
af["data"][0] = 41
10091009

10101010
# Forcing memmap, the array should still be readonly
1011-
with asdf.open(tmpfile, copy_arrays=False) as af:
1011+
with asdf.open(tmpfile, memmap=True) as af:
10121012
assert af["data"].flags.writeable is False
10131013
with pytest.raises(ValueError, match=r"assignment destination is read-only"):
10141014
af["data"][0] = 41
@@ -1019,7 +1019,7 @@ def test_readonly(tmp_path):
10191019
af["data"][0] = 40
10201020

10211021
# Copying the arrays makes it safe to write to the underlying array
1022-
with asdf.open(tmpfile, mode="r", copy_arrays=True) as af:
1022+
with asdf.open(tmpfile, mode="r", memmap=False) as af:
10231023
assert af["data"].flags.writeable is True
10241024
af["data"][0] = 42
10251025

asdf/_tests/test_api.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ def test_update_exceptions(tmp_path):
136136
ff.write_to(path)
137137

138138
with (
139-
asdf.open(path, mode="r", copy_arrays=True) as ff,
139+
asdf.open(path, mode="r", memmap=False) as ff,
140140
pytest.raises(
141141
IOError,
142142
match=r"Can not update, since associated file is read-only.*",
@@ -500,7 +500,7 @@ def test_array_access_after_file_close(tmp_path):
500500

501501
# With memory mapping disabled and copying arrays enabled,
502502
# the array data should still persist in memory after close:
503-
with asdf.open(path, lazy_load=False, copy_arrays=True) as af:
503+
with asdf.open(path, lazy_load=False, memmap=False) as af:
504504
tree = af.tree
505505
assert_array_equal(tree["data"], data)
506506

0 commit comments

Comments
 (0)