py-modelrunner 0.13.0__tar.gz → 0.14.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 (175) hide show
  1. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/.gitignore +6 -0
  2. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/PKG-INFO +19 -2
  3. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/examples/io_hdf.py +1 -1
  4. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/examples/io_json.py +1 -1
  5. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/examples/io_yaml.py +1 -1
  6. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/examples/model_class.py +5 -1
  7. py-modelrunner-0.14.0/examples/model_storage_output.py +27 -0
  8. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/examples/script_function.py +1 -1
  9. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/modelrunner/__init__.py +1 -19
  10. py-modelrunner-0.14.0/modelrunner/_version.py +16 -0
  11. py-modelrunner-0.14.0/modelrunner/compatibility/__init__.py +5 -0
  12. py-modelrunner-0.14.0/modelrunner/compatibility/triage.py +181 -0
  13. py-modelrunner-0.14.0/modelrunner/compatibility/version0.py +101 -0
  14. py-modelrunner-0.14.0/modelrunner/compatibility/version1.py +261 -0
  15. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/modelrunner/model.py +74 -36
  16. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/modelrunner/parameters.py +6 -2
  17. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/modelrunner/results.py +99 -176
  18. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/modelrunner/run/job.py +31 -9
  19. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/modelrunner/run/templates/background.template +9 -0
  20. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/modelrunner/run/templates/foreground.template +9 -0
  21. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/modelrunner/run/templates/qsub.template +9 -0
  22. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/modelrunner/run/templates/srun.template +9 -0
  23. py-modelrunner-0.14.0/modelrunner/storage/__init__.py +8 -0
  24. py-modelrunner-0.14.0/modelrunner/storage/access_modes.py +142 -0
  25. py-modelrunner-0.14.0/modelrunner/storage/attributes.py +88 -0
  26. py-modelrunner-0.14.0/modelrunner/storage/backend/__init__.py +28 -0
  27. py-modelrunner-0.14.0/modelrunner/storage/backend/hdf.py +267 -0
  28. py-modelrunner-0.14.0/modelrunner/storage/backend/json.py +28 -0
  29. py-modelrunner-0.14.0/modelrunner/storage/backend/memory.py +176 -0
  30. py-modelrunner-0.14.0/modelrunner/storage/backend/text_base.py +215 -0
  31. py-modelrunner-0.14.0/modelrunner/storage/backend/utils.py +64 -0
  32. py-modelrunner-0.14.0/modelrunner/storage/backend/yaml.py +36 -0
  33. py-modelrunner-0.14.0/modelrunner/storage/backend/zarr.py +232 -0
  34. py-modelrunner-0.14.0/modelrunner/storage/base.py +507 -0
  35. py-modelrunner-0.14.0/modelrunner/storage/group.py +411 -0
  36. py-modelrunner-0.14.0/modelrunner/storage/tools.py +139 -0
  37. py-modelrunner-0.14.0/modelrunner/storage/trajectory.py +231 -0
  38. py-modelrunner-0.14.0/modelrunner/storage/utils.py +232 -0
  39. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/py_modelrunner.egg-info/PKG-INFO +19 -2
  40. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/py_modelrunner.egg-info/SOURCES.txt +51 -14
  41. py-modelrunner-0.14.0/py_modelrunner.egg-info/requires.txt +19 -0
  42. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/pyproject.toml +20 -6
  43. py-modelrunner-0.14.0/requirements.txt +4 -0
  44. py-modelrunner-0.14.0/requirements_full.txt +5 -0
  45. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/scripts/create_compatibility_files.py +13 -15
  46. py-modelrunner-0.14.0/tests/compatibility/2/array.hdf +0 -0
  47. py-modelrunner-0.14.0/tests/compatibility/2/array.json +1 -0
  48. py-modelrunner-0.14.0/tests/compatibility/2/array.pkl +0 -0
  49. py-modelrunner-0.14.0/tests/compatibility/2/array.yaml +15 -0
  50. py-modelrunner-0.14.0/tests/compatibility/2/array.zip +0 -0
  51. py-modelrunner-0.14.0/tests/compatibility/2/array_col.hdf +0 -0
  52. py-modelrunner-0.14.0/tests/compatibility/2/array_col.json +1 -0
  53. py-modelrunner-0.14.0/tests/compatibility/2/array_col.pkl +0 -0
  54. py-modelrunner-0.14.0/tests/compatibility/2/array_col.yaml +16 -0
  55. py-modelrunner-0.14.0/tests/compatibility/2/array_col.zip +0 -0
  56. py-modelrunner-0.14.0/tests/compatibility/2/dict.hdf +0 -0
  57. py-modelrunner-0.14.0/tests/compatibility/2/dict.json +1 -0
  58. py-modelrunner-0.14.0/tests/compatibility/2/dict.pkl +0 -0
  59. py-modelrunner-0.14.0/tests/compatibility/2/dict.yaml +17 -0
  60. py-modelrunner-0.14.0/tests/compatibility/2/dict.zip +0 -0
  61. py-modelrunner-0.14.0/tests/compatibility/2/nested.hdf +0 -0
  62. py-modelrunner-0.14.0/tests/compatibility/2/nested.json +1 -0
  63. py-modelrunner-0.14.0/tests/compatibility/2/nested.pkl +0 -0
  64. py-modelrunner-0.14.0/tests/compatibility/2/nested.yaml +15 -0
  65. py-modelrunner-0.14.0/tests/compatibility/2/nested.zip +0 -0
  66. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/tests/compatibility/test_compatibility.py +13 -15
  67. py-modelrunner-0.14.0/tests/helpers/__init__.py +2 -0
  68. py-modelrunner-0.14.0/tests/helpers/asserts.py +62 -0
  69. py-modelrunner-0.14.0/tests/helpers/storage.py +102 -0
  70. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/tests/requirements.txt +2 -1
  71. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/tests/run/test_job.py +4 -2
  72. py-modelrunner-0.14.0/tests/run/test_run_main.py +26 -0
  73. py-modelrunner-0.14.0/tests/storage/test_group.py +18 -0
  74. py-modelrunner-0.14.0/tests/storage/test_storage_generic.py +279 -0
  75. py-modelrunner-0.14.0/tests/storage/test_storage_special.py +79 -0
  76. py-modelrunner-0.14.0/tests/storage/test_trajectory.py +147 -0
  77. py-modelrunner-0.14.0/tests/storage/test_utils.py +42 -0
  78. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/tests/test_model.py +46 -0
  79. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/tests/test_results.py +57 -3
  80. py-modelrunner-0.13.0/.settings/.gitignore +0 -1
  81. py-modelrunner-0.13.0/modelrunner/_version.py +0 -4
  82. py-modelrunner-0.13.0/modelrunner/state/__init__.py +0 -71
  83. py-modelrunner-0.13.0/modelrunner/state/array.py +0 -128
  84. py-modelrunner-0.13.0/modelrunner/state/array_collection.py +0 -192
  85. py-modelrunner-0.13.0/modelrunner/state/base.py +0 -413
  86. py-modelrunner-0.13.0/modelrunner/state/dict.py +0 -178
  87. py-modelrunner-0.13.0/modelrunner/state/io.py +0 -336
  88. py-modelrunner-0.13.0/modelrunner/state/object.py +0 -88
  89. py-modelrunner-0.13.0/modelrunner/state/trajectory.py +0 -171
  90. py-modelrunner-0.13.0/py_modelrunner.egg-info/requires.txt +0 -8
  91. py-modelrunner-0.13.0/requirements.txt +0 -8
  92. py-modelrunner-0.13.0/tests/state/test_dict.py +0 -39
  93. py-modelrunner-0.13.0/tests/state/test_generic.py +0 -178
  94. py-modelrunner-0.13.0/tests/state/test_trajectory.py +0 -107
  95. py-modelrunner-0.13.0/tests/utils/__init__.py +0 -0
  96. py-modelrunner-0.13.0/tests/utils/states.py +0 -84
  97. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/.github/workflows/build.yml +0 -0
  98. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/.github/workflows/check_docs.yml +0 -0
  99. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/.github/workflows/coverage_report.yml +0 -0
  100. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/.github/workflows/release_pip.yml +0 -0
  101. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/.readthedocs.yaml +0 -0
  102. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/LICENSE +0 -0
  103. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/README.md +0 -0
  104. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/codecov.yml +0 -0
  105. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/docs/Makefile +0 -0
  106. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/docs/build_all.sh +0 -0
  107. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/docs/requirements.txt +0 -0
  108. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/docs/source/.gitignore +0 -0
  109. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/docs/source/conf.py +0 -0
  110. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/docs/source/index.rst +0 -0
  111. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/docs/source/installation.rst +0 -0
  112. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/docs/source/run_autodoc.py +0 -0
  113. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/docs/source/sphinx_simplify_typehints.py +0 -0
  114. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/docs/source/structure.rst +0 -0
  115. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/examples/model_decorator.py +0 -0
  116. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/examples/model_function.py +0 -0
  117. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/examples/read_many.py +0 -0
  118. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/examples/script_custom_func.py +0 -0
  119. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/examples/script_many_classes.py +0 -0
  120. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/examples/script_minimal.py +0 -0
  121. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/examples/script_model_class.py +0 -0
  122. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/examples/submit_function.py +0 -0
  123. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/examples/submit_many_func.py +0 -0
  124. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/examples/submit_many_iter.py +0 -0
  125. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/examples/submit_shebang.py +0 -0
  126. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/modelrunner/__main__.py +0 -0
  127. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/modelrunner/py.typed +0 -0
  128. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/modelrunner/run/__init__.py +0 -0
  129. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/modelrunner/run/__main__.py +0 -0
  130. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/py_modelrunner.egg-info/dependency_links.txt +0 -0
  131. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/py_modelrunner.egg-info/not-zip-safe +0 -0
  132. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/py_modelrunner.egg-info/top_level.txt +0 -0
  133. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/scripts/format_code.sh +0 -0
  134. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/scripts/performance_hdf5_zarr.py +0 -0
  135. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/scripts/run_tests.py +0 -0
  136. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/scripts/tests_all.sh +0 -0
  137. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/scripts/tests_codestyle.sh +0 -0
  138. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/scripts/tests_coverage.sh +0 -0
  139. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/scripts/tests_parallel.sh +0 -0
  140. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/scripts/tests_run.sh +0 -0
  141. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/scripts/tests_types.sh +0 -0
  142. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/setup.cfg +0 -0
  143. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/tests/compatibility/0/result.hdf +0 -0
  144. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/tests/compatibility/0/result.json +0 -0
  145. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/tests/compatibility/0/result.pkl +0 -0
  146. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/tests/compatibility/0/result.yaml +0 -0
  147. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/tests/compatibility/1/array.json +0 -0
  148. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/tests/compatibility/1/array.pkl +0 -0
  149. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/tests/compatibility/1/array.yaml +0 -0
  150. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/tests/compatibility/1/array.zarr +0 -0
  151. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/tests/compatibility/1/array_col.json +0 -0
  152. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/tests/compatibility/1/array_col.pkl +0 -0
  153. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/tests/compatibility/1/array_col.yaml +0 -0
  154. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/tests/compatibility/1/array_col.zarr +0 -0
  155. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/tests/compatibility/1/dict.json +0 -0
  156. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/tests/compatibility/1/dict.pkl +0 -0
  157. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/tests/compatibility/1/dict.yaml +0 -0
  158. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/tests/compatibility/1/dict.zarr +0 -0
  159. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/tests/compatibility/1/object.json +0 -0
  160. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/tests/compatibility/1/object.pkl +0 -0
  161. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/tests/compatibility/1/object.yaml +0 -0
  162. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/tests/compatibility/1/object.zarr +0 -0
  163. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/tests/run/scripts/function.py +0 -0
  164. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/tests/run/scripts/script.py +0 -0
  165. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/tests/scripts/empty.py +0 -0
  166. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/tests/scripts/function.py +0 -0
  167. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/tests/scripts/function_main.py +0 -0
  168. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/tests/scripts/function_marked.py +0 -0
  169. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/tests/scripts/make_model.py +0 -0
  170. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/tests/scripts/make_model_class.py +0 -0
  171. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/tests/scripts/make_model_marked.py +0 -0
  172. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/tests/test_examples.py +0 -0
  173. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/tests/test_main.py +0 -0
  174. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/tests/test_parameters.py +0 -0
  175. {py-modelrunner-0.13.0 → py-modelrunner-0.14.0}/tests/test_version.py +0 -0
