bw-processing 0.9.6__tar.gz → 1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. {bw_processing-0.9.6/bw_processing.egg-info → bw_processing-1.0}/PKG-INFO +1 -1
  2. {bw_processing-0.9.6 → bw_processing-1.0}/bw_processing/__init__.py +1 -1
  3. {bw_processing-0.9.6 → bw_processing-1.0}/bw_processing/constants.py +2 -1
  4. {bw_processing-0.9.6 → bw_processing-1.0}/bw_processing/datapackage.py +9 -0
  5. {bw_processing-0.9.6 → bw_processing-1.0/bw_processing.egg-info}/PKG-INFO +1 -1
  6. {bw_processing-0.9.6 → bw_processing-1.0}/bw_processing.egg-info/SOURCES.txt +13 -20
  7. bw_processing-1.0/tests/test_array_creation.py +14 -0
  8. bw_processing-1.0/tests/test_datapackage.py +499 -0
  9. bw_processing-1.0/tests/test_filesystem.py +33 -0
  10. bw_processing-1.0/tests/test_filtered_datapackage.py +151 -0
  11. bw_processing-1.0/tests/test_indexing.py +384 -0
  12. bw_processing-1.0/tests/test_integration.py +472 -0
  13. bw_processing-1.0/tests/test_interfaces.py +113 -0
  14. bw_processing-1.0/tests/test_io_parquet_helpers.py +155 -0
  15. bw_processing-1.0/tests/test_io_pyarrow_helpers.py +66 -0
  16. bw_processing-1.0/tests/test_loading.py +64 -0
  17. bw_processing-1.0/tests/test_merging.py +369 -0
  18. bw_processing-1.0/tests/test_proxies.py +27 -0
  19. bw_processing-1.0/tests/test_unique_fields.py +139 -0
  20. bw_processing-0.9.6/dev/calculation_package.py +0 -179
  21. bw_processing-0.9.6/dev/loading.py +0 -85
  22. bw_processing-0.9.6/dev/processed_package.py +0 -261
  23. bw_processing-0.9.6/dev/resources.py +0 -32
  24. bw_processing-0.9.6/dev/speed_tests.py +0 -47
  25. bw_processing-0.9.6/docs/conf.py +0 -109
  26. {bw_processing-0.9.6 → bw_processing-1.0}/LICENSE +0 -0
  27. {bw_processing-0.9.6 → bw_processing-1.0}/MANIFEST.in +0 -0
  28. {bw_processing-0.9.6 → bw_processing-1.0}/README.md +0 -0
  29. {bw_processing-0.9.6 → bw_processing-1.0}/bw_processing/array_creation.py +0 -0
  30. {bw_processing-0.9.6 → bw_processing-1.0}/bw_processing/errors.py +0 -0
  31. {bw_processing-0.9.6 → bw_processing-1.0}/bw_processing/examples/__init__.py +0 -0
  32. {bw_processing-0.9.6 → bw_processing-1.0}/bw_processing/examples/datapackage_1/another name.indices.parquet +0 -0
  33. {bw_processing-0.9.6 → bw_processing-1.0}/bw_processing/examples/datapackage_1/sa-data-vector-from-dict.data.parquet +0 -0
  34. {bw_processing-0.9.6 → bw_processing-1.0}/bw_processing/examples/datapackage_1/sa-data-vector-from-dict.distributions.parquet +0 -0
  35. {bw_processing-0.9.6 → bw_processing-1.0}/bw_processing/examples/datapackage_1/sa-data-vector-from-dict.flip.parquet +0 -0
  36. {bw_processing-0.9.6 → bw_processing-1.0}/bw_processing/examples/datapackage_1/sa-data-vector-from-dict.indices.parquet +0 -0
  37. {bw_processing-0.9.6 → bw_processing-1.0}/bw_processing/examples/datapackage_1/some name.data.parquet +0 -0
  38. {bw_processing-0.9.6 → bw_processing-1.0}/bw_processing/examples/datapackage_1/some name.flip.parquet +0 -0
  39. {bw_processing-0.9.6 → bw_processing-1.0}/bw_processing/examples/datapackage_1/some name.indices.parquet +0 -0
  40. {bw_processing-0.9.6 → bw_processing-1.0}/bw_processing/examples/datapackage_2.zip +0 -0
  41. {bw_processing-0.9.6 → bw_processing-1.0}/bw_processing/examples/interfaces.py +0 -0
  42. {bw_processing-0.9.6 → bw_processing-1.0}/bw_processing/examples/parquet_files.py +0 -0
  43. {bw_processing-0.9.6 → bw_processing-1.0}/bw_processing/examples/simple.zip +0 -0
  44. {bw_processing-0.9.6 → bw_processing-1.0}/bw_processing/filesystem.py +0 -0
  45. {bw_processing-0.9.6 → bw_processing-1.0}/bw_processing/indexing.py +0 -0
  46. {bw_processing-0.9.6 → bw_processing-1.0}/bw_processing/io_helpers.py +0 -0
  47. {bw_processing-0.9.6 → bw_processing-1.0}/bw_processing/io_parquet_helpers.py +0 -0
  48. {bw_processing-0.9.6 → bw_processing-1.0}/bw_processing/io_pyarrow_helpers.py +0 -0
  49. {bw_processing-0.9.6 → bw_processing-1.0}/bw_processing/merging.py +0 -0
  50. {bw_processing-0.9.6 → bw_processing-1.0}/bw_processing/proxies.py +0 -0
  51. {bw_processing-0.9.6 → bw_processing-1.0}/bw_processing/unique_fields.py +0 -0
  52. {bw_processing-0.9.6 → bw_processing-1.0}/bw_processing/utils.py +0 -0
  53. {bw_processing-0.9.6 → bw_processing-1.0}/bw_processing.egg-info/dependency_links.txt +0 -0
  54. {bw_processing-0.9.6 → bw_processing-1.0}/bw_processing.egg-info/requires.txt +0 -0
  55. {bw_processing-0.9.6 → bw_processing-1.0}/bw_processing.egg-info/top_level.txt +0 -0
  56. {bw_processing-0.9.6 → bw_processing-1.0}/pyproject.toml +0 -0
  57. {bw_processing-0.9.6 → bw_processing-1.0}/setup.cfg +0 -0
  58. {bw_processing-0.9.6 → bw_processing-1.0}/tests/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: bw_processing
