py-modelrunner 0.16.0__tar.gz → 0.17.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 (168) hide show
  1. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/PKG-INFO +1 -1
  2. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/docs/source/user_manual.rst +3 -2
  3. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/examples/io_hdf.py +1 -1
  4. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/examples/io_json.py +1 -1
  5. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/examples/io_yaml.py +1 -1
  6. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/examples/model_storage_output.py +1 -1
  7. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/examples/script_function.py +1 -1
  8. py-modelrunner-0.17.0/modelrunner/.gitignore +1 -0
  9. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/modelrunner/_version.py +2 -2
  10. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/modelrunner/model.py +14 -8
  11. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/modelrunner/results.py +36 -7
  12. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/modelrunner/run/job.py +16 -10
  13. py-modelrunner-0.17.0/modelrunner/run/templates/background.jinja +27 -0
  14. py-modelrunner-0.17.0/modelrunner/run/templates/foreground.jinja +26 -0
  15. py-modelrunner-0.16.0/modelrunner/run/templates/qsub.template → py-modelrunner-0.17.0/modelrunner/run/templates/qsub.jinja +8 -8
  16. py-modelrunner-0.16.0/modelrunner/run/templates/srun.template → py-modelrunner-0.17.0/modelrunner/run/templates/srun.jinja +8 -8
  17. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/modelrunner/storage/backend/memory.py +15 -9
  18. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/modelrunner/storage/group.py +42 -8
  19. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/modelrunner/storage/tools.py +4 -1
  20. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/py_modelrunner.egg-info/PKG-INFO +1 -1
  21. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/py_modelrunner.egg-info/SOURCES.txt +7 -4
  22. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/pyproject.toml +5 -2
  23. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/compatibility/test_compatibility.py +2 -2
  24. py-modelrunner-0.17.0/tests/run/scripts/fail.py +3 -0
  25. py-modelrunner-0.17.0/tests/run/scripts/print.py +3 -0
  26. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/run/test_job.py +43 -4
  27. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/storage/test_group.py +15 -0
  28. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/storage/test_storage_generic.py +8 -0
  29. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/storage/test_trajectory.py +2 -2
  30. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/test_model.py +27 -27
  31. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/test_results.py +5 -5
  32. py-modelrunner-0.16.0/modelrunner/run/templates/background.template +0 -29
  33. py-modelrunner-0.16.0/modelrunner/run/templates/foreground.template +0 -29
  34. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/.github/workflows/build.yml +0 -0
  35. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/.github/workflows/check_docs.yml +0 -0
  36. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/.github/workflows/coverage_report.yml +0 -0
  37. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/.github/workflows/release_pip.yml +0 -0
  38. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/.gitignore +0 -0
  39. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/.readthedocs.yaml +0 -0
  40. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/LICENSE +0 -0
  41. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/README.md +0 -0
  42. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/docs/Makefile +0 -0
  43. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/docs/build_all.sh +0 -0
  44. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/docs/requirements.txt +0 -0
  45. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/docs/source/.gitignore +0 -0
  46. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/docs/source/conf.py +0 -0
  47. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/docs/source/examples.rst +0 -0
  48. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/docs/source/index.rst +0 -0
  49. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/docs/source/installation.rst +0 -0
  50. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/docs/source/parse_examples.py +0 -0
  51. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/docs/source/run_autodoc.py +0 -0
  52. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/docs/source/sphinx_simplify_typehints.py +0 -0
  53. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/examples/model_class.py +0 -0
  54. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/examples/model_decorator.py +0 -0
  55. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/examples/model_function.py +0 -0
  56. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/examples/read_many.py +0 -0
  57. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/examples/script_custom_func.py +0 -0
  58. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/examples/script_many_classes.py +0 -0
  59. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/examples/script_minimal.py +0 -0
  60. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/examples/script_model_class.py +0 -0
  61. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/examples/submit_function.py +0 -0
  62. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/examples/submit_many_func.py +0 -0
  63. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/examples/submit_many_iter.py +0 -0
  64. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/examples/submit_shebang.py +0 -0
  65. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/modelrunner/__init__.py +0 -0
  66. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/modelrunner/__main__.py +0 -0
  67. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/modelrunner/compatibility/__init__.py +0 -0
  68. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/modelrunner/compatibility/triage.py +0 -0
  69. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/modelrunner/compatibility/version0.py +0 -0
  70. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/modelrunner/compatibility/version1.py +0 -0
  71. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/modelrunner/config.py +0 -0
  72. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/modelrunner/parameters.py +0 -0
  73. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/modelrunner/py.typed +0 -0
  74. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/modelrunner/run/__init__.py +0 -0
  75. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/modelrunner/run/__main__.py +0 -0
  76. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/modelrunner/storage/__init__.py +0 -0
  77. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/modelrunner/storage/access_modes.py +0 -0
  78. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/modelrunner/storage/attributes.py +0 -0
  79. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/modelrunner/storage/backend/__init__.py +0 -0
  80. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/modelrunner/storage/backend/hdf.py +0 -0
  81. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/modelrunner/storage/backend/json.py +0 -0
  82. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/modelrunner/storage/backend/text_base.py +0 -0
  83. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/modelrunner/storage/backend/utils.py +0 -0
  84. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/modelrunner/storage/backend/yaml.py +0 -0
  85. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/modelrunner/storage/backend/zarr.py +0 -0
  86. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/modelrunner/storage/base.py +0 -0
  87. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/modelrunner/storage/trajectory.py +0 -0
  88. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/modelrunner/storage/utils.py +0 -0
  89. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/modelrunner/utils.py +0 -0
  90. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/py_modelrunner.egg-info/dependency_links.txt +0 -0
  91. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/py_modelrunner.egg-info/not-zip-safe +0 -0
  92. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/py_modelrunner.egg-info/requires.txt +0 -0
  93. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/py_modelrunner.egg-info/top_level.txt +0 -0
  94. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/requirements.txt +0 -0
  95. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/requirements_full.txt +0 -0
  96. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/scripts/create_compatibility_files.py +0 -0
  97. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/scripts/format_code.sh +0 -0
  98. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/scripts/performance_hdf5_zarr.py +0 -0
  99. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/scripts/run_tests.py +0 -0
  100. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/scripts/tests_all.sh +0 -0
  101. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/scripts/tests_codestyle.sh +0 -0
  102. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/scripts/tests_coverage.sh +0 -0
  103. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/scripts/tests_parallel.sh +0 -0
  104. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/scripts/tests_run.sh +0 -0
  105. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/scripts/tests_types.sh +0 -0
  106. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/setup.cfg +0 -0
  107. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/compatibility/0/result.hdf +0 -0
  108. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/compatibility/0/result.json +0 -0
  109. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/compatibility/0/result.pkl +0 -0
  110. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/compatibility/0/result.yaml +0 -0
  111. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/compatibility/1/array.json +0 -0
  112. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/compatibility/1/array.pkl +0 -0
  113. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/compatibility/1/array.yaml +0 -0
  114. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/compatibility/1/array.zarr +0 -0
  115. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/compatibility/1/array_col.json +0 -0
  116. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/compatibility/1/array_col.pkl +0 -0
  117. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/compatibility/1/array_col.yaml +0 -0
  118. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/compatibility/1/array_col.zarr +0 -0
  119. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/compatibility/1/dict.json +0 -0
  120. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/compatibility/1/dict.pkl +0 -0
  121. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/compatibility/1/dict.yaml +0 -0
  122. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/compatibility/1/dict.zarr +0 -0
  123. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/compatibility/1/object.json +0 -0
  124. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/compatibility/1/object.pkl +0 -0
  125. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/compatibility/1/object.yaml +0 -0
  126. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/compatibility/1/object.zarr +0 -0
  127. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/compatibility/2/array.hdf +0 -0
  128. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/compatibility/2/array.json +0 -0
  129. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/compatibility/2/array.pkl +0 -0
  130. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/compatibility/2/array.yaml +0 -0
  131. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/compatibility/2/array.zip +0 -0
  132. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/compatibility/2/array_col.hdf +0 -0
  133. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/compatibility/2/array_col.json +0 -0
  134. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/compatibility/2/array_col.pkl +0 -0
  135. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/compatibility/2/array_col.yaml +0 -0
  136. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/compatibility/2/array_col.zip +0 -0
  137. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/compatibility/2/dict.hdf +0 -0
  138. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/compatibility/2/dict.json +0 -0
  139. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/compatibility/2/dict.pkl +0 -0
  140. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/compatibility/2/dict.yaml +0 -0
  141. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/compatibility/2/dict.zip +0 -0
  142. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/compatibility/2/nested.hdf +0 -0
  143. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/compatibility/2/nested.json +0 -0
  144. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/compatibility/2/nested.pkl +0 -0
  145. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/compatibility/2/nested.yaml +0 -0
  146. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/compatibility/2/nested.zip +0 -0
  147. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/conftest.py +0 -0
  148. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/helpers/__init__.py +0 -0
  149. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/helpers/asserts.py +0 -0
  150. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/helpers/storage.py +0 -0
  151. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/requirements.txt +0 -0
  152. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/run/scripts/function.py +0 -0
  153. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/run/scripts/script.py +0 -0
  154. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/run/test_run_main.py +0 -0
  155. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/scripts/empty.py +0 -0
  156. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/scripts/function.py +0 -0
  157. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/scripts/function_main.py +0 -0
  158. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/scripts/function_marked.py +0 -0
  159. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/scripts/make_model.py +0 -0
  160. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/scripts/make_model_class.py +0 -0
  161. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/scripts/make_model_marked.py +0 -0
  162. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/storage/test_storage_special.py +0 -0
  163. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/storage/test_utils.py +0 -0
  164. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/test_config.py +0 -0
  165. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/test_examples.py +0 -0
  166. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/test_main.py +0 -0
  167. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/test_parameters.py +0 -0
  168. {py-modelrunner-0.16.0 → py-modelrunner-0.17.0}/tests/test_version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: py-modelrunner