@@ -122,6 +122,12 @@ venv.bak/
122
122
  # Rope project settings
123
123
  .ropeproject
124
124
 
125
+ # VSCode project settings
126
+ .vscode
127
+
128
+ # Eclipse project settings
129
+ .settings
130
+
125
131
  # mkdocs documentation
126
132
  /site
127
133
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: py-modelrunner
3
- Version: 0.13.0
3
+ Version: 0.14.0
4
4
  Summary: Python classes for organizing (HPC) simulations
5
5
  Author-email: David Zwicker <david.zwicker@ds.mpg.de>
6
6
  License: MIT
@@ -18,9 +18,26 @@ Classifier: Programming Language :: Python :: 3.8
18
18
  Classifier: Programming Language :: Python :: 3.9
19
19
  Classifier: Programming Language :: Python :: 3.10
20
20
  Classifier: Programming Language :: Python :: 3.11
21
- Requires-Python: >=3.8
21
+ Requires-Python: <3.12,>=3.8
22
22
  Description-Content-Type: text/markdown
23
23
  License-File: LICENSE
24
+ Requires-Dist: jinja2>=3
25
+ Requires-Dist: numpy>=1.18.0
26
+ Requires-Dist: tqdm>=4.45
27
+ Requires-Dist: numcodecs>=0.10
28
+ Provides-Extra: all
29
+ Requires-Dist: h5py>=3.5; extra == "all"
30
+ Requires-Dist: pandas>=1.3; extra == "all"
31
+ Requires-Dist: PyYAML>=5; extra == "all"
32
+ Requires-Dist: zarr>=2; extra == "all"
33
+ Provides-Extra: test
34
+ Requires-Dist: black>=19; extra == "test"
35
+ Requires-Dist: isort>=5.1; extra == "test"
36
+ Requires-Dist: pytest>=5.4; extra == "test"
37
+ Requires-Dist: pytest-cov>=2.8; extra == "test"
38
+ Requires-Dist: pytest-xdist>=1.30; extra == "test"
39
+ Requires-Dist: py-pde>=0.33; extra == "test"
40
+ Requires-Dist: mypy>=0.770; extra == "test"
24
41
 