3
- Version: 0.9.6
3
+ Version: 1.0
4
4
  Summary: Foo
5
5
  Author-email: Chris Mutel <cmutel@gmail.com>
6
6
  Maintainer-email: Chris Mutel <cmutel@gmail.com>
@@ -26,7 +26,7 @@ __all__ = (
26
26
  "UndefinedInterface",
27
27
  )
28
28
 
29
- __version__ = "0.9.6"
29
+ __version__ = "1.0"
30
30
 
31
31
 
32
32
  from .array_creation import create_array, create_structured_array
@@ -4,6 +4,7 @@ from enum import Enum
4
4
  import numpy as np
5
5
 
6
6
  MAX_SIGNED_32BIT_INT = 2147483647
7
+ MAX_SIGNED_64BIT_INT = 9223372036854775807
7
8
 
8
9
  # We could try to save space by not storing the columns
9
10
  # `row_index` and `col_index`, and add them after loading from
@@ -20,7 +21,7 @@ UNCERTAINTY_DTYPE = [
20
21
  ("maximum", np.float32),
21
22
  ("negative", bool),
22
23
  ]
23
- INDICES_DTYPE = [("row", np.int32), ("col", np.int32)]
24
+ INDICES_DTYPE = [("row", np.int64), ("col", np.int64)]
24
25
 
25
26
  NAME_RE = re.compile(r"^[\w\-\.]*$")
26
27
 