3
- Version: 0.16.0
3
+ Version: 0.17.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
@@ -43,11 +43,12 @@ The main requirements for the storage classes were
43
43
  - *Usability*: The user should not need to think about how data is stored in different files
44
44
  - *Flexibility*: We want a general interface to write data in multiple file formats (YAML, HDF, zarr, ...)
45
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)
46
+ - *Modularity*: Different parts of the package (like :mod:`~modelrunner.storage`, :mod:`~modelrunner.parameters`, and :mod:`~modelrunner.run`) should be rather independent of each other, so they can be used in isolation
47
+ - *Extensibility*: Models should be easy to subclass to implement more complicated requirements (e.g., additional parameters)
47
48
  - *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
49
  - *Efficiency*: The files should only store necessary information.
49
50
 
50
51
  The last point results in particular constraints if we want to store temporal simulation results.
51
52
  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
53
  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.
54
+ The :mod:`~modelrunner.storage.trajectory` module deals with such data.
@@ -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.data)
25
+ print(read.parameters, "–– start + [0..length-1] =", read.result)
@@ -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.data)
21
+ print(read.parameters, "–– a * b =", read.result)
@@ -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.data)
21
+ print(read.parameters, "–– a * b =", read.result)
@@ -24,4 +24,4 @@ with tempfile.NamedTemporaryFile(suffix=".yaml") as fp:
24
24
  # read the file and check whether all the data is there
