py-modelrunner 0.14.0__tar.gz → 0.16.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 (166) hide show
  1. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/.github/workflows/build.yml +8 -1
  2. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/PKG-INFO +3 -2
  3. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/docs/requirements.txt +1 -1
  4. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/docs/source/.gitignore +1 -0
  5. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/docs/source/conf.py +17 -10
  6. py-modelrunner-0.16.0/docs/source/examples.rst +10 -0
  7. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/docs/source/index.rst +4 -2
  8. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/docs/source/installation.rst +1 -1
  9. py-modelrunner-0.16.0/docs/source/parse_examples.py +65 -0
  10. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/docs/source/run_autodoc.py +1 -1
  11. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/docs/source/sphinx_simplify_typehints.py +1 -1
  12. py-modelrunner-0.16.0/docs/source/user_manual.rst +53 -0
  13. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/modelrunner/__init__.py +0 -1
  14. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/modelrunner/__main__.py +2 -0
  15. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/modelrunner/_version.py +2 -2
  16. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/modelrunner/compatibility/triage.py +8 -8
  17. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/modelrunner/compatibility/version0.py +5 -5
  18. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/modelrunner/compatibility/version1.py +17 -20
  19. py-modelrunner-0.16.0/modelrunner/config.py +149 -0
  20. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/modelrunner/model.py +34 -26
  21. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/modelrunner/parameters.py +74 -91
  22. py-modelrunner-0.16.0/modelrunner/py.typed +1 -0
  23. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/modelrunner/results.py +17 -16
  24. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/modelrunner/run/__main__.py +3 -0
  25. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/modelrunner/run/job.py +103 -32
  26. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/modelrunner/run/templates/background.template +8 -8
  27. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/modelrunner/run/templates/foreground.template +8 -8
  28. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/modelrunner/run/templates/qsub.template +10 -12
  29. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/modelrunner/run/templates/srun.template +10 -12
  30. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/modelrunner/storage/access_modes.py +11 -5
  31. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/modelrunner/storage/attributes.py +2 -0
  32. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/modelrunner/storage/backend/hdf.py +41 -19
  33. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/modelrunner/storage/backend/memory.py +5 -5
  34. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/modelrunner/storage/backend/text_base.py +7 -6
  35. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/modelrunner/storage/backend/utils.py +1 -29
  36. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/modelrunner/storage/backend/zarr.py +7 -8
  37. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/modelrunner/storage/base.py +29 -32
  38. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/modelrunner/storage/group.py +31 -23
  39. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/modelrunner/storage/tools.py +19 -4
  40. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/modelrunner/storage/trajectory.py +32 -22
  41. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/modelrunner/storage/utils.py +17 -27
  42. py-modelrunner-0.16.0/modelrunner/utils.py +71 -0
  43. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/py_modelrunner.egg-info/PKG-INFO +3 -2
  44. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/py_modelrunner.egg-info/SOURCES.txt +7 -2
  45. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/pyproject.toml +2 -1
  46. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/requirements.txt +1 -0
  47. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/requirements_full.txt +0 -1
  48. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/scripts/format_code.sh +5 -0
  49. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/scripts/run_tests.py +12 -2
  50. py-modelrunner-0.16.0/tests/conftest.py +4 -0
  51. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/helpers/storage.py +1 -29
  52. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/requirements.txt +2 -2
  53. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/storage/test_storage_generic.py +46 -3
  54. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/storage/test_storage_special.py +4 -5
  55. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/storage/test_trajectory.py +81 -4
  56. py-modelrunner-0.16.0/tests/test_config.py +107 -0
  57. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/test_examples.py +2 -3
  58. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/test_model.py +57 -2
  59. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/test_parameters.py +41 -0
  60. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/test_results.py +3 -3
  61. py-modelrunner-0.14.0/codecov.yml +0 -11
  62. py-modelrunner-0.14.0/docs/source/structure.rst +0 -61
  63. py-modelrunner-0.14.0/modelrunner/py.typed +0 -1
  64. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/.github/workflows/check_docs.yml +0 -0
  65. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/.github/workflows/coverage_report.yml +0 -0
  66. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/.github/workflows/release_pip.yml +0 -0
  67. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/.gitignore +0 -0
  68. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/.readthedocs.yaml +0 -0
  69. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/LICENSE +0 -0
  70. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/README.md +0 -0
  71. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/docs/Makefile +0 -0
  72. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/docs/build_all.sh +0 -0
  73. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/examples/io_hdf.py +0 -0
  74. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/examples/io_json.py +0 -0
  75. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/examples/io_yaml.py +0 -0
  76. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/examples/model_class.py +0 -0
  77. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/examples/model_decorator.py +0 -0
  78. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/examples/model_function.py +0 -0
  79. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/examples/model_storage_output.py +0 -0
  80. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/examples/read_many.py +0 -0
  81. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/examples/script_custom_func.py +0 -0
  82. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/examples/script_function.py +0 -0
  83. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/examples/script_many_classes.py +0 -0
  84. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/examples/script_minimal.py +0 -0
  85. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/examples/script_model_class.py +0 -0
  86. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/examples/submit_function.py +0 -0
  87. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/examples/submit_many_func.py +0 -0
  88. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/examples/submit_many_iter.py +0 -0
  89. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/examples/submit_shebang.py +0 -0
  90. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/modelrunner/compatibility/__init__.py +0 -0
  91. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/modelrunner/run/__init__.py +0 -0
  92. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/modelrunner/storage/__init__.py +0 -0
  93. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/modelrunner/storage/backend/__init__.py +0 -0
  94. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/modelrunner/storage/backend/json.py +0 -0
  95. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/modelrunner/storage/backend/yaml.py +0 -0
  96. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/py_modelrunner.egg-info/dependency_links.txt +0 -0
  97. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/py_modelrunner.egg-info/not-zip-safe +0 -0
  98. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/py_modelrunner.egg-info/requires.txt +0 -0
  99. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/py_modelrunner.egg-info/top_level.txt +0 -0
  100. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/scripts/create_compatibility_files.py +0 -0
  101. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/scripts/performance_hdf5_zarr.py +0 -0
  102. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/scripts/tests_all.sh +0 -0
  103. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/scripts/tests_codestyle.sh +0 -0
  104. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/scripts/tests_coverage.sh +0 -0
  105. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/scripts/tests_parallel.sh +0 -0
  106. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/scripts/tests_run.sh +0 -0
  107. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/scripts/tests_types.sh +0 -0
  108. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/setup.cfg +0 -0
  109. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/compatibility/0/result.hdf +0 -0
  110. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/compatibility/0/result.json +0 -0
  111. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/compatibility/0/result.pkl +0 -0
  112. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/compatibility/0/result.yaml +0 -0
  113. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/compatibility/1/array.json +0 -0
  114. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/compatibility/1/array.pkl +0 -0
  115. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/compatibility/1/array.yaml +0 -0
  116. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/compatibility/1/array.zarr +0 -0
  117. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/compatibility/1/array_col.json +0 -0
  118. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/compatibility/1/array_col.pkl +0 -0
  119. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/compatibility/1/array_col.yaml +0 -0
  120. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/compatibility/1/array_col.zarr +0 -0
  121. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/compatibility/1/dict.json +0 -0
  122. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/compatibility/1/dict.pkl +0 -0
  123. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/compatibility/1/dict.yaml +0 -0
  124. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/compatibility/1/dict.zarr +0 -0
  125. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/compatibility/1/object.json +0 -0
  126. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/compatibility/1/object.pkl +0 -0
  127. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/compatibility/1/object.yaml +0 -0
  128. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/compatibility/1/object.zarr +0 -0
  129. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/compatibility/2/array.hdf +0 -0
  130. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/compatibility/2/array.json +0 -0
  131. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/compatibility/2/array.pkl +0 -0
  132. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/compatibility/2/array.yaml +0 -0
  133. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/compatibility/2/array.zip +0 -0
  134. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/compatibility/2/array_col.hdf +0 -0
  135. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/compatibility/2/array_col.json +0 -0
  136. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/compatibility/2/array_col.pkl +0 -0
  137. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/compatibility/2/array_col.yaml +0 -0
  138. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/compatibility/2/array_col.zip +0 -0
  139. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/compatibility/2/dict.hdf +0 -0
  140. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/compatibility/2/dict.json +0 -0
  141. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/compatibility/2/dict.pkl +0 -0
  142. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/compatibility/2/dict.yaml +0 -0
  143. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/compatibility/2/dict.zip +0 -0
  144. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/compatibility/2/nested.hdf +0 -0
  145. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/compatibility/2/nested.json +0 -0
  146. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/compatibility/2/nested.pkl +0 -0
  147. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/compatibility/2/nested.yaml +0 -0
  148. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/compatibility/2/nested.zip +0 -0
  149. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/compatibility/test_compatibility.py +0 -0
  150. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/helpers/__init__.py +0 -0
  151. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/helpers/asserts.py +0 -0
  152. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/run/scripts/function.py +0 -0
  153. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/run/scripts/script.py +0 -0
  154. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/run/test_job.py +0 -0
  155. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/run/test_run_main.py +0 -0
  156. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/scripts/empty.py +0 -0
  157. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/scripts/function.py +0 -0
  158. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/scripts/function_main.py +0 -0
  159. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/scripts/function_marked.py +0 -0
  160. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/scripts/make_model.py +0 -0
  161. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/scripts/make_model_class.py +0 -0
  162. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/scripts/make_model_marked.py +0 -0
  163. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/storage/test_group.py +0 -0
  164. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/storage/test_utils.py +0 -0
  165. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/test_main.py +0 -0
  166. {py-modelrunner-0.14.0 → py-modelrunner-0.16.0}/tests/test_version.py +0 -0