25
42
  # py-modelrunner
26
43
 
@@ -22,4 +22,4 @@ if __name__ == "__main__":
22
22
 
23
23
  # write result from file
24
24
  read = Result.from_file("test.hdf")
25
- print(read.parameters, "–– start + [0..length-1] =", read.state)
25
+ print(read.parameters, "–– start + [0..length-1] =", read.data)
@@ -18,4 +18,4 @@ if __name__ == "__main__":
18
18
  result.to_file("test.json")
19
19
 
20
20
  read = Result.from_file("test.json")
21
- print(read.parameters, "–– a * b =", read.state)
21
+ print(read.parameters, "–– a * b =", read.data)
@@ -18,4 +18,4 @@ if __name__ == "__main__":
18
18
  result.to_file("test.yaml")
19
19
 
20
20
  read = Result.from_file("test.yaml")
21
- print(read.parameters, "–– a * b =", read.state)
21
+ print(read.parameters, "–– a * b =", read.data)
@@ -5,6 +5,8 @@ This example shows defining a custom model class by subclassing.
5
5
  .. codeauthor:: David Zwicker <david.zwicker@ds.mpg.de>
6
6
  """
7
7
 
8
+ import numpy as np
9
+
8
10
  from modelrunner import ModelBase
9
11
 
10
12
 
@@ -12,10 +14,12 @@ class MyModel(ModelBase):
12
14
  parameters_default = {"a": 1, "b": 2}
13
15
 
14
16
  def __call__(self):
17
+ self.storage.write_array("arr", np.arange(4))
18
+ self.storage.write_attrs("arr", {"key": "value"}) # write extra information
15
19
  return self.parameters["a"] * self.parameters["b"]
16
20
 
17
21
 
18
22
  # create an instance of the model
19
- model = MyModel({"a": 3})
23
+ model = MyModel({"a": 3}, output="test.yaml")
20
24
  # run the instance
21
25
  print(model())
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ This example shows defining a custom model that stores additional data
4
+
5
+ .. codeauthor:: David Zwicker <david.zwicker@ds.mpg.de>
6
+ """
7
+
8
+ import tempfile
9
+
10
+ from modelrunner import make_model, open_storage
11
+
12
+
13
+ def multiply(a, b=2, storage=None):
14
+ storage["data"] = {"additional": "information"}
15
+ return a * b
16
+
17
+
18
+ with tempfile.NamedTemporaryFile(suffix=".yaml") as fp:
19
+ # create an instance of the model defined by the function
20
+ model = make_model(multiply, {"a": 3}, output=fp.name)
21
+ # run the instance and store the data
22
+ model.write_result()
23
+
24
+ # read the file and check whether all the data is there
25
+ with open_storage(fp.name) as storage:
26
+ print("Stored data:", storage["data"])
27
+ print("Model result:", storage["result"].data)
@@ -15,4 +15,4 @@ def multiply(a: float = 1, b: float = 2):
15
15
 