25
25
  with open_storage(fp.name) as storage:
26
26
  print("Stored data:", storage["data"])
27
- print("Model result:", storage["result"].data)
27
+ print("Model result:", storage["result"].result)
@@ -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.data)
18
+ print(result.result)
@@ -0,0 +1 @@
1
+ /_version.py
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '0.16.0'
16
- __version_tuple__ = version_tuple = (0, 16, 0)
15
+ __version__ = version = '0.17.0'
16
+ __version_tuple__ = version_tuple = (0, 17, 0)
@@ -64,7 +64,11 @@ class ModelBase(Parameterized, metaclass=ABCMeta):
64
64
  :meth:`~Parameterized.get_parameters` or displayed by calling
65
65
  :meth:`~Parameterized.show_parameters`.
66
66
  output (str):
67
- Path where the output file will be written.
67
+ Path where the output file will be written. The output will be written
68
+ using :mod:`~modelrunner.storage` and might contain two groups: `result`
69
+ to which the final result of the model is written, and `data`, which
70
+ can contain extra information that is written using
71
+ :attr:`~ModelBase.storage`.
68
72
  mode (str or :class:`~modelrunner.storage.access_modes.ModeType`):
69
73
  The file mode with which the storage is accessed, which determines the
70
74
  allowed operations. Common options are "read", "full", "append", and
@@ -87,7 +91,9 @@ class ModelBase(Parameterized, metaclass=ABCMeta):
87
91
  if self.output is None:
88
92
  raise RuntimeError("Output file needs to be specified")
89
93
  self._storage = open_storage(self.output, mode=self.mode)
90
- return self._storage
94
+ return self._storage.create_group("data")
95
+ else:
96
+ return self._storage.open_group("data")
91
97
 
92
98
  def close(self) -> None:
93
99
  """close any opened storages"""
@@ -124,21 +130,21 @@ class ModelBase(Parameterized, metaclass=ABCMeta):
124
130
  result:
125
131
  The result data. If omitted, the model is run to obtain results
126
132
  """
133
+ from .results import Result # @Reimport
134
+
127
135
  if self.output is None:
128
136
  raise RuntimeError("Output file needs to be specified")
129
137
 
130
138
  if result is None:
131
139
  result = self.get_result()
132
- else:
133
- from .results import Result # @Reimport
134
-
135
- assert isinstance(result, Result)
140
+ elif not isinstance(result, Result):
141
+ raise TypeError(f"result has type {result.__class__} instead of `Result`")
136
142
 
137
143
  if self._storage is not None:
138
144
  # reuse the opened storage
139
- result.to_file(self.storage)
145
+ result.to_file(self._storage, loc="result")
140
146
  else:
141
- result.to_file(self.output, mode=self.mode)
147
+ result.to_file(self.output, loc="result", mode=self.mode)
142
148
 
143
149
  @classmethod
144
150
  def _prepare_argparser(cls, name: str | None = None) -> argparse.ArgumentParser:
@@ -47,7 +47,12 @@ class Result:
47
47
  """int: number indicating the version of the file format"""
48
48
 
49
49
  def __init__(
50
- self, model: ModelBase, result: Any, info: dict[str, Any] | None = None
50
+ self,
51
+ model: ModelBase,
52
+ result: Any,
53
+ *,
54
+ storage: StorageID = None,
55
+ info: dict[str, Any] | None = None,
51
56
  ):
52
57
  """