@@ -9,20 +9,27 @@ jobs:
9
9
  strategy:
10
10
  matrix:
11
11
  os: [macos-latest, ubuntu-latest, windows-latest]
12
- python-version: ['3.8', '3.11']
12
+ python-version: ['3.8', '3.12']
13
13
 
14
14
  steps:
15
15
  - uses: actions/checkout@v3
16
+
16
17
  - name: Set up Python ${{ matrix.python-version }}
17
18
  uses: actions/setup-python@v4
18
19
  with:
19
20
  python-version: ${{ matrix.python-version }}
21
+
20
22
  - name: Install dependencies
21
23
  run: |
22
24
  python -m pip install --upgrade pip
23
25
  pip install -r requirements.txt
24
26
  pip install -r tests/requirements.txt
25
27
 
28
+ - name: Install optional dependencies
29
+ continue-on-error: true
30
+ run: |
31
+ pip install py-pde
32
+
26
33
  - name: Test with pytest
27
34
  env:
28
35
  NUMBA_WARNINGS: 1
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: py-modelrunner
3
- Version: 0.14.0
3
+ Version: 0.16.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,7 +18,8 @@ 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.12,>=3.8
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Requires-Python: <3.13,>=3.8
22
23
  Description-Content-Type: text/markdown
23
24
  License-File: LICENSE
