py-modelrunner 0.19.1__tar.gz → 0.20.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.
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/.github/workflows/build.yml +1 -1
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/.github/workflows/coverage_report.yml +1 -1
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/.github/workflows/release_pip.yml +1 -1
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/.readthedocs.yaml +1 -1
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/PKG-INFO +5 -6
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/docs/source/installation.rst +1 -1
- py_modelrunner-0.20.0/modelrunner/_version.py +24 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/modelrunner/model/factory.py +2 -1
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/modelrunner/model/parameters.py +4 -4
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/modelrunner/run/compatibility/triage.py +6 -6
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/modelrunner/run/compatibility/version1.py +3 -4
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/modelrunner/run/job.py +1 -1
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/modelrunner/run/launch.py +1 -2
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/modelrunner/run/results.py +1 -1
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/modelrunner/storage/access_modes.py +2 -2
- py_modelrunner-0.19.1/modelrunner/storage/backend/zarr.py → py_modelrunner-0.20.0/modelrunner/storage/backend/_zarr2.py +9 -5
- py_modelrunner-0.20.0/modelrunner/storage/backend/_zarr3.py +240 -0
- py_modelrunner-0.20.0/modelrunner/storage/backend/zarr.py +20 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/modelrunner/storage/tools.py +2 -3
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/modelrunner/storage/trajectory.py +5 -7
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/modelrunner/storage/utils.py +3 -3
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/modelrunner/utils.py +3 -2
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/py_modelrunner.egg-info/PKG-INFO +5 -6
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/py_modelrunner.egg-info/SOURCES.txt +5 -2
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/py_modelrunner.egg-info/requires.txt +2 -2
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/pyproject.toml +6 -12
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/requirements.txt +1 -1
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/requirements_full.txt +1 -1
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/scripts/format_code.sh +2 -2
- {py_modelrunner-0.19.1/tests → py_modelrunner-0.20.0/scripts}/requirements.txt +0 -3
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/scripts/run_tests.py +4 -4
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/test_compatibility.py +4 -2
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/helpers/asserts.py +2 -2
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/helpers/storage.py +18 -7
- py_modelrunner-0.20.0/tests/requirements.txt +4 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/run/scripts/fail.py +1 -1
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/run/scripts/function.py +1 -1
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/run/scripts/print.py +1 -1
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/run/test_results.py +0 -1
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/storage/test_register_action.py +1 -1
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/storage/test_storage_generic.py +5 -4
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/storage/test_storage_special.py +20 -8
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/storage/test_trajectory.py +8 -14
- py_modelrunner-0.19.1/modelrunner/_version.py +0 -34
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/.github/workflows/check_docs.yml +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/.gitignore +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/LICENSE +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/README.md +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/docs/Makefile +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/docs/build_all.sh +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/docs/requirements.txt +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/docs/source/.gitignore +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/docs/source/conf.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/docs/source/examples.rst +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/docs/source/index.rst +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/docs/source/parse_examples.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/docs/source/run_autodoc.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/docs/source/sphinx_simplify_typehints.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/docs/source/user_manual.rst +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/examples/io_hdf.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/examples/io_json.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/examples/io_yaml.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/examples/model_class.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/examples/model_decorator.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/examples/model_function.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/examples/model_storage_output.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/examples/read_many.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/examples/script_custom_func.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/examples/script_function.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/examples/script_many_classes.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/examples/script_minimal.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/examples/script_model_class.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/examples/submit_function.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/examples/submit_many_func.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/examples/submit_many_iter.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/examples/submit_shebang.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/modelrunner/.gitignore +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/modelrunner/__init__.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/modelrunner/__main__.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/modelrunner/config.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/modelrunner/model/__init__.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/modelrunner/model/base.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/modelrunner/py.typed +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/modelrunner/run/__init__.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/modelrunner/run/__main__.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/modelrunner/run/compatibility/__init__.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/modelrunner/run/compatibility/version0.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/modelrunner/run/compatibility/version2.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/modelrunner/run/templates/background.jinja +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/modelrunner/run/templates/foreground.jinja +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/modelrunner/run/templates/qsub.jinja +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/modelrunner/run/templates/srun.jinja +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/modelrunner/storage/__init__.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/modelrunner/storage/attributes.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/modelrunner/storage/backend/__init__.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/modelrunner/storage/backend/hdf.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/modelrunner/storage/backend/json.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/modelrunner/storage/backend/memory.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/modelrunner/storage/backend/text_base.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/modelrunner/storage/backend/utils.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/modelrunner/storage/backend/yaml.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/modelrunner/storage/base.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/modelrunner/storage/group.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/py_modelrunner.egg-info/dependency_links.txt +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/py_modelrunner.egg-info/not-zip-safe +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/py_modelrunner.egg-info/top_level.txt +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/scripts/create_compatibility_files.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/scripts/performance_hdf5_zarr.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/scripts/tests_all.sh +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/scripts/tests_codestyle.sh +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/scripts/tests_coverage.sh +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/scripts/tests_debug.sh +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/scripts/tests_parallel.sh +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/scripts/tests_run.sh +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/scripts/tests_types.sh +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/setup.cfg +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/0/result.hdf +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/0/result.json +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/0/result.pkl +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/0/result.yaml +0 -0
- /py_modelrunner-0.19.1/tests/compatibility/1/dict.zarr → /py_modelrunner-0.20.0/tests/compatibility/1/_dict.zarr +0 -0
- /py_modelrunner-0.19.1/tests/compatibility/1/object.zarr → /py_modelrunner-0.20.0/tests/compatibility/1/_object.zarr +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/1/array.json +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/1/array.pkl +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/1/array.yaml +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/1/array.zarr +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/1/array_col.json +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/1/array_col.pkl +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/1/array_col.yaml +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/1/array_col.zarr +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/1/dict.json +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/1/dict.pkl +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/1/dict.yaml +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/1/object.json +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/1/object.pkl +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/1/object.yaml +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/2/array.hdf +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/2/array.json +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/2/array.pkl +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/2/array.yaml +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/2/array.zip +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/2/array_col.hdf +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/2/array_col.json +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/2/array_col.pkl +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/2/array_col.yaml +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/2/array_col.zip +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/2/dict.hdf +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/2/dict.json +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/2/dict.pkl +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/2/dict.yaml +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/2/dict.zip +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/2/nested.hdf +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/2/nested.json +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/2/nested.pkl +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/2/nested.yaml +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/2/nested.zip +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/3/array.hdf +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/3/array.json +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/3/array.pkl +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/3/array.yaml +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/3/array.zip +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/3/array_col.hdf +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/3/array_col.json +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/3/array_col.pkl +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/3/array_col.yaml +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/3/array_col.zip +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/3/dict.hdf +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/3/dict.json +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/3/dict.pkl +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/3/dict.yaml +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/3/dict.zip +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/3/model_array.hdf +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/3/model_array.json +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/3/model_array.pkl +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/3/model_array.yaml +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/3/model_array.zip +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/3/model_array_col.hdf +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/3/model_array_col.json +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/3/model_array_col.pkl +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/3/model_array_col.yaml +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/3/model_array_col.zip +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/3/model_dict.hdf +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/3/model_dict.json +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/3/model_dict.pkl +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/3/model_dict.yaml +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/3/model_dict.zip +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/3/model_nested.hdf +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/3/model_nested.json +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/3/model_nested.pkl +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/3/model_nested.yaml +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/3/model_nested.zip +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/3/nested.hdf +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/3/nested.json +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/3/nested.pkl +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/3/nested.yaml +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/compatibility/3/nested.zip +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/conftest.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/helpers/__init__.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/model/scripts/empty.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/model/scripts/function.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/model/scripts/function_main.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/model/scripts/function_marked.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/model/scripts/make_model.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/model/scripts/make_model_class.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/model/scripts/make_model_marked.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/model/test_model.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/model/test_parameters.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/run/scripts/custom.jinja +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/run/scripts/script.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/run/test_job.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/run/test_run_main.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/storage/test_group.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/storage/test_utils.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/test_config.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/test_examples.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/test_main.py +0 -0
- {py_modelrunner-0.19.1 → py_modelrunner-0.20.0}/tests/test_version.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: py-modelrunner
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.20.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
|
|
@@ -14,23 +14,22 @@ Classifier: Topic :: Scientific/Engineering
|
|
|
14
14
|
Classifier: Topic :: Utilities
|
|
15
15
|
Classifier: License :: OSI Approved :: MIT License
|
|
16
16
|
Classifier: Programming Language :: Python :: 3
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
19
17
|
Classifier: Programming Language :: Python :: 3.11
|
|
20
18
|
Classifier: Programming Language :: Python :: 3.12
|
|
21
19
|
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
-
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
21
|
+
Requires-Python: <3.15,>=3.11
|
|
23
22
|
Description-Content-Type: text/markdown
|
|
24
23
|
License-File: LICENSE
|
|
25
24
|
Requires-Dist: jinja2>=3
|
|
26
25
|
Requires-Dist: numpy>=1.18.0
|
|
27
26
|
Requires-Dist: tqdm>=4.45
|
|
28
|
-
Requires-Dist: numcodecs>=0.
|
|
27
|
+
Requires-Dist: numcodecs>=0.16
|
|
29
28
|
Provides-Extra: all
|
|
30
29
|
Requires-Dist: h5py>=3.5; extra == "all"
|
|
31
30
|
Requires-Dist: pandas>=1.3; extra == "all"
|
|
32
31
|
Requires-Dist: PyYAML>=5; extra == "all"
|
|
33
|
-
Requires-Dist: zarr<3
|
|
32
|
+
Requires-Dist: zarr<4,>=3; extra == "all"
|
|
34
33
|
Provides-Extra: test
|
|
35
34
|
Requires-Dist: black>=19; extra == "test"
|
|
36
35
|
Requires-Dist: isort>=5.1; extra == "test"
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# file generated by vcs-versioning
|
|
2
|
+
# don't change, don't track in version control
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
__all__ = [
|
|
6
|
+
"__version__",
|
|
7
|
+
"__version_tuple__",
|
|
8
|
+
"version",
|
|
9
|
+
"version_tuple",
|
|
10
|
+
"__commit_id__",
|
|
11
|
+
"commit_id",
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
version: str
|
|
15
|
+
__version__: str
|
|
16
|
+
__version_tuple__: tuple[int | str, ...]
|
|
17
|
+
version_tuple: tuple[int | str, ...]
|
|
18
|
+
commit_id: str | None
|
|
19
|
+
__commit_id__: str | None
|
|
20
|
+
|
|
21
|
+
__version__ = version = '0.20.0'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 20, 0)
|
|
23
|
+
|
|
24
|
+
__commit_id__ = commit_id = 'ga172a6158'
|
|
@@ -7,7 +7,8 @@ from __future__ import annotations
|
|
|
7
7
|
|
|
8
8
|
import functools
|
|
9
9
|
import inspect
|
|
10
|
-
from
|
|
10
|
+
from collections.abc import Callable
|
|
11
|
+
from typing import TYPE_CHECKING, Any, Literal, TypeVar, get_args, get_origin
|
|
11
12
|
|
|
12
13
|
from ..storage import ModeType
|
|
13
14
|
from .base import ModelBase
|
|
@@ -19,9 +19,9 @@ from __future__ import annotations
|
|
|
19
19
|
import copy
|
|
20
20
|
import logging
|
|
21
21
|
import warnings
|
|
22
|
-
from collections.abc import Container, Iterator
|
|
22
|
+
from collections.abc import Callable, Container, Iterator
|
|
23
23
|
from dataclasses import dataclass, field
|
|
24
|
-
from typing import Any
|
|
24
|
+
from typing import Any
|
|
25
25
|
|
|
26
26
|
import numpy as np
|
|
27
27
|
|
|
@@ -280,8 +280,8 @@ class HideParameter:
|
|
|
280
280
|
pass
|
|
281
281
|
|
|
282
282
|
|
|
283
|
-
ParameterListType = list[
|
|
284
|
-
ParameterInputType =
|
|
283
|
+
ParameterListType = list[Parameter | HideParameter]
|
|
284
|
+
ParameterInputType = dict[str, Any] | None
|
|
285
285
|
|
|
286
286
|
|
|
287
287
|
class Parameterized:
|
|
@@ -147,12 +147,12 @@ def _get_format_version(path: Path, label: str) -> int | None:
|
|
|
147
147
|
store = normalize_zarr_store(path, mode="r")
|
|
148
148
|
if store is None:
|
|
149
149
|
raise RuntimeError
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
150
|
+
root = zarr.open_group(store, mode="r")
|
|
151
|
+
format_version = _find_version(root, label)
|
|
152
|
+
if format_version is None and label != "data":
|
|
153
|
+
format_version = _find_version(root, "data")
|
|
154
|
+
if format_version is not None:
|
|
155
|
+
label = "data"
|
|
156
156
|
|
|
157
157
|
else:
|
|
158
158
|
raise RuntimeError
|
|
@@ -7,9 +7,8 @@ from __future__ import annotations
|
|
|
7
7
|
|
|
8
8
|
import json
|
|
9
9
|
import warnings
|
|
10
|
-
from abc import ABCMeta
|
|
11
10
|
from pathlib import Path
|
|
12
|
-
from typing import TYPE_CHECKING, Any, TypeVar
|
|
11
|
+
from typing import TYPE_CHECKING, Any, TypeVar
|
|
13
12
|
|
|
14
13
|
import numpy as np
|
|
15
14
|
|
|
@@ -20,7 +19,7 @@ from .triage import guess_format, normalize_zarr_store
|
|
|
20
19
|
if TYPE_CHECKING:
|
|
21
20
|
import zarr
|
|
22
21
|
|
|
23
|
-
zarrElement =
|
|
22
|
+
zarrElement = zarr.Group | zarr.Array
|
|
24
23
|
|
|
25
24
|
|
|
26
25
|
class NoData:
|
|
@@ -119,7 +118,7 @@ class StateBase:
|
|
|
119
118
|
raise TypeError(f"Do not know how to load `{cls_name}`")
|
|
120
119
|
|
|
121
120
|
@classmethod
|
|
122
|
-
def _from_zarr(cls, zarr_element: zarrElement, *, index=...) -> StateBase:
|
|
121
|
+
def _from_zarr(cls, zarr_element: zarrElement, *, index=...) -> StateBase: # type: ignore
|
|
123
122
|
"""Create instance of correct subclass from data stored in zarr."""
|
|
124
123
|
# determine the class that knows how to read this data
|
|
125
124
|
cls_name = zarr_element.attrs["__class__"]
|
|
@@ -9,9 +9,8 @@ import importlib.util
|
|
|
9
9
|
import inspect
|
|
10
10
|
import logging
|
|
11
11
|
import os.path
|
|
12
|
-
from collections.abc import Sequence
|
|
12
|
+
from collections.abc import Callable, Sequence
|
|
13
13
|
from pathlib import Path
|
|
14
|
-
from typing import Callable
|
|
15
14
|
|
|
16
15
|
from ..model import ModelBase, cleared_default_model, factory, make_model_class
|
|
17
16
|
from .results import Result
|
|
@@ -411,7 +411,7 @@ class ResultCollection(list[Result]):
|
|
|
411
411
|
group_values = [self.parameters[name] for name in args]
|
|
412
412
|
|
|
413
413
|
for group_value in itertools.product(*group_values):
|
|
414
|
-
group_parameters = dict(zip(args, group_value))
|
|
414
|
+
group_parameters = dict(zip(args, group_value, strict=False))
|
|
415
415
|
subset = self.filtered(**group_parameters)
|
|
416
416
|
if len(subset) > 0:
|
|
417
417
|
yield group_parameters, subset
|
|
@@ -6,7 +6,7 @@ from __future__ import annotations
|
|
|
6
6
|
|
|
7
7
|
import warnings
|
|
8
8
|
from dataclasses import dataclass
|
|
9
|
-
from typing import ClassVar, Literal
|
|
9
|
+
from typing import ClassVar, Literal
|
|
10
10
|
|
|
11
11
|
FileMode = Literal[
|
|
12
12
|
"r", # open as readable
|
|
@@ -137,7 +137,7 @@ access_truncate = AccessMode(
|
|
|
137
137
|
dynamic_append=True,
|
|
138
138
|
)
|
|
139
139
|
|
|
140
|
-
ModeType =
|
|
140
|
+
ModeType = str | AccessMode
|
|
141
141
|
|
|
142
142
|
|
|
143
143
|
class AccessError(RuntimeError):
|
|
@@ -15,13 +15,17 @@ from typing import Any, Union
|
|
|
15
15
|
import numpy as np
|
|
16
16
|
import zarr
|
|
17
17
|
from numpy.typing import ArrayLike, DTypeLike
|
|
18
|
-
|
|
18
|
+
|
|
19
|
+
zarr_version = int(zarr.__version__.split(".", 1)[0])
|
|
20
|
+
assert zarr_version == 2
|
|
21
|
+
|
|
22
|
+
from zarr.storage import Store
|
|
19
23
|
|
|
20
24
|
from ..access_modes import ModeType
|
|
21
25
|
from ..attributes import AttrsLike
|
|
22
26
|
from ..base import StorageBase
|
|
23
27
|
|
|
24
|
-
zarrElement =
|
|
28
|
+
zarrElement = zarr.Group | zarr.Array
|
|
25
29
|
|
|
26
30
|
|
|
27
31
|
class ZarrStorage(StorageBase):
|
|
@@ -56,7 +60,7 @@ class ZarrStorage(StorageBase):
|
|
|
56
60
|
if self.mode.file_mode == "r":
|
|
57
61
|
self._logger.info("DirectoryStore is always opened writable")
|
|
58
62
|
|
|
59
|
-
self._store = zarr.
|
|
63
|
+
self._store = zarr.storage.LocalStore(path)
|
|
60
64
|
|
|
61
65
|
elif path.suffix == ".zip":
|
|
62
66
|
# create a ZipStore
|
|
@@ -77,7 +81,7 @@ class ZarrStorage(StorageBase):
|
|
|
77
81
|
if self.mode.file_mode == "w" and path.exists():
|
|
78
82
|
self._logger.info("Delete file `%s`", path)
|
|
79
83
|
path.unlink()
|
|
80
|
-
self._store = zarr.SQLiteStore(path)
|
|
84
|
+
self._store = zarr.storage.SQLiteStore(path)
|
|
81
85
|
|
|
82
86
|
elif isinstance(store_or_path, Store):
|
|
83
87
|
# use already opened zarr storage
|
|
@@ -142,7 +146,7 @@ class ZarrStorage(StorageBase):
|
|
|
142
146
|
return self._root.keys() # type: ignore
|
|
143
147
|
|
|
144
148
|
def is_group(self, loc: Sequence[str], *, ignore_cls: bool = False) -> bool:
|
|
145
|
-
return isinstance(self[loc], zarr.
|
|
149
|
+
return isinstance(self[loc], zarr.Group)
|
|
146
150
|
|
|
147
151
|
def _create_group(self, loc: Sequence[str]) -> None:
|
|
148
152
|
parent, name = self._get_parent(loc)
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
"""Defines a class storing data in various storages.
|
|
2
|
+
|
|
3
|
+
Requires the optional :mod:`zarr` module.
|
|
4
|
+
|
|
5
|
+
.. codeauthor:: David Zwicker <david.zwicker@ds.mpg.de>
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import base64
|
|
11
|
+
import json
|
|
12
|
+
import pickle
|
|
13
|
+
import shutil
|
|
14
|
+
from collections.abc import Collection, Sequence
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
from typing import Any, Union
|
|
17
|
+
|
|
18
|
+
import numpy as np
|
|
19
|
+
import zarr
|
|
20
|
+
from numpy.typing import ArrayLike, DTypeLike
|
|
21
|
+
|
|
22
|
+
zarr_version = int(zarr.__version__.split(".", 1)[0])
|
|
23
|
+
assert zarr_version == 3
|
|
24
|
+
|
|
25
|
+
from zarr.abc.store import Store
|
|
26
|
+
|
|
27
|
+
from ..access_modes import ModeType
|
|
28
|
+
from ..attributes import AttrsLike
|
|
29
|
+
from ..base import StorageBase
|
|
30
|
+
|
|
31
|
+
zarrElement = zarr.Group | zarr.Array
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class ZarrStorage(StorageBase):
|
|
35
|
+
"""Storage that stores data in an zarr file or database."""
|
|
36
|
+
|
|
37
|
+
extensions = ["zarr", "zip", "sqldb", "lmdb"]
|
|
38
|
+
|
|
39
|
+
def __init__(self, store_or_path: str | Path | Store, *, mode: ModeType = "read"):
|
|
40
|
+
"""
|
|
41
|
+
Args:
|
|
42
|
+
store_or_path (str or :class:`~pathlib.Path` or :class:`~zarr._storage.store.Store`):
|
|
43
|
+
File path to the file/folder or a :mod:`zarr` Store
|
|
44
|
+
mode (str or :class:`~modelrunner.storage.access_modes.AccessMode`):
|
|
45
|
+
The file mode with which the storage is accessed. Determines allowed
|
|
46
|
+
operations.
|
|
47
|
+
"""
|
|
48
|
+
super().__init__(mode=mode)
|
|
49
|
+
|
|
50
|
+
if isinstance(store_or_path, (str, Path)):
|
|
51
|
+
# open zarr storage on file system
|
|
52
|
+
self._close = True
|
|
53
|
+
path = Path(store_or_path)
|
|
54
|
+
|
|
55
|
+
if self.mode.file_mode == "x" and path.exists():
|
|
56
|
+
raise FileExistsError(f"File `{path}` already exists")
|
|
57
|
+
|
|
58
|
+
if path.suffix in {"", ".zarr"}:
|
|
59
|
+
# path seems to be a directory or a zarr direction => DirectoryStore
|
|
60
|
+
if path.is_dir() and self.mode.file_mode == "w":
|
|
61
|
+
self._logger.info("Delete directory `{%s}`", path)
|
|
62
|
+
shutil.rmtree(path) # remove the directory to reinstate it
|
|
63
|
+
if self.mode.file_mode == "r":
|
|
64
|
+
self._logger.info("DirectoryStore is always opened writable")
|
|
65
|
+
|
|
66
|
+
self._store = zarr.storage.LocalStore(path)
|
|
67
|
+
|
|
68
|
+
elif path.suffix == ".zip":
|
|
69
|
+
# create a ZipStore
|
|
70
|
+
file_mode = self.mode.file_mode
|
|
71
|
+
if file_mode == "x":
|
|
72
|
+
if path.exists():
|
|
73
|
+
raise OSError("File `{path}` already exists")
|
|
74
|
+
else:
|
|
75
|
+
file_mode = "w"
|
|
76
|
+
elif file_mode == "w" and path.exists():
|
|
77
|
+
self._logger.info("Delete file `%s`", path)
|
|
78
|
+
path.unlink()
|
|
79
|
+
|
|
80
|
+
self._store = zarr.storage.ZipStore(path, mode=file_mode)
|
|
81
|
+
|
|
82
|
+
elif isinstance(store_or_path, Store):
|
|
83
|
+
# use already opened zarr storage
|
|
84
|
+
self._close = False
|
|
85
|
+
self._store = store_or_path
|
|
86
|
+
|
|
87
|
+
else:
|
|
88
|
+
raise TypeError(f"Unknown store `{store_or_path}`")
|
|
89
|
+
|
|
90
|
+
zarr_mode = "r" if self.mode.file_mode == "r" else "a"
|
|
91
|
+
self._root = zarr.open_group(store=self._store, mode=zarr_mode)
|
|
92
|
+
|
|
93
|
+
@property
|
|
94
|
+
def can_update(self) -> bool:
|
|
95
|
+
"""Bool: indicates whether the storage supports updating items."""
|
|
96
|
+
return not isinstance(self._store, zarr.storage.ZipStore)
|
|
97
|
+
|
|
98
|
+
def __repr__(self):
|
|
99
|
+
return f'{self.__class__.__name__}({self._root.store}, mode="{self.mode.name}")'
|
|
100
|
+
|
|
101
|
+
def close(self) -> None:
|
|
102
|
+
if self._close:
|
|
103
|
+
self._store.close()
|
|
104
|
+
self._root = None
|
|
105
|
+
super().close()
|
|
106
|
+
|
|
107
|
+
def _get_parent(self, loc: Sequence[str]) -> tuple[zarr.Group, str]:
|
|
108
|
+
"""Get the parent group for a particular location.
|
|
109
|
+
|
|
110
|
+
Args:
|
|
111
|
+
loc (list of str):
|
|
112
|
+
The location in the storage where the group will be created
|
|
113
|
+
|
|
114
|
+
Returns:
|
|
115
|
+
(group, str):
|
|
116
|
+
A tuple consisting of the parent group and the name of the current item
|
|
117
|
+
"""
|
|
118
|
+
try:
|
|
119
|
+
path, name = loc[:-1], loc[-1]
|
|
120
|
+
except IndexError as err:
|
|
121
|
+
raise KeyError(f"Location `/{'/'.join(loc)}` has no parent") from err
|
|
122
|
+
|
|
123
|
+
parent = self._root
|
|
124
|
+
for part in path:
|
|
125
|
+
try:
|
|
126
|
+
parent = parent[part]
|
|
127
|
+
except KeyError:
|
|
128
|
+
parent = parent.create_group(part, overwrite=False)
|
|
129
|
+
|
|
130
|
+
return parent, name
|
|
131
|
+
|
|
132
|
+
def __getitem__(self, loc: Sequence[str]) -> Any:
|
|
133
|
+
if len(loc) == 0:
|
|
134
|
+
return self._root
|
|
135
|
+
else:
|
|
136
|
+
parent, name = self._get_parent(loc)
|
|
137
|
+
return parent[name]
|
|
138
|
+
|
|
139
|
+
def keys(self, loc: Sequence[str] | None = None) -> Collection[str]:
|
|
140
|
+
if loc:
|
|
141
|
+
return self[loc].keys() # type: ignore
|
|
142
|
+
else:
|
|
143
|
+
return self._root.keys() # type: ignore
|
|
144
|
+
|
|
145
|
+
def is_group(self, loc: Sequence[str], *, ignore_cls: bool = False) -> bool:
|
|
146
|
+
return isinstance(self[loc], zarr.Group)
|
|
147
|
+
|
|
148
|
+
def _create_group(self, loc: Sequence[str]) -> None:
|
|
149
|
+
parent, name = self._get_parent(loc)
|
|
150
|
+
parent.create_group(name)
|
|
151
|
+
|
|
152
|
+
def _read_attrs(self, loc: Sequence[str]) -> AttrsLike:
|
|
153
|
+
return self[loc].attrs # type: ignore
|
|
154
|
+
|
|
155
|
+
def _write_attr(self, loc: Sequence[str], name: str, value: str) -> None:
|
|
156
|
+
self[loc].attrs[name] = value
|
|
157
|
+
|
|
158
|
+
def _read_array(
|
|
159
|
+
self, loc: Sequence[str], *, copy: bool, index: int | None = None
|
|
160
|
+
) -> np.ndarray:
|
|
161
|
+
arr_like = self[loc]
|
|
162
|
+
|
|
163
|
+
if not isinstance(arr_like, zarr.Array):
|
|
164
|
+
raise RuntimeError(
|
|
165
|
+
f"Found {arr_like.__class__} at location `/{'/'.join(loc)}`"
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
is_recarray = arr_like.attrs.get("__recarray__", False)
|
|
169
|
+
if index is not None:
|
|
170
|
+
arr_like = arr_like[index]
|
|
171
|
+
|
|
172
|
+
# convert it into the right type
|
|
173
|
+
arr = np.array(arr_like, copy=copy)
|
|
174
|
+
if is_recarray:
|
|
175
|
+
arr = arr.view(np.recarray)
|
|
176
|
+
|
|
177
|
+
return arr
|
|
178
|
+
|
|
179
|
+
def _write_array(self, loc: Sequence[str], arr: np.ndarray) -> None:
|
|
180
|
+
parent, name = self._get_parent(loc)
|
|
181
|
+
|
|
182
|
+
if name in parent:
|
|
183
|
+
# update an existing array assuming it has the same shape. The credentials
|
|
184
|
+
# for this operation need to be checked by the caller!
|
|
185
|
+
parent[name][...] = arr
|
|
186
|
+
|
|
187
|
+
else:
|
|
188
|
+
# create a new array element
|
|
189
|
+
if arr.dtype == object:
|
|
190
|
+
el = parent.create_array(name, data=arr, overwrite=True)
|
|
191
|
+
else:
|
|
192
|
+
el = parent.create_array(name, data=arr, overwrite=True)
|
|
193
|
+
|
|
194
|
+
if isinstance(arr, np.recarray):
|
|
195
|
+
el.attrs["__recarray__"] = True
|
|
196
|
+
|
|
197
|
+
def _create_dynamic_array(
|
|
198
|
+
self,
|
|
199
|
+
loc: Sequence[str],
|
|
200
|
+
shape: tuple[int, ...],
|
|
201
|
+
dtype: DTypeLike,
|
|
202
|
+
record_array: bool = False,
|
|
203
|
+
) -> None:
|
|
204
|
+
parent, name = self._get_parent(loc)
|
|
205
|
+
try:
|
|
206
|
+
element = parent.zeros(
|
|
207
|
+
name=name, shape=(0,) + shape, chunks=(1,) + shape, dtype=dtype
|
|
208
|
+
)
|
|
209
|
+
except zarr.errors.ContainsArrayError as err:
|
|
210
|
+
raise RuntimeError(f"Array `/{'/'.join(loc)}` already exists") from err
|
|
211
|
+
else:
|
|
212
|
+
if record_array:
|
|
213
|
+
element.attrs["__recarray__"] = True
|
|
214
|
+
|
|
215
|
+
def _extend_dynamic_array(self, loc: Sequence[str], data: ArrayLike) -> None:
|
|
216
|
+
arr_obj = self[loc]
|
|
217
|
+
arr_obj.append([data])
|
|
218
|
+
|
|
219
|
+
def _read_object(self, loc: Sequence[str]) -> Any:
|
|
220
|
+
stored = self[loc][0].item()
|
|
221
|
+
# Check if the object was pickled (starts with pickle marker)
|
|
222
|
+
if stored.startswith("__pickle__:"):
|
|
223
|
+
obj_data = stored[11:] # Remove the marker
|
|
224
|
+
return pickle.loads(base64.b64decode(obj_data))
|
|
225
|
+
else:
|
|
226
|
+
# Otherwise it's JSON
|
|
227
|
+
return json.loads(stored)
|
|
228
|
+
|
|
229
|
+
def _write_object(self, loc: Sequence[str], obj: Any) -> None:
|
|
230
|
+
# Try JSON serialization first
|
|
231
|
+
try:
|
|
232
|
+
obj_enc = json.dumps(obj)
|
|
233
|
+
except (TypeError, ValueError):
|
|
234
|
+
# Fall back to pickle for non-JSON-serializable objects
|
|
235
|
+
pickled = pickle.dumps(obj)
|
|
236
|
+
obj_enc = "__pickle__:" + base64.b64encode(pickled).decode("ascii")
|
|
237
|
+
|
|
238
|
+
data = np.array([obj_enc])
|
|
239
|
+
parent, name = self._get_parent(loc)
|
|
240
|
+
parent.create_array(name, data=data, overwrite=True)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"""Defines a class storing data in various storages.
|
|
2
|
+
|
|
3
|
+
Requires the optional :mod:`zarr` module.
|
|
4
|
+
|
|
5
|
+
.. codeauthor:: David Zwicker <david.zwicker@ds.mpg.de>
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import zarr
|
|
11
|
+
|
|
12
|
+
zarr_version = int(zarr.__version__.split(".", 1)[0])
|
|
13
|
+
|
|
14
|
+
if zarr_version == 2:
|
|
15
|
+
# import classes from paths of zarr version 2
|
|
16
|
+
from ._zarr2 import ZarrStorage
|
|
17
|
+
|
|
18
|
+
elif zarr_version == 3:
|
|
19
|
+
# import classes from paths of zarr version 3
|
|
20
|
+
from ._zarr3 import ZarrStorage # type: ignore
|
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
from __future__ import annotations
|
|
7
7
|
|
|
8
8
|
from pathlib import Path
|
|
9
|
-
from typing import Union
|
|
10
9
|
|
|
11
10
|
from .access_modes import AccessMode
|
|
12
11
|
from .backend import AVAILABLE_STORAGE, MemoryStorage
|
|
@@ -14,7 +13,7 @@ from .base import StorageBase
|
|
|
14
13
|
from .group import StorageGroup
|
|
15
14
|
from .utils import Location
|
|
16
15
|
|
|
17
|
-
StorageID =
|
|
16
|
+
StorageID = str | Path | StorageGroup | StorageBase | None
|
|
18
17
|
|
|
19
18
|
|
|
20
19
|
class open_storage(StorageGroup):
|
|
@@ -121,7 +120,7 @@ class open_storage(StorageGroup):
|
|
|
121
120
|
|
|
122
121
|
if isinstance(storage, zarr.Group):
|
|
123
122
|
self._close = False
|
|
124
|
-
store_obj = ZarrStorage(storage.
|
|
123
|
+
store_obj = ZarrStorage(storage.store, **kwargs)
|
|
125
124
|
loc = [storage.path] + [loc]
|
|
126
125
|
|
|
127
126
|
if store_obj is None:
|
|
@@ -124,9 +124,7 @@ class TrajectoryWriter:
|
|
|
124
124
|
shape: tuple[int, ...] = data.shape
|
|
125
125
|
self._item_type = "array"
|
|
126
126
|
else:
|
|
127
|
-
|
|
128
|
-
shape = ()
|
|
129
|
-
self._item_type = "object"
|
|
127
|
+
raise NotImplementedError("Trajectories must be arrays for zarr3")
|
|
130
128
|
self._trajectory.create_dynamic_array("data", shape=shape, dtype=dtype)
|
|
131
129
|
self._trajectory.create_dynamic_array("time", shape=(), dtype=float)
|
|
132
130
|
self._trajectory.write_attrs(None, {"item_type": self._item_type})
|
|
@@ -138,10 +136,10 @@ class TrajectoryWriter:
|
|
|
138
136
|
|
|
139
137
|
if self._item_type == "array":
|
|
140
138
|
self._trajectory.extend_dynamic_array("data", data)
|
|
141
|
-
elif self._item_type == "object":
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
139
|
+
# elif self._item_type == "object":
|
|
140
|
+
# arr: np.ndarray = np.empty((), dtype=object)
|
|
141
|
+
# arr[...] = data
|
|
142
|
+
# self._trajectory.extend_dynamic_array("data", arr)
|
|
145
143
|
else:
|
|
146
144
|
raise NotImplementedError
|
|
147
145
|
self._trajectory.extend_dynamic_array("time", time)
|
|
@@ -9,9 +9,9 @@ import codecs
|
|
|
9
9
|
import inspect
|
|
10
10
|
import pickle
|
|
11
11
|
from collections import defaultdict
|
|
12
|
-
from collections.abc import Sequence
|
|
12
|
+
from collections.abc import Callable, Sequence
|
|
13
13
|
from importlib import import_module
|
|
14
|
-
from typing import TYPE_CHECKING, Any,
|
|
14
|
+
from typing import TYPE_CHECKING, Any, Literal, overload
|
|
15
15
|
|
|
16
16
|
import numpy as np
|
|
17
17
|
|
|
@@ -21,7 +21,7 @@ if TYPE_CHECKING:
|
|
|
21
21
|
PICKLE_PROTOCOL = pickle.HIGHEST_PROTOCOL
|
|
22
22
|
|
|
23
23
|
|
|
24
|
-
Location =
|
|
24
|
+
Location = str | Sequence["Location"] | None
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
@overload
|
|
@@ -73,8 +73,9 @@ def import_class(identifier: str):
|
|
|
73
73
|
def is_serial_or_mpi_root() -> bool:
|
|
74
74
|
"""Function checking whether the current program is serial or an MPI root node."""
|
|
75
75
|
try:
|
|
76
|
-
from mpi4py import MPI
|
|
76
|
+
from mpi4py import MPI # type: ignore
|
|
77
77
|
except ImportError:
|
|
78
78
|
return True # assume we are in a serial run
|
|
79
79
|
else:
|
|
80
|
-
|
|
80
|
+
# check whether we are the root node
|
|
81
|
+
return MPI.COMM_WORLD.rank == 0 # type: ignore
|