53
58
  Args:
@@ -55,18 +60,23 @@ class Result:
55
60
  The model from which the result was obtained
56
61
  result:
57
62
  The actual result
63
+ storage:
64
+ A storage containing additional data from the model run
58
65
  info (dict):
59
66
  Additional information for this result
60
67
  """
61
68
  if not isinstance(model, ModelBase):
62
69
  raise TypeError("The model should be of type `ModelBase`")
63
- self.model = model
64
70
  self.result = result
71
+ self.model = model
72
+ self.storage = storage
65
73
  self.info: Attrs = {} if info is None else info
66
74
 
67
75
  @property
68
76
  def data(self):
69
77
  """direct access to the underlying state data"""
78
+ # deprecated on 2024-04-13
79
+ warnings.warn("`.data` attribute was renamed to `.result`", DeprecationWarning)
70
80
  return self.result
71
81
 
72
82
  @classmethod
@@ -74,7 +84,9 @@ class Result:
74
84
  cls,
75
85
  model_data: dict[str, Any],
76
86
  result,
87
+ *,
77
88
  model: ModelBase | None = None,
89
+ storage: StorageID = None,
78
90
  info: dict[str, Any] | None = None,
79
91
  ) -> Result:
80
92
  """create result from data
@@ -86,6 +98,8 @@ class Result:
86
98
  The actual result data
87
99
  model (:class:`ModelBase`):
88
100
  The model from which the result was obtained
101
+ storage:
102
+ A storage containing additional data from the model run
89
103
  info (dict):
90
104
  Additional information for this result
91
105
 
@@ -103,7 +117,7 @@ class Result:
103
117
  model.name = model_data.get("name")
104
118
  model.description = model_data.get("description")
105
119
 
106
- return cls(model, result, info)
120
+ return cls(model, result, storage=storage, info=info)
107
121
 
108
122
  @property
109
123
  def parameters(self) -> dict[str, Any]:
@@ -119,13 +133,20 @@ class Result:
119
133
  ):
120
134
  """load object from a file
121
135
 
136
+ This function loads the results from a hierachical storage. It also attempts to
137
+ read information about the model that was used to create this result and
138
+ additional data that might have been stored in a
139
+ :attr:`~modelrunner.results.Result.storage` while the model was running.
140
+
122
141
  Args:
123
142
  store (str or :class:`zarr.Store`):
124
143
  Path or instance describing the storage, which is either a file path or
125
144
  a :class:`zarr.Storage`.
126
- key (str):
127
- Name of the node in which the data was stored. This applies to some
128
- hierarchical storage formats.
145
+ loc:
146
+ The location where the result is stored in the storage. This should
147
+ rarely be modified.
148
+ model (:class:`~modelrunner.model.ModelBase`):
149
+ The model which lead to this result
129
150
  """
130
151
  if isinstance(storage, (str, Path)):
131
152
  # check whether the file was written with an old format version
@@ -141,10 +162,15 @@ class Result:
141
162
  format_version = attrs.pop("format_version", None)
142
163
  if format_version == cls._format_version:
143
164
  # current version of storing results
165
+ if "data" in storage_obj:
166
+ data_storage = open_storage(storage, loc="data", mode="read")
167
+ else:
168
+ data_storage = None
144
169
  return cls.from_data(
145
170
  model_data=attrs.get("model", {}),
146
171
  result=storage_obj.read_item(loc, use_class=False),
147
172
  model=model,
173
+ storage=data_storage,
148
174
  info=attrs.pop("info", {}), # load additional info,
149
175
  )
150
176
 
@@ -154,7 +180,10 @@ class Result:
154
180
  def to_file(
155
181
  self, storage: StorageID, loc: str = "result", *, mode: ModeType = "insert"
156
182
  ) -> None:
157
- """write this object to a file
183
+ """write the results to a file
184
+
185
+ Note that this does only write the actual `results` but omits additional data
186
+ that might have been stored in a storage that is associated with the results.
158
187
 
159
188
  Args:
160
189
  storage (:class:`StorageBase` or :class:`StorageGroup`):
@@ -11,7 +11,7 @@ import itertools
11
11
  import json
12
12
  import logging
13
13
  import os
14
- import pipes
14
+ import shlex
15
15
  import subprocess as sp
16
16
  import sys
17
17
  import warnings
@@ -26,7 +26,7 @@ from ..parameters import Parameter
26
26
 
27
27
  def escape_string(obj) -> str:
28
28
  """escape a string for the command line"""
29
- return pipes.quote(str(obj))
29
+ return shlex.quote(str(obj))
30
30
 