@@ -14,6 +14,8 @@ from morefs.dict import DictFS
14
14
  from .constants import (
15
15
  DEFAULT_LICENSES,
16
16
  INDICES_DTYPE,
17
+ MAX_SIGNED_32BIT_INT,
18
+ MAX_SIGNED_64BIT_INT,
17
19
  NUMPY_SERIALIZE_FORMAT_EXTENSION,
18
20
  NUMPY_SERIALIZE_FORMAT_NAME,
19
21
  PARQUET_SERIALIZE_FORMAT_EXTENSION,
@@ -257,6 +259,12 @@ class DatapackageBase(ABC):
257
259
 
258
260
  self.data[index] = resource
259
261
 
262
+ def get_max_index_value(self) -> int:
263
+ """Get maximum index value (max signed 32 or 64 bit integer) for this datapackage"""
264
+ if self.metadata.get("64_bit_indices"):
265
+ return MAX_SIGNED_64BIT_INT
266
+ return MAX_SIGNED_32BIT_INT
267
+
260
268
 
261
269
  class FilteredDatapackage(DatapackageBase):
262
270
  """A subset of a datapackage. Used in matrix construction or other data manipulation operations.
@@ -360,6 +368,7 @@ class Datapackage(DatapackageBase):
360
368
  "combinatorial": combinatorial,
361
369
  "sequential": sequential,
362
370
  "seed": seed,
371
+ "64_bit_indices": True,
363
372
  "sum_intra_duplicates": sum_intra_duplicates,
364
373
  "sum_inter_duplicates": sum_inter_duplicates,
365
374
  "matrix_serialize_format_type": matrix_serialize_format_type.value,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: bw_processing
3
- Version: 0.9.6
3
+ Version: 1.0
4
4
  Summary: Foo
5
5
  Author-email: Chris Mutel <cmutel@gmail.com>
6
6
  Maintainer-email: Chris Mutel <cmutel@gmail.com>
@@ -2,26 +2,6 @@ LICENSE
2
2
  MANIFEST.in
3
3
  README.md
4
4
  pyproject.toml
5
- ./bw_processing/__init__.py
6
- ./bw_processing/array_creation.py
7
- ./bw_processing/constants.py
8
- ./bw_processing/datapackage.py
9
- ./bw_processing/errors.py
10
- ./bw_processing/filesystem.py
11
- ./bw_processing/indexing.py
12
- ./bw_processing/io_helpers.py
13
- ./bw_processing/merging.py
14
- ./bw_processing/proxies.py
15
- ./bw_processing/unique_fields.py
16
- ./bw_processing/utils.py
17
- ./bw_processing/examples/__init__.py
18
- ./bw_processing/examples/interfaces.py
19
- ./dev/calculation_package.py
20
- ./dev/loading.py
21
- ./dev/processed_package.py
22
- ./dev/resources.py
23
- ./dev/speed_tests.py
24
- ./docs/conf.py
25
5
  bw_processing/__init__.py
26
6
  bw_processing/array_creation.py
27
7
  bw_processing/constants.py
@@ -54,4 +34,17 @@ bw_processing/examples/datapackage_1/sa-data-vector-from-dict.indices.parquet
54
34
  bw_processing/examples/datapackage_1/some name.data.parquet
55
35
  bw_processing/examples/datapackage_1/some name.flip.parquet
56
36
  bw_processing/examples/datapackage_1/some name.indices.parquet
37
+ tests/test_array_creation.py
38
+ tests/test_datapackage.py
39
+ tests/test_filesystem.py
40
+ tests/test_filtered_datapackage.py
41
+ tests/test_indexing.py
42
+ tests/test_integration.py
43
+ tests/test_interfaces.py
44
+ tests/test_io_parquet_helpers.py
45
+ tests/test_io_pyarrow_helpers.py
46
+ tests/test_loading.py
47
+ tests/test_merging.py
48
+ tests/test_proxies.py
49
+ tests/test_unique_fields.py
57
50
  tests/test_utils.py
@@ -0,0 +1,14 @@
1
+ from bw_processing.array_creation import chunked
2
+
3
+
4
+ def test_chunked():
5
+ c = chunked(range(600), 250)
6
+ for x in next(c):
7
+ pass
8
+ assert x == 249
9
+ for x in next(c):
10
+ pass
11
+ assert x == 499
12
+ for x in next(c):
13
+ pass
14
+ assert x == 599
@@ -0,0 +1,499 @@
1
+ import shutil
2
+ from pathlib import Path
3
+
4
+ import numpy as np
5
+ import pandas as pd
6
+ import pytest
7
+ from fsspec.implementations.zip import ZipFileSystem
8
+ from morefs.dict import DictFS
9
+
10
+ from bw_processing import create_datapackage, load_datapackage, simple_graph
11
+ from bw_processing.constants import INDICES_DTYPE, UNCERTAINTY_DTYPE, MAX_SIGNED_64BIT_INT, MAX_SIGNED_32BIT_INT
12
+ from bw_processing.errors import NonUnique, PotentialInconsistency, ShapeMismatch, WrongDatatype
13
+ from bw_processing.io_helpers import generic_directory_filesystem
14
+
15
+ dirpath = Path(__file__).parent.resolve() / "fixtures"
16
+
17
+
18
+ class Dummy:
19
+ pass
20
+
21
+
22
+ def add_data(dp):
23
+ data_array = np.array([2, 7, 12])
24
+ indices_array = np.array([(1, 4), (2, 5), (3, 6)], dtype=INDICES_DTYPE)
25
+ flip_array = np.array([1, 0, 0], dtype=bool)
26
+ dp.add_persistent_vector(
27
+ matrix="sa_matrix",
28
+ data_array=data_array,
29
+ name="sa-data-vector",
30
+ indices_array=indices_array,
31
+ nrows=2,
32
+ flip_array=flip_array,
33
+ )
34
+
35
+ json_data = [{"a": "b"}, 1, True]
36
+ df = pd.DataFrame(
37
+ [
38
+ {"id": 1, "a": 1, "c": 3, "d": 11},
39
+ {"id": 2, "a": 2, "c": 4, "d": 11},
40
+ {"id": 3, "a": 1, "c": 4, "d": 11},
41
+ ]
42
+ ).set_index(["id"])
43
+
44
+ dp.add_persistent_array(
45
+ matrix="sa_matrix",
46
+ data_array=np.arange(12).reshape((3, 4)),
47
+ indices_array=indices_array,
48
+ name="sa-data-array",
49
+ flip_array=flip_array,
50
+ )
51
+
52
+ dp.add_dynamic_vector(
53
+ interface=Dummy(),
54
+ indices_array=indices_array,
55
+ matrix="sa_matrix",
56
+ name="sa-vector-interface",
57
+ )
58
+
59
+ dp.add_dynamic_array(
60
+ interface=Dummy(),
61
+ matrix="sa_matrix",
62
+ name="sa-array-interface",
63
+ indices_array=indices_array,
64
+ )
65
+ dp.add_csv_metadata(
66
+ dataframe=df,
67
+ valid_for=[("sa-data-vector", "rows")],
68
+ name="sa-data-vector-csv-metadata",
69
+ )
70
+ dp.add_json_metadata(
71
+ data=json_data, valid_for="sa-data-array", name="sa-data-array-json-metadata"
72
+ )
73
+
74
+
75
+ def copy_fixture(fixture_name, dest):
76
+ source = Path(__file__).parent.resolve() / "fixtures" / fixture_name
77
+ for fp in source.iterdir():
78
+ shutil.copy(fp, dest / fp.name)
79
+
80
+
81
+ def test_group_ordering_consistent():
82
+ dp = load_datapackage(ZipFileSystem(dirpath / "test-fixture.zip"))
83
+ assert list(dp.groups) == [
84
+ "sa-data-vector-from-dict",
85
+ "sa-data-vector",
86
+ "sa-data-array",
87
+ "sa-vector-interface",
88
+ "sa-array-interface",
89
+ ]
90
+
91
+
92
+ def test_get_max_index_value():
93
+ dp = load_datapackage(ZipFileSystem(dirpath / "test-fixture.zip"))
94
+ assert dp.metadata.get("64_bit_indices")
95
+ assert dp.get_max_index_value() == MAX_SIGNED_64BIT_INT
96
+
97
+ dp = load_datapackage(ZipFileSystem(dirpath / "test-fixture-32bit.zip"))
98
+ assert not dp.metadata.get("64_bit_indices")
99
+ assert dp.get_max_index_value() == MAX_SIGNED_32BIT_INT
100
+
101
+
102
+ def test_add_resource_with_same_name():
103
+ dp = create_datapackage()
104
+ add_data(dp)
105
+
106
+ data_array = np.array([2, 7, 12])
107
+ indices_array = np.array([(1, 4), (2, 5), (3, 6)], dtype=INDICES_DTYPE)
108
+ with pytest.raises(NonUnique):
109
+ dp.add_persistent_vector(
110
+ matrix="sa_matrix",
111
+ data_array=data_array,
112
+ name="sa-data-vector",
113
+ indices_array=indices_array,
114
+ )
115
+
116
+
117
+ def test_save_modifications(tmp_path):
118
+ copy_fixture("tfd", tmp_path)
119
+ dp = load_datapackage(generic_directory_filesystem(dirpath=tmp_path))
120
+
121
+ assert dp.resources[1]["name"] == "sa-data-vector-from-dict.data"
122
+ assert np.allclose(dp.data[1], [3.3, 8.3])
123
+
124
+ dp.data[1][:] = 42
125
+ dp._modified = [1]
126
+ dp.write_modified()
127
+
128
+ assert np.allclose(dp.data[1], 42)
129
+ assert not dp._modified
130
+
131
+ dp = load_datapackage(generic_directory_filesystem(dirpath=tmp_path))
132
+ assert np.allclose(dp.data[1], 42)
133
+
134
+
135
+ def test_del_resource_filesystem(tmp_path):
136
+ copy_fixture("tfd", tmp_path)
137
+ dp = load_datapackage(generic_directory_filesystem(dirpath=tmp_path))
138
+ reference_length = len(dp)
139
+ assert "sa-vector-interface.indices.npy" in [o.name for o in tmp_path.iterdir()]
140
+ dp.del_resource("sa-vector-interface.indices")
141
+ assert "sa-vector-interface.indices.npy" not in [o.name for o in tmp_path.iterdir()]
142
+ assert len(dp) == reference_length - 1
143
+ assert len(dp.data) == reference_length - 1
144
+ assert len(dp.metadata["resources"]) == reference_length - 1
145
+ assert len(dp.resources) == reference_length - 1
146
+
147
+
148
+ def test_del_resource_in_memory():
149
+ dp = create_datapackage()
150
+ add_data(dp)
151
+ assert isinstance(dp.fs, DictFS)
152
+
153
+ reference_length = len(dp)
154
+ assert "sa-vector-interface.indices" in [o["name"] for o in dp.resources]
155
+ dp.del_resource("sa-vector-interface.indices")
156
+ assert "sa-vector-interface.indices" not in [o["name"] for o in dp.resources]
157
+ assert len(dp) == reference_length - 1
158
+ assert len(dp.data) == reference_length - 1
159
+ assert len(dp.metadata["resources"]) == reference_length - 1
160
+ assert len(dp.resources) == reference_length - 1
161
+
162
+
163
+ def test_del_resource_error_modifications(tmp_path):
164
+ copy_fixture("tfd", tmp_path)
165
+ dp = load_datapackage(generic_directory_filesystem(dirpath=tmp_path))
166
+ dp._modified = [1]
167
+ with pytest.raises(PotentialInconsistency):
168
+ dp.del_resource(1)
169
+
170
+
171
+ def test_del_resource_group_filesystem(tmp_path):
172
+ copy_fixture("tfd", tmp_path)
173
+ dp = load_datapackage(generic_directory_filesystem(dirpath=tmp_path))
174
+
175
+ reference_length = len(dp)
176
+ assert "sa-data-vector.indices.npy" in [o.name for o in tmp_path.iterdir()]
177
+ dp.del_resource_group("sa-data-vector")
178
+ assert "sa-data-vector.indices.npy" not in [o.name for o in tmp_path.iterdir()]
179
+ assert len(dp) == reference_length - 3
180
+ assert len(dp.data) == reference_length - 3
181
+ assert len(dp.metadata["resources"]) == reference_length - 3
182
+ assert len(dp.resources) == reference_length - 3
183
+
184
+
185
+ def test_del_resource_group_in_memory():
186
+ dp = create_datapackage()
187
+ add_data(dp)
188
+ assert isinstance(dp.fs, DictFS)
189
+
190
+ reference_length = len(dp)
191
+ assert "sa-data-vector.indices" in [o["name"] for o in dp.resources]
192
+ dp.del_resource_group("sa-data-vector")
193
+ assert "sa-data-vector.indices" not in [o["name"] for o in dp.resources]
194
+ assert len(dp) == reference_length - 3
195
+ assert len(dp.data) == reference_length - 3
196
+ assert len(dp.metadata["resources"]) == reference_length - 3
197
+ assert len(dp.resources) == reference_length - 3
198
+
199
+
200
+ def test_del_resource_group_error_modifications(tmp_path):
201
+ copy_fixture("tfd", tmp_path)
202
+ dp = load_datapackage(generic_directory_filesystem(dirpath=tmp_path))
203
+ dp._modified = [1]
204
+ with pytest.raises(PotentialInconsistency):
205
+ dp.del_resource_group("sa-vector-interface")
206
+
207
+
208
+ def test_exclude_basic():
209
+ dp = create_datapackage()
210
+ add_data(dp)
211
+ assert isinstance(dp.fs, DictFS)
212
+
213
+ reference_length = len(dp)
214
+ assert "sa-data-vector.indices" in [o["name"] for o in dp.resources]
215
+ ndp = dp.exclude({"group": "sa-data-vector"})
216
+ assert ndp is not dp
217
+ assert "sa-data-vector.indices" in [o["name"] for o in dp.resources]
218
+ assert "sa-data-vector.indices" not in [o["name"] for o in ndp.resources]
219
+ assert len(ndp) == reference_length - 3
220
+ assert len(ndp.data) == reference_length - 3
221
+ assert len(ndp.metadata["resources"]) == reference_length - 3
222
+ assert len(ndp.resources) == reference_length - 3
223
+
224
+
225
+ def test_exclude_no_match():
226
+ dp = create_datapackage()
227
+ add_data(dp)
228
+ assert isinstance(dp.fs, DictFS)
229
+
230
+ reference_length = len(dp)
231
+ assert "sa-data-vector.indices" in [o["name"] for o in dp.resources]
232
+ ndp = dp.exclude({"foo": "bar"})
233
+ assert ndp is not dp
234
+ assert "sa-data-vector.indices" in [o["name"] for o in dp.resources]
235
+ assert "sa-data-vector.indices" in [o["name"] for o in ndp.resources]
236
+ assert len(ndp) == reference_length
237
+
238
+
239
+ def test_exclude_multiple_filters():
240
+ dp = create_datapackage()
241
+ add_data(dp)
242
+ assert isinstance(dp.fs, DictFS)
243
+
244
+ reference_length = len(dp)
245
+ assert "sa-array-interface.indices" in [o["name"] for o in dp.resources]
246
+ ndp = dp.exclude({"group": "sa-array-interface", "matrix": "sa_matrix"})
247
+ assert ndp is not dp
248
+ assert "sa-array-interface.indices" in [o["name"] for o in dp.resources]
249
+ assert "sa-array-interface.indices" not in [o["name"] for o in ndp.resources]
250
+ assert len(ndp) == reference_length - 2
251
+ assert len(ndp.data) == reference_length - 2
252
+ assert len(ndp.metadata["resources"]) == reference_length - 2
253
+ assert len(ndp.resources) == reference_length - 2
254
+
255
+
256
+ def test_exclude_multiple_matrix():
257
+ dp = create_datapackage()
258
+ add_data(dp)
259
+ assert isinstance(dp.fs, DictFS)
260
+
261
+ assert "sa-data-vector.indices" in [o["name"] for o in dp.resources]
262
+ ndp = dp.exclude({"matrix": "sa_matrix"})
263
+ assert ndp is not dp
264
+ assert "sa-data-vector.indices" in [o["name"] for o in dp.resources]
265
+ assert "sa-data-vector.indices" not in [o["name"] for o in ndp.resources]
266
+ assert len(ndp) == 2
267
+ assert len(ndp.data) == 2
268
+ assert len(ndp.metadata["resources"]) == 2
269
+ assert len(ndp.resources) == 2
270
+
271
+
272
+ def test_add_persistent_vector_data_shapemismatch_ndimensions():
273
+ dp = create_datapackage()
274
+ data_array = np.array([[2, 7, 12], [4, 5, 15]])
275
+ indices_array = np.array([(1, 4), (2, 5), (3, 6)], dtype=INDICES_DTYPE)
276
+ with pytest.raises(ShapeMismatch):
277
+ dp.add_persistent_vector(
278
+ matrix="sa_matrix",
279
+ data_array=data_array,
280
+ name="sa-data-vector",
281
+ indices_array=indices_array,
282
+ )
283
+
284
+
285
+ def test_add_persistent_vector_data_shapemismatch_nrows():
286
+ dp = create_datapackage()
287
+ data_array = np.array([2, 7, 12, 15])
288
+ indices_array = np.array([(1, 4), (2, 5), (3, 6)], dtype=INDICES_DTYPE)
289
+ with pytest.raises(ShapeMismatch):
290
+ dp.add_persistent_vector(
291
+ matrix="sa_matrix",
292
+ data_array=data_array,
293
+ name="sa-data-vector",
294
+ indices_array=indices_array,
295
+ )
296
+
297
+
298
+ def test_add_persistent_vector_distributions_shapemismatch():
299
+ dp = create_datapackage()
300
+ distributions_array = np.array(
301
+ [
302
+ (3, 1.3, 2.5, np.nan, np.nan, np.nan, False),
303
+ (0, 1.3, 2.5, np.nan, np.nan, np.nan, False),
304
+ ],
305
+ dtype=UNCERTAINTY_DTYPE,
306
+ )
307
+ indices_array = np.array([(1, 4), (2, 5), (3, 6)], dtype=INDICES_DTYPE)
308
+ with pytest.raises(ShapeMismatch):
309
+ dp.add_persistent_vector(
310
+ matrix="sa_matrix",
311
+ distributions_array=distributions_array,
312
+ name="sa-data-vector",
313
+ indices_array=indices_array,
314
+ )
315
+
316
+
317
+ def test_add_persistent_vector_flip_dtype():
318
+ dp = create_datapackage()
319
+ data_array = np.array([2, 7, 12])
320
+ flip_array = np.array([0, 1, 0])
321
+ indices_array = np.array([(1, 4), (2, 5), (3, 6)], dtype=INDICES_DTYPE)
322
+ with pytest.raises(WrongDatatype):
323
+ dp.add_persistent_vector(
324
+ matrix="sa_matrix",
325
+ data_array=data_array,
326
+ name="sa-data-vector",
327
+ flip_array=flip_array,
328
+ indices_array=indices_array,
329
+ )
330
+
331
+
332
+ def test_add_persistent_vector_flip_shapemistmatch():
333
+ dp = create_datapackage()
334
+ data_array = np.array([2, 7, 12])
335
+ flip_array = np.array([0, 1, 0, 1], dtype=bool)
336
+ indices_array = np.array([(1, 4), (2, 5), (3, 6)], dtype=ShapeMismatch)
337
+ with pytest.raises(ShapeMismatch):
338
+ dp.add_persistent_vector(
339
+ matrix="sa_matrix",
340
+ data_array=data_array,
341
+ name="sa-data-vector",
342
+ flip_array=flip_array,
343
+ indices_array=indices_array,
344
+ )
345
+
346
+
347
+ def test_add_persistent_array_data_shapemismatch_ndimensions():
348
+ dp = create_datapackage()
349
+ data_array = np.array([2, 7, 12])
350
+ indices_array = np.array([(1, 4), (2, 5), (3, 6)], dtype=INDICES_DTYPE)
351
+ with pytest.raises(ShapeMismatch):
352
+ dp.add_persistent_array(
353
+ matrix="sa_matrix",
354
+ data_array=data_array,
355
+ name="sa-data-vector",
356
+ indices_array=indices_array,
357
+ )
358
+
359
+
360
+ def test_add_persistent_array_data_shapemismatch_nrows():
361
+ dp = create_datapackage()
362
+ data_array = np.arange(12).reshape(4, 3)
363
+ indices_array = np.array([(1, 4), (2, 5), (3, 6)], dtype=INDICES_DTYPE)
364
+ with pytest.raises(ShapeMismatch):
365
+ dp.add_persistent_array(
366
+ matrix="sa_matrix",
367
+ data_array=data_array,
368
+ name="sa-data-vector",
369
+ indices_array=indices_array,
370
+ )
371
+
372
+
373
+ def test_add_persistent_array_flip_dtype():
374
+ dp = create_datapackage()
375
+ data_array = np.arange(12).reshape(3, 4)
376
+ flip_array = np.array([0, 1, 0])
377
+ indices_array = np.array([(1, 4), (2, 5), (3, 6)], dtype=INDICES_DTYPE)
378
+ with pytest.raises(WrongDatatype):
379
+ dp.add_persistent_array(
380
+ matrix="sa_matrix",
381
+ data_array=data_array,
382
+ name="sa-data-vector",
383
+ flip_array=flip_array,
384
+ indices_array=indices_array,
385
+ )
386
+
387
+
388
+ def test_add_persistent_array_flip_shapemistmatch():
389
+ dp = create_datapackage()
390
+ data_array = np.arange(12).reshape(3, 4)
391
+ flip_array = np.array([0, 1, 0, 1], dtype=bool)
392
+ indices_array = np.array([(1, 4), (2, 5), (3, 6)], dtype=ShapeMismatch)
393
+ with pytest.raises(ShapeMismatch):
394
+ dp.add_persistent_array(
395
+ matrix="sa_matrix",
396
+ data_array=data_array,
397
+ name="sa-data-vector",
398
+ flip_array=flip_array,
399
+ indices_array=indices_array,
400
+ )
401
+
402
+
403
+ def test_add_dynamic_array_flip_dtype():
404
+ dp = create_datapackage()
405
+ flip_array = np.array([0, 1, 0])
406
+ indices_array = np.array([(1, 4), (2, 5), (3, 6)], dtype=INDICES_DTYPE)
407
+ with pytest.raises(WrongDatatype):
408
+ dp.add_dynamic_array(
409
+ matrix="sa_matrix",
410
+ interface=Dummy(),
411
+ name="sa-data-vector",
412
+ flip_array=flip_array,
413
+ indices_array=indices_array,
414
+ )
415
+
416
+
417
+ def test_add_dynamic_array_flip_shapemistmatch():
418
+ dp = create_datapackage()
419
+ flip_array = np.array([0, 1, 0, 1], dtype=bool)
420
+ indices_array = np.array([(1, 4), (2, 5), (3, 6)], dtype=ShapeMismatch)
421
+ with pytest.raises(ShapeMismatch):
422
+ dp.add_dynamic_array(
423
+ matrix="sa_matrix",
424
+ interface=Dummy(),
425
+ name="sa-data-vector",
426
+ flip_array=flip_array,
427
+ indices_array=indices_array,
428
+ )
429
+
430
+
431
+ def test_add_dynamic_vector_flip_dtype():
432
+ dp = create_datapackage()
433
+ flip_array = np.array([0, 1, 0])
434
+ indices_array = np.array([(1, 4), (2, 5), (3, 6)], dtype=INDICES_DTYPE)
435
+ with pytest.raises(WrongDatatype):
436
+ dp.add_dynamic_vector(
437
+ matrix="sa_matrix",
438
+ interface=Dummy(),
439
+ name="sa-data-vector",
440
+ flip_array=flip_array,
441
+ indices_array=indices_array,
442
+ )
443
+
444
+
445
+ def test_add_dynamic_vector_flip_shapemistmatch():
446
+ dp = create_datapackage()
447
+ flip_array = np.array([0, 1, 0, 1], dtype=bool)
448
+ indices_array = np.array([(1, 4), (2, 5), (3, 6)], dtype=ShapeMismatch)
449
+ with pytest.raises(ShapeMismatch):
450
+ dp.add_dynamic_vector(
451
+ matrix="sa_matrix",
452
+ interface=Dummy(),
453
+ name="sa-data-vector",
454
+ flip_array=flip_array,
455
+ indices_array=indices_array,
456
+ )
457
+
458
+
459
+ def test_simple_graph():
460
+ data = {
461
+ "some_matrix": [(1, 2, 3.14), (4, 5, 17, True), (8, 9, 11.11, False)],
462
+ "a different life": [
463
+ (99, 100, 101.234, False, "ignored"),
464
+ (1001, 1002, 777, 1),
465
+ ],
466
+ }
467
+ expected_resource = {
468
+ "category": "vector",
469
+ "profile": "data-resource",
470
+ "format": "npy",
471
+ "mediatype": "application/octet-stream",
472
+ "name": "some_matrix-data.flip",
473
+ "matrix": "some_matrix",
474
+ "kind": "flip",
475
+ "nrows": 3,
476
+ "path": "some_matrix-data.flip.npy",
477
+ "group": "some_matrix-data",
478
+ }
479
+ dp = simple_graph(data, name="foo", sequential=True)
480
+ assert dp.metadata["name"] == "foo"
481
+ assert dp.metadata["sequential"]
482
+ assert len(dp.metadata["resources"]) == 6
483
+ assert expected_resource in dp.metadata["resources"]
484
+
485
+ d, _ = dp.get_resource("some_matrix-data.flip")
486
+ assert np.allclose(d, np.array([False, True, False]))
487
+ d, _ = dp.get_resource("some_matrix-data.indices")
488
+ assert d["row"].sum() == 13
489
+ assert d["col"].sum() == 16
490
+ d, _ = dp.get_resource("some_matrix-data.data")
491
+ assert np.allclose(d, np.array([3.14, 17, 11.11]))
492
+
493
+ d, _ = dp.get_resource("a different life-data.flip")
494
+ assert np.allclose(d, np.array([False, True]))
495
+ d, _ = dp.get_resource("a different life-data.indices")
496
+ assert d["row"].sum() == 1100
497
+ assert d["col"].sum() == 1102
498
+ d, _ = dp.get_resource("a different life-data.data")
499
+ assert np.allclose(d, np.array([101.234, 777]))
@@ -0,0 +1,33 @@
1
+ import platform
2
+ from pathlib import Path
3
+
4
+ import pytest
5
+
6
+ from bw_processing.filesystem import clean_datapackage_name, md5, safe_filename
7
+
8
+ fixtures_dir = Path(__file__, "..").resolve() / "fixtures"
9
+ _windows = platform.system() == "Windows"
10
+
11
+
12
+ @pytest.mark.skipif(_windows, reason="Different line encodings on Windows")
13
+ def test_md5_text():
14
+ assert md5(fixtures_dir / "lorem.txt") == "edc715389af2498a623134608ba0a55b"
15
+
16
+
17
+ def test_md5_binary():
18
+ assert md5(fixtures_dir / "array.npy") == "bbadddf09cf6b1e36d8333f474e36cee"
19
+
20
+
21
+ def test_safe_filename():
22
+ assert safe_filename("Wave your hand yeah 🙋!") == "Wave-your-hand-yeah.f7952a3d"
23
+ assert (
24
+ safe_filename("Wave your hand yeah 🙋!", full=True)
25
+ == "Wave-your-hand-yeah.f7952a3d4b0534cdac0e0cbbf66aac73"
26
+ )
27
+ assert safe_filename("Wave your hand yeah 🙋!", add_hash=False) == "Wave-your-hand-yeah"
28
+
29
+
30
+ def test_clean_datapackage_name():
31
+ a = "('IPCC', 'simple') processed arrays"
32
+ b = "IPCC_simple_processed_arrays"
33
+ assert clean_datapackage_name(a) == b