24
25
  Requires-Dist: jinja2>=3
@@ -1,4 +1,4 @@
1
- -r ../requirements.txt
1
+ -r ../requirements_full.txt
2
2
  Sphinx>=4
3
3
  sphinx-autodoc-annotation>=1.0
4
4
  sphinx-gallery>=0.6
@@ -1 +1,2 @@
1
1
  /packages/
2
+ /examples/
@@ -1,4 +1,3 @@
1
- # -*- coding: utf-8 -*-
2
1
  #
3
2
  # Configuration file for the Sphinx documentation builder.
4
3
  #
@@ -226,8 +225,8 @@ napoleon_numpy_docstring = False
226
225
  napoleon_include_init_with_doc = False
227
226
  napoleon_include_private_with_doc = False
228
227
  napoleon_include_special_with_doc = False
229
- napoleon_use_admonition_for_examples = False
230
- napoleon_use_admonition_for_notes = False
228
+ napoleon_use_admonition_for_examples = True
229
+ napoleon_use_admonition_for_notes = True
231
230
  napoleon_use_admonition_for_references = False
232
231
  napoleon_use_ivar = False
233
232
  napoleon_use_param = True
@@ -239,13 +238,16 @@ napoleon_custom_sections = None
239
238
 
240
239
  # Example configuration for intersphinx: refer to the Python standard library.