31
31
 
32
32
  def ensure_directory_exists(folder):
@@ -130,7 +130,7 @@ def submit_job(
130
130
  parameters: str | dict[str, Any] | None = None,
131
131
  config: str | dict[str, Any] | None = None,
132
132
  *,
133
- log_folder: str | Path = "logs",
133
+ log_folder: str | Path | None = None,
134
134
  method: str = "auto",
135
135
  use_modelrunner: bool = True,
136
136
  template: str | Path | None = None,
@@ -153,7 +153,10 @@ def submit_job(
153
153
  Configuration for the job, which determines how the job is run. Can be either
154
154
  a python dictionary or a string containing a JSON-encoded dictionary.
155
155
  log_folder (str of :class:`~pathlib.Path`):
156
- Path to the logging folder
156
+ Path to the logging folder. If omitted, the default of the template is used,
157
+ which typically sends data to stdout for local scripts (which is thus
158
+ captured and returned by this function) or writes log files to the current
159
+ working directory for remote jobs.
157
160
  method (str):
158
161
  Specifies the submission method. Currently `background`, `foreground`,
159
162
  'srun', and `qsub` are supported. The special value `auto` reads the method
@@ -169,7 +172,9 @@ def submit_job(
169
172
  `error`, `warn_skip`, `silent_skip`, `overwrite`, and `silent_overwrite`.
170
173
 
171
174
  Returns:
172
- tuple: The result `(stdout, stderr)` of the submission call
175
+ tuple: The result `(stdout, stderr)` of the submission call. These two strings
176
+ can contain the output from the actual scripts that is run when `log_folder`
177
+ is `None`.
173
178
  """
174
179
  from jinja2 import Template
175
180
 
@@ -191,7 +196,7 @@ def submit_job(
191
196
 
192
197
  # load the correct template
193
198
  if template is None:
194
- template_path = Path(__file__).parent / "templates" / (method + ".template")
199
+ template_path = Path(__file__).parent / "templates" / (method + ".jinja")
195
200
  else:
196
201
  template_path = Path(template)
197
202
  logger.info("Load template `%s`", template_path)
@@ -199,15 +204,16 @@ def submit_job(
199
204
  script_template = fp.read()
200
205
 
201
206
  # prepare submission script
202
- ensure_directory_exists(log_folder)
203
207
  script_args: dict[str, Any] = {
204
208
  "PACKAGE_PATH": Path(__file__).parents[2],
205
- "LOG_FOLDER": log_folder,
206
209
  "JOB_NAME": name,
207
210
  "MODEL_FILE": escape_string(script),
208
211
  "USE_MODELRUNNER": use_modelrunner,
209
212
  "CONFIG": configuration,
210
213
  }
214
+ if log_folder is not None:
215
+ ensure_directory_exists(log_folder)
216
+ script_args["LOG_FOLDER"] = log_folder
211
217
 
212
218
  # add the parameters to the job arguments
213
219
  job_args = []
@@ -244,9 +250,9 @@ def submit_job(
244
250
 
245
251
  # check whether output points to a directory or whether this should be a file
246
252
  if output.is_dir():
247
- script_args["OUTPUT_FOLDER"] = pipes.quote(str(output))
253
+ script_args["OUTPUT_FOLDER"] = shlex.quote(str(output))
248
254
  else:
249
- script_args["OUTPUT_FOLDER"] = pipes.quote(str(output.parent))
255
+ script_args["OUTPUT_FOLDER"] = shlex.quote(str(output.parent))
250
256
  job_args.append(f"--output {escape_string(output)}")
251
257
 
252
258
  else:
@@ -0,0 +1,27 @@
1
+ #!/bin/bash -l
2
+
3
+ export PYTHONPATH={{ PACKAGE_PATH }}:$PYTHONPATH
4
+
5
+ {% if CONFIG.num_threads is number %}
6
+ # set the number of threads to use
7
+ export MKL_NUM_THREADS={{ CONFIG.num_threads }}
8
+ export NUMBA_NUM_THREADS={{ CONFIG.num_threads }}
9
+ export NUMEXPR_NUM_THREADS={{ CONFIG.num_threads }}
10
+ export OMP_NUM_THREADS={{ CONFIG.num_threads }}
11
+ export OPENBLAS_NUM_THREADS={{ CONFIG.num_threads }}
12
+ {% endif %}
13
+
14
+ {% if OUTPUT_FOLDER is defined and OUTPUT_FOLDER %}
15
+ mkdir -p {{ OUTPUT_FOLDER }}
16
+ {% endif %}
17
+
18
+ # Run the program in the background
19
+ nohup {{ CONFIG.python_bin }} \
20
+ {% if USE_MODELRUNNER is defined and USE_MODELRUNNER %} -m modelrunner {% endif %} \
21
+ {{ MODEL_FILE }} \
22
+ {{ JOB_ARGS }} \
23
+ {% if LOG_FOLDER is defined -%}
24
+ > {{ LOG_FOLDER }}/{{ JOB_NAME }}.out.txt \
25
+ 2> {{ LOG_FOLDER }}/{{ JOB_NAME }}.err.txt \
26
+ {% endif -%}
27
+ &
@@ -0,0 +1,26 @@
1
+ #!/bin/bash -l
2
+
3
+ export PYTHONPATH={{ PACKAGE_PATH }}:$PYTHONPATH
4
+
5
+ {% if CONFIG.num_threads is number %}
6
+ # set the number of threads to use
7
+ export MKL_NUM_THREADS={{ CONFIG.num_threads }}
8
+ export NUMBA_NUM_THREADS={{ CONFIG.num_threads }}
9
+ export NUMEXPR_NUM_THREADS={{ CONFIG.num_threads }}
10
+ export OMP_NUM_THREADS={{ CONFIG.num_threads }}
11
+ export OPENBLAS_NUM_THREADS={{ CONFIG.num_threads }}
12
+ {% endif %}
13
+
14
+ {% if OUTPUT_FOLDER is defined and OUTPUT_FOLDER %}
15
+ mkdir -p {{ OUTPUT_FOLDER }}
16
+ {% endif %}
17
+
18
+ # Run the program
19
+ {{ CONFIG.python_bin }} \
20
+ {% if USE_MODELRUNNER is defined and USE_MODELRUNNER %} -m modelrunner {% endif %} \
21
+ {{ MODEL_FILE }} \
22
+ {{ JOB_ARGS }} \
23
+ {% if LOG_FOLDER is defined -%}
24
+ > {{ LOG_FOLDER }}/{{ JOB_NAME }}.out.txt \
25
+ 2> {{ LOG_FOLDER }}/{{ JOB_NAME }}.err.txt \
26
+ {% endif -%}
@@ -18,13 +18,13 @@
18
18
  hostname
19
19
  echo $JOB_ID
20
20
 
21
- {% if CONFIG['num_threads'] is number %}
21
+ {% if CONFIG.num_threads is number %}
22
22
  # set the number of threads to use
23
- export MKL_NUM_THREADS={{ CONFIG['num_threads'] }}
24
- export NUMBA_NUM_THREADS={{ CONFIG['num_threads'] }}
25
- export NUMEXPR_NUM_THREADS={{ CONFIG['num_threads'] }}
26
- export OMP_NUM_THREADS={{ CONFIG['num_threads'] }}
27
- export OPENBLAS_NUM_THREADS={{ CONFIG['num_threads'] }}
23
+ export MKL_NUM_THREADS={{ CONFIG.num_threads }}
24
+ export NUMBA_NUM_THREADS={{ CONFIG.num_threads }}
25
+ export NUMEXPR_NUM_THREADS={{ CONFIG.num_threads }}
26
+ export OMP_NUM_THREADS={{ CONFIG.num_threads }}
27
+ export OPENBLAS_NUM_THREADS={{ CONFIG.num_threads }}
28
28
  {% endif %}
29
29
 
30
30
  {% if OUTPUT_FOLDER is defined and OUTPUT_FOLDER %}
@@ -33,7 +33,7 @@ mkdir -p {{ OUTPUT_FOLDER }}
33
33
 
34
34
  # Run the program
35
35
  {% if USE_MODELRUNNER is defined and USE_MODELRUNNER %}
36
- {{ CONFIG['python_bin'] }} -m modelrunner {{ MODEL_FILE }} {{ JOB_ARGS }}
36
+ {{ CONFIG.python_bin }} -m modelrunner {{ MODEL_FILE }} {{ JOB_ARGS }}
37
37
  {% else %}
38
- {{ CONFIG['python_bin'] }} {{ MODEL_FILE }} {{ JOB_ARGS }}
38
+ {{ CONFIG.python_bin }} {{ MODEL_FILE }} {{ JOB_ARGS }}
39
39
  {% endif %}
@@ -16,13 +16,13 @@
16
16
  hostname
17
17
  echo $JOB_ID
18
18
 
19
- {% if CONFIG['num_threads'] is number %}
19
+ {% if CONFIG.num_threads is number %}
20
20
  # set the number of threads to use
21
- export MKL_NUM_THREADS={{ CONFIG['num_threads'] }}
22
- export NUMBA_NUM_THREADS={{ CONFIG['num_threads'] }}
23
- export NUMEXPR_NUM_THREADS={{ CONFIG['num_threads'] }}
24
- export OMP_NUM_THREADS={{ CONFIG['num_threads'] }}
25
- export OPENBLAS_NUM_THREADS={{ CONFIG['num_threads'] }}
21
+ export MKL_NUM_THREADS={{ CONFIG.num_threads }}
22
+ export NUMBA_NUM_THREADS={{ CONFIG.num_threads }}
23
+ export NUMEXPR_NUM_THREADS={{ CONFIG.num_threads }}
24
+ export OMP_NUM_THREADS={{ CONFIG.num_threads }}
25
+ export OPENBLAS_NUM_THREADS={{ CONFIG.num_threads }}
26
26
  {% endif %}
27
27
 
28
28
  {% if OUTPUT_FOLDER is defined and OUTPUT_FOLDER %}
@@ -31,7 +31,7 @@ mkdir -p {{ OUTPUT_FOLDER }}
31
31
 
32
32
  # Run the program
33
33
  {% if USE_MODELRUNNER is defined and USE_MODELRUNNER %}
34
- {{ CONFIG['python_bin'] }} -m modelrunner {{ MODEL_FILE }} {{ JOB_ARGS }}
34
+ {{ CONFIG.python_bin }} -m modelrunner {{ MODEL_FILE }} {{ JOB_ARGS }}
35
35
  {% else %}
36
- {{ CONFIG['python_bin'] }} {{ MODEL_FILE }} {{ JOB_ARGS }}
36
+ {{ CONFIG.python_bin }} {{ MODEL_FILE }} {{ JOB_ARGS }}
37
37
  {% endif %}
@@ -56,17 +56,20 @@ class MemoryStorage(StorageBase):
56
56
  (group, str):
57
57
  A tuple consisting of the parent group and the name of the current item
58
58
  """
59
- value = self._data
59
+ if check_write and not self.is_group(loc[:-1]):
60
+ raise TypeError(f"Location `/{'/'.join(loc[:-1])}` is not a group")
61
+
62
+ parent = self._data
60
63
  for part in loc[:-1]:
61
64
  try:
62
- value = value[part]
65
+ parent = parent[part]
63
66
  except KeyError:
64
- if isinstance(value, dict):
65
- value[part] = {}
66
- value = value[part]
67
+ if isinstance(parent, dict):
68
+ parent[part] = {}
69
+ parent = parent[part]
67
70
  else:
68
71
  raise TypeError(f"Cannot add item to `/{'/'.join(loc)}`")
69
- if not isinstance(value, dict):
72
+ if not isinstance(parent, dict):
70
73
  raise TypeError(f"Cannot add item to `/{'/'.join(loc)}`")
71
74
 
72
75
  try:
@@ -74,14 +77,17 @@ class MemoryStorage(StorageBase):
74
77
  except IndexError:
75
78
  raise KeyError(f"Location `/{'/'.join(loc)}` has no parent")
76
79
 
77
- if check_write and not self.mode.overwrite and name in value:
80
+ if check_write and not self.mode.overwrite and name in parent:
78
81
  raise AccessError(f"Overwriting `/{'/'.join(loc)}` disabled")
79
- return value, name
82
+ return parent, name
80
83
 
81
84
  def __getitem__(self, loc: Sequence[str]) -> Any:
82
85
  if loc:
83
86
  parent, name = self._get_parent(loc)
84
- return parent[name]
87
+ try:
88
+ return parent[name]
89
+ except KeyError as e:
90
+ raise KeyError(f"Item `{name}` not in group {parent.keys()}") from e
85
91
  else:
86
92
  return self._data
87
93
 
@@ -57,6 +57,37 @@ class StorageGroup:
57
57
  def __repr__(self):
58
58
  return f'StorageGroup(storage={self._storage}, loc="/{"/".join(self.loc)}")'
59
59
 
60
+ def tree(self) -> None:
61
+ """print the hierarchical storage as a tree structure"""
62
+ vertic = "│ "
63
+ cross = "├──"
64
+ corner = "└──"
65
+ space = " "
66
+
67
+ def print_tree(loc: list[str], header: str = ""):
68
+ """recursive function printing information about one group"""
69
+ group = StorageGroup(self._storage, loc)
70
+ for i, key in enumerate(sorted(group.keys())):
71
+ last = i == len(group) - 1
72
+ if self._storage.is_group(loc + [key]):
73
+ cls = self._storage._read_attrs(loc).get("__class__")
74
+ if cls is None:
75
+ # item is a sub group
76
+ print(header + (corner if last else cross) + key)
77
+ print_tree(
78
+ loc + [key], header=header + (space if last else vertic)
79
+ )
80
+ else:
81
+ # item contains information to restore a certain class
82
+ print(header + (corner if last else cross) + f"{key} ({cls})")
83
+ else:
84
+ # item is a simple, scalar item
85
+ print(header + (corner if last else cross) + key)
86
+
87
+ if self.loc:
88
+ print("/" + "/".join(self.loc))
89
+ print_tree(self.loc)
90
+
60
91
  def _get_loc(self, loc: Location) -> list[str]:
61
92
  """return a normalized location from various input
62
93
 
@@ -74,7 +105,7 @@ class StorageGroup:
74
105
  if loc_data is None or loc_data == "":
75
106
  return []
76
107
  elif isinstance(loc_data, str):
77
- return loc_data.split("/")
108
+ return loc_data.strip("/").split("/")
78
109
  else:
79
110
  return sum((parse_loc(k) for k in loc_data), start=list())
80
111
 
@@ -82,11 +113,11 @@ class StorageGroup:
82
113
 
83
114
  def __getitem__(self, loc: Location) -> Any:
84
115
  """read state or trajectory from storage"""
85
- loc = self._get_loc(loc)
86
- if self._storage.is_group(loc): # storage points to a group
87
- if "__class__" not in self._storage._read_attrs(loc):
116
+ loc_list = self._get_loc(loc)
117
+ if self._storage.is_group(loc_list): # storage points to a group
118
+ if "__class__" not in self._storage._read_attrs(loc_list):
88
119
  # group does not contain class information => just return a subgroup
89
- return StorageGroup(self._storage, loc)
120
+ return StorageGroup(self._storage, loc_list)
90
121
  # reconstruct objected stored at this place
91
122
  return self.read_item(loc, use_class=True)
92
123
 
@@ -97,6 +128,9 @@ class StorageGroup:
97
128
  """return name of all stored items in this group"""
98
129
  return self._storage.keys(self.loc)
99
130
 
131
+ def __len__(self) -> int:
132
+ return len(self.keys())
133
+
100
134
  def __iter__(self) -> Iterator[Any]:
101
135
  """iterate over all stored items in this group"""
102
136
  for loc in self.keys():
@@ -169,15 +203,15 @@ class StorageGroup:
169
203
  Returns:
170
204
  The reconstructed python object
171
205
  """
172
- loc_list = self._get_loc(loc)
173
206
  if use_class:
174
- cls = self.get_class(loc_list)
207
+ cls = self.get_class(loc)
175
208
  if cls is not None:
176
209
  # create object using a registered action
177
210
  read_item = storage_actions.get(cls, "read_item")
178
- return read_item(self._storage, loc_list)
211
+ return read_item(self._storage, loc)
179
212
 
180
213
  # read the item using the generic classes
214
+ loc_list = self._get_loc(loc)
181
215
  obj_type = self._storage._read_attrs(loc_list).get("__type__")
182
216
  if obj_type in {"array", "dynamic_array"}:
183
217
  arr = self._storage.read_array(loc_list)
@@ -48,7 +48,9 @@ class open_storage(StorageGroup):
48
48
  r"""
49
49
  Args:
50
50
  storage:
51
- The path to a file or directory or a :class:`StorageBase` instance
51
+ The path to a file or directory or a :class:`StorageBase` instance. The
52
+ special value `None` creates a
53
+ :class:`~modelrunner.storage.backend.memory.MemoryStorage`
52
54
  loc (str or list of str):
53
55
  Denotes the location that will be opened within the storage. The default
54
56
  `None` opens the root group of the storage.
@@ -60,6 +62,7 @@ class open_storage(StorageGroup):
60
62
  All other arguments are passed on to the storage class
61
63
  """
62
64
  store_obj: StorageBase | None = None
65
+
63
66
  if isinstance(storage, StorageBase):
64
67
  # storage is of type `StorageBase`
65
68
  self._close = False
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: py-modelrunner
3
- Version: 0.16.0
3
+ Version: 0.17.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
@@ -38,6 +38,7 @@ examples/submit_function.py
38
38
  examples/submit_many_func.py
39
39
  examples/submit_many_iter.py
40
40
  examples/submit_shebang.py
41
+ modelrunner/.gitignore
41
42
  modelrunner/__init__.py
42
43
  modelrunner/__main__.py
43
44
  modelrunner/_version.py
@@ -54,10 +55,10 @@ modelrunner/compatibility/version1.py
54
55
  modelrunner/run/__init__.py
55
56
  modelrunner/run/__main__.py
56
57
  modelrunner/run/job.py
57
- modelrunner/run/templates/background.template
58
- modelrunner/run/templates/foreground.template
59
- modelrunner/run/templates/qsub.template
60
- modelrunner/run/templates/srun.template
58
+ modelrunner/run/templates/background.jinja
59
+ modelrunner/run/templates/foreground.jinja
60
+ modelrunner/run/templates/qsub.jinja
61
+ modelrunner/run/templates/srun.jinja
61
62
  modelrunner/storage/__init__.py
62
63
  modelrunner/storage/access_modes.py
63
64
  modelrunner/storage/attributes.py
@@ -145,7 +146,9 @@ tests/helpers/asserts.py
145
146
  tests/helpers/storage.py
146
147
  tests/run/test_job.py
147
148
  tests/run/test_run_main.py
149
+ tests/run/scripts/fail.py
148
150
  tests/run/scripts/function.py
151
+ tests/run/scripts/print.py
149
152
  tests/run/scripts/script.py
150
153
  tests/scripts/empty.py
151
154
  tests/scripts/function.py