16
16
  if __name__ == "__main__":
17
17
  result = run_function_with_cmd_args(multiply)
18
- print(result.state)
18
+ print(result.data)
@@ -1,15 +1,4 @@
1
1
  """
2
-
3
- .. inheritance-diagram::
4
- state.io.IOBase
5
- state.base.StateBase
6
- state.array.ArrayState
7
- state.array_collection.ArrayCollectionState
8
- state.object.ObjectState
9
- state.dict.DictState
10
- results.Result
11
- :parts: 1
12
-
13
2
  .. codeauthor:: David Zwicker <david.zwicker@ds.mpg.de>
14
3
  """
15
4
 
@@ -41,11 +30,4 @@ from .model import (
41
30
  from .parameters import HideParameter, Parameter, Parameterized
42
31
  from .results import Result, ResultCollection
43
32
  from .run import submit_job, submit_jobs
44
- from .state import (
45
- ArrayCollectionState,
46
- ArrayState,
47
- DictState,
48
- ObjectState,
49
- load_state,
50
- make_state,
51
- )
33
+ from .storage import open_storage
@@ -0,0 +1,16 @@
1
+ # file generated by setuptools_scm
2
+ # don't change, don't track in version control
3
+ TYPE_CHECKING = False
4
+ if TYPE_CHECKING:
5
+ from typing import Tuple, Union
6
+ VERSION_TUPLE = Tuple[Union[int, str], ...]
7
+ else:
8
+ VERSION_TUPLE = object
9
+
10
+ version: str
11
+ __version__: str
12
+ __version_tuple__: VERSION_TUPLE
13
+ version_tuple: VERSION_TUPLE
14
+
15
+ __version__ = version = '0.14.0'
16
+ __version_tuple__ = version_tuple = (0, 14, 0)
@@ -0,0 +1,5 @@
1
+ """
2
+ Code for maintaining backwards compatibility, particularly for loading results
3
+
4
+ .. codeauthor:: David Zwicker <david.zwicker@ds.mpg.de>
5
+ """
@@ -0,0 +1,181 @@
1
+ """
2
+ Contains code necessary for deciding which format version was used to write a file
3
+
4
+ .. codeauthor:: David Zwicker <david.zwicker@ds.mpg.de>
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import json
10
+ from pathlib import Path
11
+ from typing import TYPE_CHECKING, Any, Mapping, Optional, Union
12
+
13
+ from ..model import ModelBase
14
+ from ..results import Result
15
+
16
+ if TYPE_CHECKING:
17
+ from zarr.storage import BaseStore
18
+
19
+
20
+ Store = Union[str, Path, "BaseStore"]
21
+
22
+
23
+ def guess_format(path: Path) -> str:
24
+ """guess the format of a given store
25
+
26
+ Args:
27
+ path (str or :class:`~pathlib.Path`):
28
+ Path pointing to a file
29
+
30
+ Returns:
31
+ str: The store format
32
+ """
33
+ # guess format from path extension
34
+ ext = Path(path).suffix.lower()
35
+ if ext == ".json":
36
+ return "json"
37
+ elif ext in {".yml", ".yaml"}:
38
+ return "yaml"
39
+ elif ext in {".h5", ".hdf", ".hdf5"}:
40
+ return "hdf"
41
+ else:
42
+ return "zarr" # fallback to the default storage method based on zarr
43
+
44
+
45
+ def normalize_zarr_store(store: Store, mode: str = "a") -> Optional[Store]:
46
+ """determine best file format for zarr storage
47
+
48
+ In particular, we use a :class:`~zarr.storage.ZipStore` when a path looking like a
49
+ file is given.
50
+
51
+ Args:
52
+ store: User-provided store
53
+ mode (str): The mode with which the file will be opened
54
+
55
+ Returns:
56
+ """
57
+ import zipfile
58
+
59
+ import zarr
60
+
61
+ if isinstance(store, (str, Path)):
62
+ store = Path(store)
63
+ if store.is_file():
64
+ try:
65
+ store = zarr.storage.ZipStore(store, mode=mode)
66
+ except zipfile.BadZipfile:
67
+ return None
68
+ else:
69
+ return None
70
+ return store
71
+
72
+
73
+ def _find_version(data: Mapping[str, Any], label: str) -> Optional[int]:
74
+ """try finding version information in different places in `data`
75
+
76
+ Args:
77
+ data (dict):
78
+ A mapping that contains attribute information
79
+ label (str):
80
+ The label of the data that should be loaded
81
+
82
+ Returns:
83
+ int: The format version or None if it could not be found
84
+ """
85
+
86
+ def read_version(item) -> Optional[str]:
87
+ """try reading attribute from a particular item"""
88
+ if hasattr(item, "attrs"):
89
+ return read_version(item.attrs)
90
+ elif "__version__" in item:
91
+ return item["__version__"] # type: ignore
92
+ elif "format_version" in item:
93
+ return item["format_version"] # type: ignore
94
+ elif "__attrs__" in item:
95
+ return read_version(item["__attrs__"])
96
+ elif "attributes" in item:
97
+ return read_version(item["attributes"])
98
+ else:
99
+ return None
100
+
101
+ format_version = read_version(data)
102
+ if format_version is None and label in data:
103
+ format_version = read_version(data[label])
104
+ if format_version is None and "state" in data:
105
+ format_version = read_version(data["state"])
106
+
107
+ if isinstance(format_version, str):
108
+ return json.loads(format_version) # type: ignore
109
+ else:
110
+ return format_version
111
+
112
+
113
+ def result_check_load_old_version(
114
+ path: Path, loc: str, *, model: Optional[ModelBase] = None
115
+ ) -> Optional[Result]:
116
+ """check whether the resource can be loaded with an older version of the package
117
+
118
+ Args:
119
+ path (str or :class:`~pathlib.Path`):
120
+ The path to the resource to be loaded
121
+ loc (str):
122
+ Label, key, or location of the item to be loaded
123
+ model (:class:`~modelrunner.model.ModelBase`, optional):
124
+ Optional model that was used to write this result
125
+
126
+ Returns:
127
+ :class:`~modelrunner.result.Result`:
128
+ The loaded result or `None` if we cannot load it with the old versions
129
+ """
130
+ label = "data" if loc is None else loc
131
+ format_version = None
132
+ # check for compatibility
133
+ fmt = guess_format(path)
134
+ if fmt == "json":
135
+ with open(path, mode="r") as fp:
136
+ format_version = _find_version(json.load(fp), label)
137
+
138
+ elif fmt == "yaml":
139
+ import yaml
140
+
141
+ with open(path, mode="r") as fp:
142
+ format_version = _find_version(yaml.safe_load(fp), label)
143
+
144
+ elif fmt == "hdf":
145
+ import h5py
146
+
147
+ with h5py.File(path, mode="r") as root:
148
+ format_version = _find_version(root, label)
149
+
150
+ elif fmt == "zarr":
151
+ import zarr
152
+
153
+ store = normalize_zarr_store(path, mode="r")
154
+ if store is None:
155
+ return None # could not open zarr file
156
+ with zarr.open_group(store, mode="r") as root:
157
+ format_version = _find_version(root, label)
158
+ if format_version is None and label != "data":
159
+ format_version = _find_version(root, "data")
160
+ if format_version is not None:
161
+ label = "data"
162
+
163
+ else:
164
+ return None
165
+
166
+ if format_version in {0, None}:
167
+ # load result written with format version 0
168
+ from .version0 import result_from_file_v0
169
+
170
+ return result_from_file_v0(path, model=model)
171
+
172
+ elif format_version == 1:
173
+ # load result written with format version 1
174
+ from .version1 import result_from_file_v1
175
+
176
+ return result_from_file_v1(path, label=label, model=model)
177
+
178
+ elif not isinstance(format_version, int):
179
+ raise RuntimeError(f"Unsupported format version {format_version}")
180
+
181
+ return None
@@ -0,0 +1,101 @@
1
+ """
2
+ Contains code necessary for loading results from format version 0
3
+
4
+ .. codeauthor:: David Zwicker <david.zwicker@ds.mpg.de>
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import json
10
+ from pathlib import Path
11
+ from typing import Any, Mapping, Optional
12
+
13
+ import numpy as np
14
+
15
+ from ..model import ModelBase
16
+ from ..results import Result
17
+ from .triage import guess_format
18
+
19
+
20
+ def read_hdf_data(node):
21
+ """read structured data written with :func:`write_hdf_dataset` from an HDF node"""
22
+ import h5py
23
+
24
+ if isinstance(node, h5py.Dataset):
25
+ return np.array(node)
26
+ else:
27
+ # this must be a group
28
+ data = {key: json.loads(value) for key, value in node.attrs.items()}
29
+ for key, value in node.items():
30
+ data[key] = read_hdf_data(value)
31
+ return data
32
+
33
+
34
+ def _Result_from_simple_objects(
35
+ content: Mapping[str, Any], model: Optional[ModelBase] = None
36
+ ) -> Result:
37
+ """read result from simple object (like loaded from a JSON file) using version 0
38
+
39
+ Args:
40
+ content (dict):
41
+ Data from which the result is restored
42
+ model (:class:`ModelBase`):
43
+ Model associated with the result
44
+
45
+ Returns:
46
+ :class:`Result`: the restored result
47
+ """
48
+
49
+ return Result.from_data(
50
+ model_data=content.get("model", {}),
51
+ result=content.get("result"),
52
+ model=model,
53
+ info=content.get("info", {}),
54
+ )
55
+
56
+
57
+ def _Result_from_hdf(hdf_element, model: Optional[ModelBase] = None) -> Result:
58
+ """old reader for backward compatible reading"""
59
+ model_data = {key: json.loads(value) for key, value in hdf_element.attrs.items()}
60
+ if "result" in hdf_element:
61
+ result = read_hdf_data(hdf_element["result"])
62
+ else:
63
+ result = model_data.pop("result")
64
+ # check for other nodes, which might not be read
65
+
66
+ info = model_data.pop("__info__") if "__info__" in model_data else {}
67
+
68
+ return Result.from_data(
69
+ model_data=model_data, result=result, model=model, info=info
70
+ )
71
+
72
+
73
+ def result_from_file_v0(path: Path, **kwargs) -> Result:
74
+ """load object from a file using format version 1
75
+
76
+ Args:
77
+ store (str or :class:`zarr.Store`):
78
+ Path or instance describing the storage, which is either a file path or
79
+ a :class:`zarr.Storage`.
80
+ """
81
+ fmt = guess_format(path)
82
+ if fmt == "json":
83
+ with open(path, mode="r") as fp:
84
+ content = json.load(fp)
85
+ return _Result_from_simple_objects(content, **kwargs)
86
+
87
+ elif fmt == "yaml":
88
+ import yaml
89
+
90
+ with open(path, mode="r") as fp:
91
+ content = yaml.safe_load(fp)
92
+ return _Result_from_simple_objects(content, **kwargs)
93
+
94
+ elif fmt == "hdf":
95
+ import h5py
96
+
97
+ with h5py.File(path, mode="r") as root:
98
+ return _Result_from_hdf(root, **kwargs)
99
+
100
+ else:
101
+ raise NotImplementedError(f"Format `{fmt}` not implemented")