241
240
  intersphinx_mapping = {
242
- "https://docs.python.org/3/": None,
243
- "https://docs.scipy.org/doc/numpy/": None,
244
- "https://docs.scipy.org/doc/scipy/reference": None,
245
- "https://matplotlib.org": None,
246
- "http://docs.h5py.org/en/latest/": None,
247
- "https://py-pde.readthedocs.io/en/latest": None,
248
- "https://py-droplets.readthedocs.io/en/latest": None,
241
+ "h5py": ("https://docs.h5py.org/en/latest", None),
242
+ "matplotlib": ("https://matplotlib.org/stable", None),
243
+ "modelrunner": ("https://py-modelrunner.readthedocs.io/en/latest", None),
244
+ "napari": ("https://napari.org/", None),
245
+ "numba": ("https://numba.pydata.org/numba-doc/latest/", None),
246
+ "numpy": ("https://numpy.org/doc/stable", None),
247
+ "pde": ("https://py-pde.readthedocs.io/en/latest", None),
248
+ "python": ("https://docs.python.org/3/", None),
249
+ "scipy": ("https://docs.scipy.org/doc/scipy/", None),
250
+ "sympy": ("https://docs.sympy.org/latest/", None),
249
251
  }
250
252
 
251
253
 
@@ -255,6 +257,11 @@ graphviz_output_format = "svg"
255
257
  # for the graph, which we here corrected manually, but which lead to issues if we also
256
258
  # used the inheritance_diagram extension
257
259
 
260
+ # create all example files
261
+ from parse_examples import main
262
+
263
+ main()
264
+
258
265
  # run autodoc
259
266
  autodoc_typehints = "description"
260
267
 
@@ -0,0 +1,10 @@
1
+ Examples
2
+ ########
3
+
4
+ The following examples showcase some functionality of the package
5
+
6
+ .. toctree::
7
+ :maxdepth: 1
8
+ :glob:
9
+
10
+ examples/*
@@ -12,11 +12,13 @@ Contents
12
12
 
13
13
  .. toctree::
14
14
  :maxdepth: 2
15
+ :glob:
15
16
 
16
17
  installation
17
- structure
18
+ user_manual
19
+ examples
18
20
  packages/modelrunner
19
-
21
+
20
22
 
21
23
  Indices and tables
22
24
  ------------------
@@ -26,7 +26,7 @@ You can thus install it using
26
26
 
27
27
  conda install -c conda-forge py-modelrunner
28
28
 
29
- This installation includes all required dependencies to have all features of `py-pde`.
29
+ This installation includes all required dependencies to have all features of `py-modelrunner`.
30
30
 
31
31
 
32
32
  Installing from source
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/env python3
2
+
3
+ import pathlib
4
+ import re
5
+
6
+ # Root direcotry of the package
7
+ ROOT = pathlib.Path(__file__).absolute().parents[2]
8
+ # directory where all the examples reside
9
+ INPUT = ROOT / "examples"
10
+ # directory to which the documents are writen
11
+ OUTPUT = ROOT / "docs" / "source" / "examples"
12
+
13
+
14
+ def main():
15
+ """parse all examples and write them in a special example module"""
16
+ # create the output directory
17
+ OUTPUT.mkdir(parents=True, exist_ok=True)
18
+
19
+ regex = r'"""((?!""").*?)"""'
20
+
21
+ # iterate over all examples
22
+ for path_in in INPUT.glob("*.py"):
23
+ path_out = OUTPUT / (path_in.stem + ".rst")
24
+ print(f"Found example {path_in}")
25
+ with path_in.open("r") as file_in, path_out.open("w") as file_out:
26
+ # write the header for the rst file
27
+ file_out.write(path_in.name + "\n")
28
+ file_out.write("-" * len(path_in.name) + "\n\n")
29
+
30
+ # read all content
31
+ file_content = file_in.read()
32
+
33
+ # identify shebang
34
+ if file_content.startswith("#"):
35
+ shebang, file_content = file_content.split("\n", 1)
36
+ if shebang == "#!/usr/bin/env python3":
37
+ shebang = "" # filter trivial case
38
+ else:
39
+ shebang = None
40
+
41
+ # locate file docstring
42
+ matches = re.search(regex, file_content, re.DOTALL)
43
+ if matches:
44
+ for line in matches.group(1).split("\n"):
45
+ if ".. codeauthor::" in line:
46
+ continue
47
+ file_out.write(f"{line}\n")
48
+
49
+ file_content = file_content[matches.end(0) :]
50
+
51
+ # write actual code
52
+ file_out.write(".. code-block:: python\n\n")
53
+ if shebang:
54
+ file_out.write(f" {shebang}\n\n")
55
+ header = True
56
+ for line in file_content.split("\n"):
57
+ # skip the shebang, comments and empty lines in the beginning
58
+ if header and (line.startswith("#") or len(line.strip()) == 0):
59
+ continue
60
+ header = False # first real line was reached
61
+ file_out.write(f" {line}\n")
62
+
63
+
64
+ if __name__ == "__main__":
65
+ main()
@@ -27,7 +27,7 @@ def replace_in_file(infile, replacements, outfile=None):
27
27
  if outfile is None:
28
28
  outfile = infile
29
29
 
30
- with open(infile, "r") as fp:
30
+ with open(infile) as fp:
31
31
  content = fp.read()
32
32
 
33
33
  for key, value in replacements.items():
@@ -83,7 +83,7 @@ REPLACEMENTS = collections.OrderedDict(
83
83
  # replacement rules based on regular expressions
84
84
  REPLACEMENTS_REGEX = {
85
85
  # remove full package path and only leave the module/class identifier
86
- "multicomp\.(\w+\.)*": "",
86
+ r"multicomp\.(\w+\.)*": "",
87
87
  }
88
88
 
89
89
 
@@ -0,0 +1,53 @@
1
+ User Manual
2
+ ===========
3
+
4
+ Main structure of the package
5
+ -----------------------------
6
+
7
+ The package offers several different components that can be used separately or together:
8
+
9
+ Hierarchical input/output using :mod:`~modelrunner.storage`:
10
+ The module provides an abstract interface for writing and reading data using an
11
+ hierarchical organization.
12
+ Storages are conveniently created by :func:`~modelrunner.storage.tools.open_storage`,
13
+ which returns a storage object that offers a dict-like interface.
14
+
15
+ Defining parameters using :mod:`~modelrunner.parameters`:
16
+ The module provides the :class:`~modelrunner.parameters.Parameter` class, describing a single parameter.
17
+ This can be used together with the mixin :class:`~modelrunner.parameters.Parametrized`,
18
+ which allows to equip classes with default parameters and some convenience methods.
19
+
20
+ Defining models using :mod:`~modelrunner.model`:
21
+ Models are augmented functions, which define input, calculations, and output.
22
+ Models can be conveniently created by decorating a function or by subclassing
23
+ :class:`~modelrunner.model.ModelBase`, which is built on the parameter classes.
24
+
25
+ Model results are captured by :mod:`~modelrunner.results`:
26
+ Results are returned as the special :class:`~modelrunner.results.Result`, which
27
+ keeps track of the input parameters and the data calculated by the model.
28
+ :class:`~modelrunner.results.ResultCollection` describes a collections of the same
29
+ model evoked with different parameter values.
30
+
31
+ Submitting models to HPC using :mod:`~modelrunner.run`:
32
+ A single model can be submitted to a compute node using :func:`~modelrunner.run.job.submit_job`,
33
+ e.g., to run the computation on a high performance compute cluster.
34
+ A parameter study using multiple jobs can be conveniently submitted using :func:`~modelrunner.run.job.submit_jobs`.
35
+ The results written to one directory can then be conveniently analyzed using :meth:`~modelrunner.results.ResultCollection.from_folder`.
36
+
37
+
38
+ Design philosophy
39
+ -----------------
40
+
41
+ The main requirements for the storage classes were
42
+
43
+ - *Usability*: The user should not need to think about how data is stored in different files
44
+ - *Flexibility*: We want a general interface to write data in multiple file formats (YAML, HDF, zarr, ...)
45
+ - *Stability*: Future versions of the package should be able to read older files even when the internal definitions of file formats change
46
+ - *Extensibility*: States should be subclasses to implement more complicated requirements (e.g., particular serialization)
47
+ - *Self-explainability*: The files should in principle contain all information to reconstruct the data, even if the `py-modelrunner` package is no longer available.
48
+ - *Efficiency*: The files should only store necessary information.
49
+
50
+ The last point results in particular constraints if we want to store temporal simulation results.
51
+ In most cases, there are are some data that are kept fixed for the simulation (describing physical parameters) and others that evolve with time.
52
+ We denote by `attributes` the parameters that are kept fixed and by `data` the data that varies over time.
53
+ The state classes are already prepared to deal with such data, in conjuction with the :mod:`~modelrunner.storage.trajectory` module.
@@ -2,7 +2,6 @@
2
2
  .. codeauthor:: David Zwicker <david.zwicker@ds.mpg.de>
3
3
  """
4
4
 
5
-
6
5
  # determine the package version
7
6
  try:
8
7
  # try reading version of the automatically generated module
@@ -4,6 +4,8 @@ Main module allowing to use the package to wrap existing code
4
4
  .. codeauthor:: David Zwicker <david.zwicker@ds.mpg.de>
5
5
  """
6
6
 
7
+ from __future__ import annotations
8
+
7
9
  import sys
8
10
 
9
11
  from modelrunner import Result, run_script
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '0.14.0'
16
- __version_tuple__ = version_tuple = (0, 14, 0)
15
+ __version__ = version = '0.16.0'
16
+ __version_tuple__ = version_tuple = (0, 16, 0)
@@ -8,7 +8,7 @@ from __future__ import annotations
8
8
 
9
9
  import json
10
10
  from pathlib import Path
11
- from typing import TYPE_CHECKING, Any, Mapping, Optional, Union
11
+ from typing import TYPE_CHECKING, Any, Mapping, Union
12
12
 
13
13
  from ..model import ModelBase
14
14
  from ..results import Result
@@ -42,7 +42,7 @@ def guess_format(path: Path) -> str:
42
42
  return "zarr" # fallback to the default storage method based on zarr
43
43
 
44
44
 
45
- def normalize_zarr_store(store: Store, mode: str = "a") -> Optional[Store]:
45
+ def normalize_zarr_store(store: Store, mode: str = "a") -> Store | None:
46
46
  """determine best file format for zarr storage
47
47
 
48
48
  In particular, we use a :class:`~zarr.storage.ZipStore` when a path looking like a
@@ -70,7 +70,7 @@ def normalize_zarr_store(store: Store, mode: str = "a") -> Optional[Store]:
70
70
  return store
71
71
 
72
72
 
73
- def _find_version(data: Mapping[str, Any], label: str) -> Optional[int]:
73
+ def _find_version(data: Mapping[str, Any], label: str) -> int | None:
74
74
  """try finding version information in different places in `data`
75
75
 
76
76
  Args:
@@ -83,7 +83,7 @@ def _find_version(data: Mapping[str, Any], label: str) -> Optional[int]:
83
83
  int: The format version or None if it could not be found
84
84
  """
85
85
 
86
- def read_version(item) -> Optional[str]:
86
+ def read_version(item) -> str | None:
87
87
  """try reading attribute from a particular item"""
88
88
  if hasattr(item, "attrs"):
89
89
  return read_version(item.attrs)
@@ -111,8 +111,8 @@ def _find_version(data: Mapping[str, Any], label: str) -> Optional[int]:
111
111
 
112
112
 
113
113
  def result_check_load_old_version(
114
- path: Path, loc: str, *, model: Optional[ModelBase] = None
115
- ) -> Optional[Result]:
114
+ path: Path, loc: str, *, model: ModelBase | None = None
115
+ ) -> Result | None:
116
116
  """check whether the resource can be loaded with an older version of the package
117
117
 
118
118
  Args:
@@ -132,13 +132,13 @@ def result_check_load_old_version(
132
132
  # check for compatibility
133
133
  fmt = guess_format(path)
134
134
  if fmt == "json":
135
- with open(path, mode="r") as fp:
135
+ with open(path) as fp:
136
136
  format_version = _find_version(json.load(fp), label)
137
137
 
138
138
  elif fmt == "yaml":
139
139
  import yaml
140
140
 
141
- with open(path, mode="r") as fp:
141
+ with open(path) as fp:
142
142
  format_version = _find_version(yaml.safe_load(fp), label)
143
143
 
144
144
  elif fmt == "hdf":
@@ -8,7 +8,7 @@ from __future__ import annotations
8
8
 
9
9
  import json
10
10
  from pathlib import Path
11
- from typing import Any, Mapping, Optional
11
+ from typing import Any, Mapping
12
12
 
13
13
  import numpy as np
14
14
 
@@ -32,7 +32,7 @@ def read_hdf_data(node):
32
32
 
33
33
 
34
34
  def _Result_from_simple_objects(
35
- content: Mapping[str, Any], model: Optional[ModelBase] = None
35
+ content: Mapping[str, Any], model: ModelBase | None = None
36
36
  ) -> Result:
37
37
  """read result from simple object (like loaded from a JSON file) using version 0
38
38
 
@@ -54,7 +54,7 @@ def _Result_from_simple_objects(
54
54
  )
55
55
 
56
56
 
57
- def _Result_from_hdf(hdf_element, model: Optional[ModelBase] = None) -> Result:
57
+ def _Result_from_hdf(hdf_element, model: ModelBase | None = None) -> Result:
58
58
  """old reader for backward compatible reading"""
59
59
  model_data = {key: json.loads(value) for key, value in hdf_element.attrs.items()}
60
60
  if "result" in hdf_element:
@@ -80,14 +80,14 @@ def result_from_file_v0(path: Path, **kwargs) -> Result:
80
80
  """
81
81
  fmt = guess_format(path)
82
82
  if fmt == "json":
83
- with open(path, mode="r") as fp:
83
+ with open(path) as fp:
84
84
  content = json.load(fp)
85
85
  return _Result_from_simple_objects(content, **kwargs)
86
86
 
87
87
  elif fmt == "yaml":
88
88
  import yaml
89
89
 
90
- with open(path, mode="r") as fp:
90
+ with open(path) as fp:
91
91
  content = yaml.safe_load(fp)
92
92
  return _Result_from_simple_objects(content, **kwargs)
93
93
 
@@ -10,7 +10,7 @@ import json
10
10
  import warnings
11
11
  from abc import ABCMeta
12
12
  from pathlib import Path
13
- from typing import TYPE_CHECKING, Any, Dict, Optional, Type, TypeVar, Union
13
+ from typing import TYPE_CHECKING, Any, TypeVar, Union
14
14
 
15
15
  import numpy as np
16
16
 
@@ -55,10 +55,10 @@ class StateBase(metaclass=ABCMeta):
55
55
  _state_format_version = 2
56
56
  """int: number indicating the version of the file format"""
57
57
 
58
- _state_classes: Dict[str, Type[StateBase]] = {}
58
+ _state_classes: dict[str, type[StateBase]] = {}
59
59
  """dict: class-level list of all subclasses of StateBase"""
60
60
 
61
- def _state_init(self, attributes: Dict[str, Any], data=NoData) -> None:
61
+ def _state_init(self, attributes: dict[str, Any], data=NoData) -> None:
62
62
  """initialize the state with attributes and (optionally) data
63
63
 
64
64
  Args:
@@ -71,7 +71,7 @@ class StateBase(metaclass=ABCMeta):
71
71
  self._state_attributes = attributes
72
72
 
73
73
  @classmethod
74
- def from_data(cls: Type[TState], attributes: Dict[str, Any], data=NoData) -> TState:
74
+ def from_data(cls: type[TState], attributes: dict[str, Any], data=NoData) -> TState:
75
75
  """create instance of any state class from attributes and data
76
76
 
77
77
  Args:
@@ -84,7 +84,8 @@ class StateBase(metaclass=ABCMeta):
84
84
  # copy attributes since they are modified in this function
85
85
  attributes = attributes.copy()
86
86
  cls_name = attributes["__class__"]
87
- assert cls_name == cls.__name__
87
+ if cls_name != cls.__name__:
88
+ raise RuntimeError(f"Expected `{cls.__name__}` but data had `{cls_name}`")
88
89
 
89
90
  format_version = attributes.pop("__version__", 0)
90
91
  if format_version != 1:
@@ -97,7 +98,7 @@ class StateBase(metaclass=ABCMeta):
97
98
  return obj
98
99
 
99
100
  @classmethod
100
- def _from_simple_objects(cls, content: Dict[str, Any]) -> StateBase:
101
+ def _from_simple_objects(cls, content: dict[str, Any]) -> StateBase:
101
102
  """create state from text data
102
103
 
103
104
  Args:
@@ -115,7 +116,7 @@ class StateBase(metaclass=ABCMeta):
115
116
  return ArrayCollectionState.from_data(content["attributes"], col_data)
116
117
 
117
118
  elif cls_name == "DictState":
118
- dict_data: Dict[str, StateBase] = {}
119
+ dict_data: dict[str, StateBase] = {}
119
120
  for label, substate in content["data"].items():
120
121
  dict_data[label] = cls._from_simple_objects(substate)
121
122
 
@@ -128,7 +129,7 @@ class StateBase(metaclass=ABCMeta):
128
129
  raise TypeError(f"Do not know how to load `{cls_name}`")
129
130
 
130
131
  @classmethod
131
- def _from_zarr(cls, zarr_element: "zarrElement", *, index=...) -> StateBase:
132
+ def _from_zarr(cls, zarr_element: zarrElement, *, index=...) -> StateBase:
132
133
  """create instance of correct subclass from data stored in zarr"""
133
134
  # determine the class that knows how to read this data
134
135
  cls_name = zarr_element.attrs["__class__"]
@@ -163,24 +164,20 @@ class StateBase(metaclass=ABCMeta):
163
164
  raise TypeError(f"Do not know how to load `{cls_name}`")
164
165
 
165
166
 
166
- class ArrayState(StateBase):
167
- ...
167
+ class ArrayState(StateBase): ...
168
168
 
169
169
 
170
- class ArrayCollectionState(StateBase):
171
- ...
170
+ class ArrayCollectionState(StateBase): ...
172
171
 
173
172
 
174
- class DictState(StateBase):
175
- ...
173
+ class DictState(StateBase): ...
176
174
 
177
175
 
178
- class ObjectState(StateBase):
179
- ...
176
+ class ObjectState(StateBase): ...
180
177
 
181
178
 
182
179
  def _Result_from_simple_objects(
183
- content: Dict[str, Any], model: Optional[ModelBase] = None
180
+ content: dict[str, Any], model: ModelBase | None = None
184
181
  ) -> Result:
185
182
  """read result from simple object (like loaded from a JSON file) using version 1
186
183
 
@@ -202,7 +199,7 @@ def _Result_from_simple_objects(
202
199
 
203
200
 
204
201
  def _Result_from_zarr(
205
- zarr_element: "zarrElement", *, index=..., model: Optional[ModelBase] = None
202
+ zarr_element: zarrElement, *, index=..., model: ModelBase | None = None
206
203
  ) -> Result:
207
204
  """create result from data stored in zarr"""
208
205
  attributes = {key: json.loads(value) for key, value in zarr_element.attrs.items()}
@@ -236,14 +233,14 @@ def result_from_file_v1(store: Path, *, label: str = "data", **kwargs) -> Result
236
233
  """
237
234
  fmt = guess_format(store)
238
235
  if fmt == "json":
239
- with open(store, mode="r") as fp:
236
+ with open(store) as fp:
240
237
  content = json.load(fp)
241
238
  return _Result_from_simple_objects(content, **kwargs)
242
239
 
243
240
  elif fmt == "yaml":
244
241
  import yaml
245
242
 
246
- with open(store, mode="r") as fp:
243
+ with open(store) as fp:
247
244
  content = yaml.safe_load(fp)
248
245
  return _Result_from_simple_objects(content, **kwargs)
249
246