hpcflow-new2 0.2.0a159__tar.gz → 0.2.0a160__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.
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/PKG-INFO +1 -1
- hpcflow_new2-0.2.0a160/hpcflow/_version.py +1 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/__init__.py +2 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/app.py +89 -15
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/cli.py +18 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/cli_common.py +16 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/core/actions.py +14 -6
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/core/command_files.py +4 -4
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/core/element.py +15 -16
- hpcflow_new2-0.2.0a160/hpcflow/sdk/core/run_dir_files.py +63 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/core/task.py +34 -35
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/core/utils.py +37 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/core/workflow.py +144 -49
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/demo/cli.py +12 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/log.py +2 -2
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/persistence/base.py +140 -12
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/persistence/json.py +84 -63
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/persistence/pending.py +21 -7
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/persistence/zarr.py +143 -108
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/submission/jobscript.py +22 -4
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/submission/shells/bash.py +2 -2
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/submission/shells/powershell.py +2 -2
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/submission/submission.py +20 -7
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/tests/scripts/test_main_scripts.py +40 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/tests/unit/test_utils.py +28 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/pyproject.toml +2 -2
- hpcflow_new2-0.2.0a159/hpcflow/_version.py +0 -1
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/README.md +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/__init__.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/__pyinstaller/__init__.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/__pyinstaller/hook-hpcflow.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/app.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/cli.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/data/demo_data_manifest/__init__.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/data/demo_data_manifest/demo_data_manifest.json +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/data/scripts/__init__.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/data/scripts/demo_task_1_generate_t1_infile_1.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/data/scripts/demo_task_1_generate_t1_infile_2.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/data/scripts/demo_task_1_parse_p3.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/data/scripts/generate_t1_file_01.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/data/scripts/main_script_test_direct_in_direct_out.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/data/scripts/main_script_test_direct_in_direct_out_all_iters_test.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/data/scripts/main_script_test_direct_in_direct_out_labels.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/data/scripts/main_script_test_direct_sub_param_in_direct_out.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/data/scripts/main_script_test_hdf5_in_obj.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/data/scripts/main_script_test_hdf5_out_obj.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/data/scripts/main_script_test_json_and_direct_in_json_out.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/data/scripts/main_script_test_json_in_json_and_direct_out.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/data/scripts/main_script_test_json_in_json_out.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/data/scripts/main_script_test_json_in_json_out_labels.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/data/scripts/main_script_test_json_in_obj.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/data/scripts/main_script_test_json_out_obj.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/data/scripts/main_script_test_json_sub_param_in_json_out_labels.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/data/scripts/parse_t1_file_01.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/data/template_components/__init__.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/data/template_components/command_files.yaml +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/data/template_components/environments.yaml +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/data/template_components/parameters.yaml +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/data/template_components/task_schemas.yaml +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/data/workflows/__init__.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/data/workflows/workflow_1.yaml +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/examples.ipynb +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/config/__init__.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/config/callbacks.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/config/cli.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/config/config.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/config/config_file.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/config/errors.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/core/__init__.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/core/commands.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/core/environment.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/core/errors.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/core/json_like.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/core/loop.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/core/object_list.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/core/parallel.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/core/parameters.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/core/rule.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/core/task_schema.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/core/test_utils.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/core/validation.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/core/zarr_io.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/data/__init__.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/data/config_file_schema.yaml +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/data/config_schema.yaml +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/data/environments_spec_schema.yaml +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/data/files_spec_schema.yaml +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/data/parameters_spec_schema.yaml +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/data/task_schema_spec_schema.yaml +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/data/workflow_spec_schema.yaml +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/demo/__init__.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/helper/__init__.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/helper/cli.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/helper/helper.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/helper/watcher.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/persistence/__init__.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/persistence/store_resource.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/persistence/utils.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/runtime.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/submission/__init__.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/submission/jobscript_info.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/submission/schedulers/__init__.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/submission/schedulers/direct.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/submission/schedulers/sge.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/submission/schedulers/slurm.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/submission/schedulers/utils.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/submission/shells/__init__.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/submission/shells/base.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/submission/shells/os_version.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/sdk/typing.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/tests/conftest.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/tests/data/__init__.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/tests/data/benchmark_N_elements.yaml +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/tests/data/workflow_1.json +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/tests/data/workflow_1.yaml +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/tests/data/workflow_1_slurm.yaml +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/tests/data/workflow_1_wsl.yaml +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/tests/data/workflow_test_run_abort.yaml +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/tests/schedulers/direct_linux/test_direct_linux_submission.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/tests/schedulers/slurm/test_slurm_submission.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/tests/shells/wsl/test_wsl_submission.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/tests/unit/test_action.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/tests/unit/test_action_rule.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/tests/unit/test_app.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/tests/unit/test_cli.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/tests/unit/test_command.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/tests/unit/test_config.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/tests/unit/test_config_file.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/tests/unit/test_element.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/tests/unit/test_element_iteration.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/tests/unit/test_element_set.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/tests/unit/test_input_source.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/tests/unit/test_input_value.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/tests/unit/test_json_like.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/tests/unit/test_loop.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/tests/unit/test_object_list.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/tests/unit/test_parameter.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/tests/unit/test_persistence.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/tests/unit/test_resources.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/tests/unit/test_run.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/tests/unit/test_runtime.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/tests/unit/test_schema_input.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/tests/unit/test_shell.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/tests/unit/test_slurm.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/tests/unit/test_submission.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/tests/unit/test_task.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/tests/unit/test_task_schema.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/tests/unit/test_value_sequence.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/tests/unit/test_workflow.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/tests/unit/test_workflow_template.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/tests/workflows/test_jobscript.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/tests/workflows/test_workflows.py +0 -0
- {hpcflow_new2-0.2.0a159 → hpcflow_new2-0.2.0a160}/hpcflow/viz_demo.ipynb +0 -0
@@ -0,0 +1 @@
|
|
1
|
+
__version__ = "0.2.0a160"
|
@@ -1,4 +1,5 @@
|
|
1
1
|
"""Sub-package to define an extensible hpcflow application."""
|
2
|
+
|
2
3
|
import logging
|
3
4
|
import os
|
4
5
|
import sys
|
@@ -90,6 +91,7 @@ sdk_classes = {
|
|
90
91
|
"SlurmPosix": "hpcflow.sdk.submission.schedulers.slurm",
|
91
92
|
"SGEPosix": "hpcflow.sdk.submission.schedulers.sge",
|
92
93
|
"OutputLabel": "hpcflow.sdk.core.task",
|
94
|
+
"RunDirAppFiles": "hpcflow.sdk.core.run_dir_files",
|
93
95
|
}
|
94
96
|
|
95
97
|
# these are defined as `BaseApp` methods with an underscore prefix:
|
@@ -20,6 +20,7 @@ import warnings
|
|
20
20
|
import zipfile
|
21
21
|
from platformdirs import user_cache_path, user_data_dir
|
22
22
|
from reretry import retry
|
23
|
+
import rich
|
23
24
|
from rich.console import Console, Group
|
24
25
|
from rich.syntax import Syntax
|
25
26
|
from rich.table import Table, box
|
@@ -965,6 +966,7 @@ class BaseApp(metaclass=Singleton):
|
|
965
966
|
}
|
966
967
|
return item
|
967
968
|
|
969
|
+
@TimeIt.decorator
|
968
970
|
def read_known_submissions_file(self) -> List[Dict]:
|
969
971
|
"""Retrieve existing workflows that *might* be running."""
|
970
972
|
known = []
|
@@ -1024,6 +1026,7 @@ class BaseApp(metaclass=Singleton):
|
|
1024
1026
|
|
1025
1027
|
return next_id
|
1026
1028
|
|
1029
|
+
@TimeIt.decorator
|
1027
1030
|
def set_inactive_in_known_subs_file(self, inactive_IDs: List[int]):
|
1028
1031
|
"""Set workflows in the known-submissions file to the non-running state.
|
1029
1032
|
|
@@ -1141,6 +1144,7 @@ class BaseApp(metaclass=Singleton):
|
|
1141
1144
|
ts_name_fmt: Optional[str] = None,
|
1142
1145
|
store_kwargs: Optional[Dict] = None,
|
1143
1146
|
variables: Optional[Dict[str, str]] = None,
|
1147
|
+
status: Optional[bool] = True,
|
1144
1148
|
) -> get_app_attribute("Workflow"):
|
1145
1149
|
"""Generate a new {app_name} workflow from a file or string containing a workflow
|
1146
1150
|
template parametrisation.
|
@@ -1177,10 +1181,17 @@ class BaseApp(metaclass=Singleton):
|
|
1177
1181
|
Keyword arguments to pass to the store's `write_empty_workflow` method.
|
1178
1182
|
variables
|
1179
1183
|
String variables to substitute in `template_file_or_str`.
|
1184
|
+
status
|
1185
|
+
If True, display a live status to track workflow creation progress.
|
1180
1186
|
"""
|
1181
1187
|
|
1182
1188
|
self.API_logger.info("make_workflow called")
|
1183
1189
|
|
1190
|
+
if status:
|
1191
|
+
console = rich.console.Console()
|
1192
|
+
status = console.status("Making persistent workflow...")
|
1193
|
+
status.start()
|
1194
|
+
|
1184
1195
|
common = {
|
1185
1196
|
"path": path,
|
1186
1197
|
"name": name,
|
@@ -1190,6 +1201,7 @@ class BaseApp(metaclass=Singleton):
|
|
1190
1201
|
"ts_name_fmt": ts_name_fmt,
|
1191
1202
|
"store_kwargs": store_kwargs,
|
1192
1203
|
"variables": variables,
|
1204
|
+
"status": status,
|
1193
1205
|
}
|
1194
1206
|
|
1195
1207
|
if not is_string:
|
@@ -1200,10 +1212,24 @@ class BaseApp(metaclass=Singleton):
|
|
1200
1212
|
)
|
1201
1213
|
|
1202
1214
|
elif template_format == "json":
|
1203
|
-
|
1215
|
+
try:
|
1216
|
+
wk = self.Workflow.from_JSON_string(
|
1217
|
+
JSON_str=template_file_or_str, **common
|
1218
|
+
)
|
1219
|
+
except Exception:
|
1220
|
+
if status:
|
1221
|
+
status.stop()
|
1222
|
+
raise
|
1204
1223
|
|
1205
1224
|
elif template_format == "yaml":
|
1206
|
-
|
1225
|
+
try:
|
1226
|
+
wk = self.Workflow.from_YAML_string(
|
1227
|
+
YAML_str=template_file_or_str, **common
|
1228
|
+
)
|
1229
|
+
except Exception:
|
1230
|
+
if status:
|
1231
|
+
status.stop()
|
1232
|
+
raise
|
1207
1233
|
|
1208
1234
|
elif not template_format:
|
1209
1235
|
raise ValueError(
|
@@ -1216,6 +1242,10 @@ class BaseApp(metaclass=Singleton):
|
|
1216
1242
|
f"Template format {template_format!r} not understood. Available template "
|
1217
1243
|
f"formats are {ALL_TEMPLATE_FORMATS!r}."
|
1218
1244
|
)
|
1245
|
+
|
1246
|
+
if status:
|
1247
|
+
status.stop()
|
1248
|
+
|
1219
1249
|
return wk
|
1220
1250
|
|
1221
1251
|
def _make_and_submit_workflow(
|
@@ -1236,6 +1266,8 @@ class BaseApp(metaclass=Singleton):
|
|
1236
1266
|
add_to_known: Optional[bool] = True,
|
1237
1267
|
return_idx: Optional[bool] = False,
|
1238
1268
|
tasks: Optional[List[int]] = None,
|
1269
|
+
cancel: Optional[bool] = False,
|
1270
|
+
status: Optional[bool] = True,
|
1239
1271
|
) -> Dict[int, int]:
|
1240
1272
|
"""Generate and submit a new {app_name} workflow from a file or string containing a
|
1241
1273
|
workflow template parametrisation.
|
@@ -1288,6 +1320,11 @@ class BaseApp(metaclass=Singleton):
|
|
1288
1320
|
tasks
|
1289
1321
|
List of task indices to include in this submission. By default all tasks are
|
1290
1322
|
included.
|
1323
|
+
cancel
|
1324
|
+
Immediately cancel the submission. Useful for testing and benchmarking.
|
1325
|
+
status
|
1326
|
+
If True, display a live status to track workflow creation and submission
|
1327
|
+
progress.
|
1291
1328
|
"""
|
1292
1329
|
|
1293
1330
|
self.API_logger.info("make_and_submit_workflow called")
|
@@ -1304,6 +1341,7 @@ class BaseApp(metaclass=Singleton):
|
|
1304
1341
|
ts_name_fmt=ts_name_fmt,
|
1305
1342
|
store_kwargs=store_kwargs,
|
1306
1343
|
variables=variables,
|
1344
|
+
status=status,
|
1307
1345
|
)
|
1308
1346
|
return wk.submit(
|
1309
1347
|
JS_parallelism=JS_parallelism,
|
@@ -1311,6 +1349,8 @@ class BaseApp(metaclass=Singleton):
|
|
1311
1349
|
add_to_known=add_to_known,
|
1312
1350
|
return_idx=return_idx,
|
1313
1351
|
tasks=tasks,
|
1352
|
+
cancel=cancel,
|
1353
|
+
status=status,
|
1314
1354
|
)
|
1315
1355
|
|
1316
1356
|
def _make_demo_workflow(
|
@@ -1325,6 +1365,7 @@ class BaseApp(metaclass=Singleton):
|
|
1325
1365
|
ts_name_fmt: Optional[str] = None,
|
1326
1366
|
store_kwargs: Optional[Dict] = None,
|
1327
1367
|
variables: Optional[Dict[str, str]] = None,
|
1368
|
+
status: Optional[bool] = True,
|
1328
1369
|
) -> get_app_attribute("Workflow"):
|
1329
1370
|
"""Generate a new {app_name} workflow from a builtin demo workflow template.
|
1330
1371
|
|
@@ -1358,10 +1399,17 @@ class BaseApp(metaclass=Singleton):
|
|
1358
1399
|
Keyword arguments to pass to the store's `write_empty_workflow` method.
|
1359
1400
|
variables
|
1360
1401
|
String variables to substitute in the demo workflow template file.
|
1402
|
+
status
|
1403
|
+
If True, display a live status to track workflow creation progress.
|
1361
1404
|
"""
|
1362
1405
|
|
1363
1406
|
self.API_logger.info("make_demo_workflow called")
|
1364
1407
|
|
1408
|
+
if status:
|
1409
|
+
console = rich.console.Console()
|
1410
|
+
status = console.status("Making persistent workflow...")
|
1411
|
+
status.start()
|
1412
|
+
|
1365
1413
|
with self.get_demo_workflow_template_file(workflow_name) as template_path:
|
1366
1414
|
wk = self.Workflow.from_file(
|
1367
1415
|
template_path=template_path,
|
@@ -1374,7 +1422,10 @@ class BaseApp(metaclass=Singleton):
|
|
1374
1422
|
ts_name_fmt=ts_name_fmt,
|
1375
1423
|
store_kwargs=store_kwargs,
|
1376
1424
|
variables=variables,
|
1425
|
+
status=status,
|
1377
1426
|
)
|
1427
|
+
if status:
|
1428
|
+
status.stop()
|
1378
1429
|
return wk
|
1379
1430
|
|
1380
1431
|
def _make_and_submit_demo_workflow(
|
@@ -1394,6 +1445,8 @@ class BaseApp(metaclass=Singleton):
|
|
1394
1445
|
add_to_known: Optional[bool] = True,
|
1395
1446
|
return_idx: Optional[bool] = False,
|
1396
1447
|
tasks: Optional[List[int]] = None,
|
1448
|
+
cancel: Optional[bool] = False,
|
1449
|
+
status: Optional[bool] = True,
|
1397
1450
|
) -> Dict[int, int]:
|
1398
1451
|
"""Generate and submit a new {app_name} workflow from a file or string containing a
|
1399
1452
|
workflow template parametrisation.
|
@@ -1443,6 +1496,10 @@ class BaseApp(metaclass=Singleton):
|
|
1443
1496
|
tasks
|
1444
1497
|
List of task indices to include in this submission. By default all tasks are
|
1445
1498
|
included.
|
1499
|
+
cancel
|
1500
|
+
Immediately cancel the submission. Useful for testing and benchmarking.
|
1501
|
+
status
|
1502
|
+
If True, display a live status to track submission progress.
|
1446
1503
|
"""
|
1447
1504
|
|
1448
1505
|
self.API_logger.info("make_and_submit_demo_workflow called")
|
@@ -1465,6 +1522,8 @@ class BaseApp(metaclass=Singleton):
|
|
1465
1522
|
add_to_known=add_to_known,
|
1466
1523
|
return_idx=return_idx,
|
1467
1524
|
tasks=tasks,
|
1525
|
+
cancel=cancel,
|
1526
|
+
status=status,
|
1468
1527
|
)
|
1469
1528
|
|
1470
1529
|
def _submit_workflow(
|
@@ -1556,8 +1615,13 @@ class BaseApp(metaclass=Singleton):
|
|
1556
1615
|
)
|
1557
1616
|
return shell.get_version_info(exclude_os)
|
1558
1617
|
|
1618
|
+
@TimeIt.decorator
|
1559
1619
|
def _get_known_submissions(
|
1560
|
-
self,
|
1620
|
+
self,
|
1621
|
+
max_recent: int = 3,
|
1622
|
+
no_update: bool = False,
|
1623
|
+
as_json: bool = False,
|
1624
|
+
status: Optional[Any] = None,
|
1561
1625
|
):
|
1562
1626
|
"""Retrieve information about active and recently inactive finished {app_name}
|
1563
1627
|
workflows.
|
@@ -1582,6 +1646,8 @@ class BaseApp(metaclass=Singleton):
|
|
1582
1646
|
inactive_IDs = []
|
1583
1647
|
|
1584
1648
|
try:
|
1649
|
+
if status:
|
1650
|
+
status.update("Reading known submissions file...")
|
1585
1651
|
known_subs = self.read_known_submissions_file()
|
1586
1652
|
except FileNotFoundError:
|
1587
1653
|
known_subs = []
|
@@ -1614,6 +1680,8 @@ class BaseApp(metaclass=Singleton):
|
|
1614
1680
|
out_item["deleted"] = not path_exists
|
1615
1681
|
if path_exists:
|
1616
1682
|
try:
|
1683
|
+
if status:
|
1684
|
+
status.update(f"Inspecting workflow {file_dat_i['path']!r}.")
|
1617
1685
|
wk_i = self.Workflow(file_dat_i["path"])
|
1618
1686
|
except Exception:
|
1619
1687
|
wk_i = None
|
@@ -1640,15 +1708,22 @@ class BaseApp(metaclass=Singleton):
|
|
1640
1708
|
out_item["deleted"] = True
|
1641
1709
|
|
1642
1710
|
else:
|
1643
|
-
|
1644
|
-
|
1645
|
-
|
1646
|
-
|
1647
|
-
|
1648
|
-
|
1649
|
-
|
1650
|
-
|
1651
|
-
|
1711
|
+
if status:
|
1712
|
+
status.update(
|
1713
|
+
f"Reading workflow {file_dat_i['path']!r} submission info..."
|
1714
|
+
)
|
1715
|
+
with wk_i._store.cache_ctx():
|
1716
|
+
sub = wk_i.submissions[file_dat_i["sub_idx"]]
|
1717
|
+
|
1718
|
+
all_jobscripts = sub._submission_parts[submit_time_str]
|
1719
|
+
out_item.update(
|
1720
|
+
{
|
1721
|
+
"jobscripts": all_jobscripts,
|
1722
|
+
"submission": sub,
|
1723
|
+
"sub_start_time": sub.start_time,
|
1724
|
+
"sub_end_time": sub.end_time,
|
1725
|
+
}
|
1726
|
+
)
|
1652
1727
|
if file_dat_i["is_active"]:
|
1653
1728
|
# check it really is active:
|
1654
1729
|
run_key = (file_dat_i["path"], file_dat_i["sub_idx"])
|
@@ -1694,9 +1769,7 @@ class BaseApp(metaclass=Singleton):
|
|
1694
1769
|
out_access = sorted(
|
1695
1770
|
out_access,
|
1696
1771
|
key=lambda i: (
|
1697
|
-
i["
|
1698
|
-
or i["submission"].start_time
|
1699
|
-
or i["submit_time_obj"]
|
1772
|
+
i["sub_end_time"] or i["sub_start_time"] or i["submit_time_obj"]
|
1700
1773
|
),
|
1701
1774
|
reverse=True,
|
1702
1775
|
)
|
@@ -1826,6 +1899,7 @@ class BaseApp(metaclass=Singleton):
|
|
1826
1899
|
run_dat = self._get_known_submissions(
|
1827
1900
|
max_recent=max_recent,
|
1828
1901
|
no_update=no_update,
|
1902
|
+
status=status,
|
1829
1903
|
)
|
1830
1904
|
except Exception:
|
1831
1905
|
status.stop()
|
@@ -25,6 +25,9 @@ from hpcflow.sdk.cli_common import (
|
|
25
25
|
add_to_known_opt,
|
26
26
|
print_idx_opt,
|
27
27
|
tasks_opt,
|
28
|
+
cancel_opt,
|
29
|
+
submit_status_opt,
|
30
|
+
make_status_opt,
|
28
31
|
zip_path_opt,
|
29
32
|
zip_overwrite_opt,
|
30
33
|
zip_log_opt,
|
@@ -71,6 +74,7 @@ def _make_API_CLI(app):
|
|
71
74
|
@ts_fmt_option
|
72
75
|
@ts_name_fmt_option
|
73
76
|
@variables_option
|
77
|
+
@make_status_opt
|
74
78
|
def make_workflow(
|
75
79
|
template_file_or_str,
|
76
80
|
string,
|
@@ -82,6 +86,7 @@ def _make_API_CLI(app):
|
|
82
86
|
ts_fmt=None,
|
83
87
|
ts_name_fmt=None,
|
84
88
|
variables=None,
|
89
|
+
status=True,
|
85
90
|
):
|
86
91
|
"""Generate a new {app_name} workflow.
|
87
92
|
|
@@ -100,6 +105,7 @@ def _make_API_CLI(app):
|
|
100
105
|
ts_fmt=ts_fmt,
|
101
106
|
ts_name_fmt=ts_name_fmt,
|
102
107
|
variables=dict(variables),
|
108
|
+
status=status,
|
103
109
|
)
|
104
110
|
click.echo(wk.path)
|
105
111
|
|
@@ -119,6 +125,8 @@ def _make_API_CLI(app):
|
|
119
125
|
@add_to_known_opt
|
120
126
|
@print_idx_opt
|
121
127
|
@tasks_opt
|
128
|
+
@cancel_opt
|
129
|
+
@submit_status_opt
|
122
130
|
def make_and_submit_workflow(
|
123
131
|
template_file_or_str,
|
124
132
|
string,
|
@@ -135,6 +143,8 @@ def _make_API_CLI(app):
|
|
135
143
|
add_to_known=True,
|
136
144
|
print_idx=False,
|
137
145
|
tasks=None,
|
146
|
+
cancel=False,
|
147
|
+
status=True,
|
138
148
|
):
|
139
149
|
"""Generate and submit a new {app_name} workflow.
|
140
150
|
|
@@ -159,6 +169,8 @@ def _make_API_CLI(app):
|
|
159
169
|
add_to_known=add_to_known,
|
160
170
|
return_idx=print_idx,
|
161
171
|
tasks=tasks,
|
172
|
+
cancel=cancel,
|
173
|
+
status=status,
|
162
174
|
)
|
163
175
|
if print_idx:
|
164
176
|
click.echo(out)
|
@@ -320,6 +332,8 @@ def _make_workflow_CLI(app):
|
|
320
332
|
@add_to_known_opt
|
321
333
|
@print_idx_opt
|
322
334
|
@tasks_opt
|
335
|
+
@cancel_opt
|
336
|
+
@submit_status_opt
|
323
337
|
@click.pass_context
|
324
338
|
def submit_workflow(
|
325
339
|
ctx,
|
@@ -328,6 +342,8 @@ def _make_workflow_CLI(app):
|
|
328
342
|
add_to_known=True,
|
329
343
|
print_idx=False,
|
330
344
|
tasks=None,
|
345
|
+
cancel=False,
|
346
|
+
status=True,
|
331
347
|
):
|
332
348
|
"""Submit the workflow."""
|
333
349
|
out = ctx.obj["workflow"].submit(
|
@@ -336,6 +352,8 @@ def _make_workflow_CLI(app):
|
|
336
352
|
add_to_known=add_to_known,
|
337
353
|
return_idx=print_idx,
|
338
354
|
tasks=tasks,
|
355
|
+
cancel=cancel,
|
356
|
+
status=status,
|
339
357
|
)
|
340
358
|
if print_idx:
|
341
359
|
click.echo(out)
|
@@ -109,6 +109,22 @@ tasks_opt = click.option(
|
|
109
109
|
),
|
110
110
|
callback=sub_tasks_callback,
|
111
111
|
)
|
112
|
+
cancel_opt = click.option(
|
113
|
+
"--cancel",
|
114
|
+
help="Immediately cancel the submission. Useful for testing and benchmarking.",
|
115
|
+
is_flag=True,
|
116
|
+
default=False,
|
117
|
+
)
|
118
|
+
submit_status_opt = click.option(
|
119
|
+
"--status/--no-status",
|
120
|
+
help="If True, display a live status to track submission progress.",
|
121
|
+
default=True,
|
122
|
+
)
|
123
|
+
make_status_opt = click.option(
|
124
|
+
"--status/--no-status",
|
125
|
+
help="If True, display a live status to track workflow creation progress.",
|
126
|
+
default=True,
|
127
|
+
)
|
112
128
|
zip_path_opt = click.option(
|
113
129
|
"--path",
|
114
130
|
default=".",
|
@@ -29,6 +29,7 @@ from hpcflow.sdk.core.utils import (
|
|
29
29
|
swap_nested_dict_keys,
|
30
30
|
)
|
31
31
|
from hpcflow.sdk.log import TimeIt
|
32
|
+
from hpcflow.sdk.core.run_dir_files import RunDirAppFiles
|
32
33
|
|
33
34
|
|
34
35
|
ACTION_SCOPE_REGEX = r"(\w*)(?:\[(.*)\])?"
|
@@ -251,13 +252,16 @@ class ElementActionRun:
|
|
251
252
|
@property
|
252
253
|
def snapshot_start(self):
|
253
254
|
if self._ss_start_obj is None and self._snapshot_start:
|
254
|
-
self._ss_start_obj = JSONLikeDirSnapShot(
|
255
|
+
self._ss_start_obj = JSONLikeDirSnapShot(
|
256
|
+
root_path=".",
|
257
|
+
**self._snapshot_start,
|
258
|
+
)
|
255
259
|
return self._ss_start_obj
|
256
260
|
|
257
261
|
@property
|
258
262
|
def snapshot_end(self):
|
259
263
|
if self._ss_end_obj is None and self._snapshot_end:
|
260
|
-
self._ss_end_obj = JSONLikeDirSnapShot(**self._snapshot_end)
|
264
|
+
self._ss_end_obj = JSONLikeDirSnapShot(root_path=".", **self._snapshot_end)
|
261
265
|
return self._ss_end_obj
|
262
266
|
|
263
267
|
@property
|
@@ -331,6 +335,7 @@ class ElementActionRun:
|
|
331
335
|
run_idx=self.index,
|
332
336
|
)
|
333
337
|
|
338
|
+
@TimeIt.decorator
|
334
339
|
def get_parameter_sources(
|
335
340
|
self,
|
336
341
|
path: str = None,
|
@@ -363,6 +368,7 @@ class ElementActionRun:
|
|
363
368
|
raise_on_unset=raise_on_unset,
|
364
369
|
)
|
365
370
|
|
371
|
+
@TimeIt.decorator
|
366
372
|
def get_EAR_dependencies(self, as_objects=False):
|
367
373
|
"""Get EARs that this EAR depends on."""
|
368
374
|
|
@@ -434,6 +440,7 @@ class ElementActionRun:
|
|
434
440
|
return self._outputs
|
435
441
|
|
436
442
|
@property
|
443
|
+
@TimeIt.decorator
|
437
444
|
def resources(self):
|
438
445
|
if not self._resources:
|
439
446
|
self._resources = self.app.ElementResources(**self.get_resources())
|
@@ -451,6 +458,7 @@ class ElementActionRun:
|
|
451
458
|
self._output_files = self.app.ElementOutputFiles(element_action_run=self)
|
452
459
|
return self._output_files
|
453
460
|
|
461
|
+
@TimeIt.decorator
|
454
462
|
def get_resources(self):
|
455
463
|
"""Resolve specific resources for this EAR, considering all applicable scopes and
|
456
464
|
template-level resources."""
|
@@ -1457,11 +1465,11 @@ class Action(JSONLike):
|
|
1457
1465
|
|
1458
1466
|
@staticmethod
|
1459
1467
|
def get_param_dump_file_stem(js_idx: int, js_act_idx: int):
|
1460
|
-
return
|
1468
|
+
return RunDirAppFiles.get_run_param_dump_file_prefix(js_idx, js_act_idx)
|
1461
1469
|
|
1462
1470
|
@staticmethod
|
1463
1471
|
def get_param_load_file_stem(js_idx: int, js_act_idx: int):
|
1464
|
-
return
|
1472
|
+
return RunDirAppFiles.get_run_param_load_file_prefix(js_idx, js_act_idx)
|
1465
1473
|
|
1466
1474
|
def get_param_dump_file_path_JSON(self, js_idx: int, js_act_idx: int):
|
1467
1475
|
return Path(self.get_param_dump_file_stem(js_idx, js_act_idx) + ".json")
|
@@ -1945,7 +1953,7 @@ class Action(JSONLike):
|
|
1945
1953
|
"""\
|
1946
1954
|
import {app_module} as app
|
1947
1955
|
app.load_config(
|
1948
|
-
log_file_path=Path("{
|
1956
|
+
log_file_path=Path("{run_log_file}").resolve(),
|
1949
1957
|
config_dir=r"{cfg_dir}",
|
1950
1958
|
config_key=r"{cfg_invoc_key}",
|
1951
1959
|
)
|
@@ -1954,7 +1962,7 @@ class Action(JSONLike):
|
|
1954
1962
|
EAR = wk.get_EARs_from_IDs([EAR_ID])[0]
|
1955
1963
|
"""
|
1956
1964
|
).format(
|
1957
|
-
|
1965
|
+
run_log_file=self.app.RunDirAppFiles.get_log_file_name(),
|
1958
1966
|
app_module=self.app.module,
|
1959
1967
|
cfg_dir=self.app.config.config_directory,
|
1960
1968
|
cfg_invoc_key=self.app.config.config_key,
|
@@ -159,7 +159,7 @@ class InputFileGenerator(JSONLike):
|
|
159
159
|
from pathlib import Path
|
160
160
|
import {app_module} as app
|
161
161
|
app.load_config(
|
162
|
-
log_file_path=Path("{
|
162
|
+
log_file_path=Path("{run_log_file}").resolve(),
|
163
163
|
config_dir=r"{cfg_dir}",
|
164
164
|
config_key=r"{cfg_invoc_key}",
|
165
165
|
)
|
@@ -171,7 +171,7 @@ class InputFileGenerator(JSONLike):
|
|
171
171
|
"""
|
172
172
|
)
|
173
173
|
main_block = main_block.format(
|
174
|
-
|
174
|
+
run_log_file=self.app.RunDirAppFiles.get_log_file_name(),
|
175
175
|
app_module=self.app.module,
|
176
176
|
cfg_dir=self.app.config.config_directory,
|
177
177
|
cfg_invoc_key=self.app.config.config_key,
|
@@ -303,7 +303,7 @@ class OutputFileParser(JSONLike):
|
|
303
303
|
from pathlib import Path
|
304
304
|
import {app_module} as app
|
305
305
|
app.load_config(
|
306
|
-
log_file_path=Path("{
|
306
|
+
log_file_path=Path("{run_log_file}").resolve(),
|
307
307
|
config_dir=r"{cfg_dir}",
|
308
308
|
config_key=r"{cfg_invoc_key}",
|
309
309
|
)
|
@@ -321,7 +321,7 @@ class OutputFileParser(JSONLike):
|
|
321
321
|
"""
|
322
322
|
)
|
323
323
|
main_block = main_block.format(
|
324
|
-
|
324
|
+
run_log_file=self.app.RunDirAppFiles.get_log_file_name(),
|
325
325
|
app_module=self.app.module,
|
326
326
|
cfg_dir=self.app.config.config_directory,
|
327
327
|
cfg_invoc_key=self.app.config.config_key,
|
@@ -13,9 +13,11 @@ from hpcflow.sdk.core.json_like import ChildObjectSpec, JSONLike
|
|
13
13
|
from hpcflow.sdk.core.parallel import ParallelMode
|
14
14
|
from hpcflow.sdk.core.utils import (
|
15
15
|
check_valid_py_identifier,
|
16
|
+
dict_values_process_flat,
|
16
17
|
get_enum_by_name_or_val,
|
17
18
|
split_param_label,
|
18
19
|
)
|
20
|
+
from hpcflow.sdk.log import TimeIt
|
19
21
|
from hpcflow.sdk.submission.shells import get_shell
|
20
22
|
|
21
23
|
|
@@ -500,6 +502,7 @@ class ElementIteration:
|
|
500
502
|
if i.startswith(prefix)
|
501
503
|
)
|
502
504
|
|
505
|
+
@TimeIt.decorator
|
503
506
|
def get_data_idx(
|
504
507
|
self,
|
505
508
|
path: str = None,
|
@@ -538,6 +541,7 @@ class ElementIteration:
|
|
538
541
|
|
539
542
|
return copy.deepcopy(data_idx)
|
540
543
|
|
544
|
+
@TimeIt.decorator
|
541
545
|
def get_parameter_sources(
|
542
546
|
self,
|
543
547
|
path: str = None,
|
@@ -555,24 +559,16 @@ class ElementIteration:
|
|
555
559
|
ID.
|
556
560
|
"""
|
557
561
|
data_idx = self.get_data_idx(path, action_idx, run_idx)
|
558
|
-
out = {}
|
559
|
-
for k, v in data_idx.items():
|
560
|
-
is_multi = False
|
561
|
-
if isinstance(v, list):
|
562
|
-
is_multi = True
|
563
|
-
else:
|
564
|
-
v = [v]
|
565
562
|
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
if not is_multi:
|
572
|
-
sources_k = src
|
573
|
-
|
574
|
-
out[k] = sources_k
|
563
|
+
# the value associated with `repeats.*` is the repeats index, not a parameter ID:
|
564
|
+
for k in list(data_idx.keys()):
|
565
|
+
if k.startswith("repeats."):
|
566
|
+
data_idx.pop(k)
|
575
567
|
|
568
|
+
out = dict_values_process_flat(
|
569
|
+
data_idx,
|
570
|
+
callable=self.workflow.get_parameter_sources,
|
571
|
+
)
|
576
572
|
task_key = "task_insert_ID"
|
577
573
|
|
578
574
|
if use_task_index:
|
@@ -631,6 +627,7 @@ class ElementIteration:
|
|
631
627
|
|
632
628
|
return out
|
633
629
|
|
630
|
+
@TimeIt.decorator
|
634
631
|
def get(
|
635
632
|
self,
|
636
633
|
path: str = None,
|
@@ -856,6 +853,7 @@ class ElementIteration:
|
|
856
853
|
out[res_i.scope.to_string()] = res_i._get_value()
|
857
854
|
return out
|
858
855
|
|
856
|
+
@TimeIt.decorator
|
859
857
|
def get_resources(self, action: app.Action, set_defaults: bool = False) -> Dict:
|
860
858
|
"""Resolve specific resources for the specified action of this iteration,
|
861
859
|
considering all applicable scopes.
|
@@ -998,6 +996,7 @@ class Element:
|
|
998
996
|
return self._iteration_IDs
|
999
997
|
|
1000
998
|
@property
|
999
|
+
@TimeIt.decorator
|
1001
1000
|
def iterations(self) -> Dict[app.ElementAction]:
|
1002
1001
|
# TODO: fix this
|
1003
1002
|
if self._iteration_objs is None:
|
@@ -0,0 +1,63 @@
|
|
1
|
+
import re
|
2
|
+
from hpcflow.sdk.core.utils import JSONLikeDirSnapShot
|
3
|
+
|
4
|
+
|
5
|
+
class RunDirAppFiles:
|
6
|
+
"""A class to encapsulate the naming/recognition of app-created files within run
|
7
|
+
directories."""
|
8
|
+
|
9
|
+
_app_attr = "app"
|
10
|
+
|
11
|
+
CMD_FILES_RE_PATTERN = r"js_\d+_act_\d+\.?\w*"
|
12
|
+
|
13
|
+
@classmethod
|
14
|
+
def get_log_file_name(cls):
|
15
|
+
"""File name for the app log file."""
|
16
|
+
return f"{cls.app.package_name}.log"
|
17
|
+
|
18
|
+
@classmethod
|
19
|
+
def get_std_file_name(cls):
|
20
|
+
"""File name for stdout and stderr streams from the app."""
|
21
|
+
return f"{cls.app.package_name}_std.txt"
|
22
|
+
|
23
|
+
@staticmethod
|
24
|
+
def get_run_file_prefix(js_idx: int, js_action_idx: int):
|
25
|
+
return f"js_{js_idx}_act_{js_action_idx}"
|
26
|
+
|
27
|
+
@classmethod
|
28
|
+
def get_commands_file_name(cls, js_idx: int, js_action_idx: int, shell):
|
29
|
+
return cls.get_run_file_prefix(js_idx, js_action_idx) + shell.JS_EXT
|
30
|
+
|
31
|
+
@classmethod
|
32
|
+
def get_run_param_dump_file_prefix(cls, js_idx: int, js_action_idx: int):
|
33
|
+
"""Get the prefix to a file in the run directory that the app will dump parameter
|
34
|
+
data to."""
|
35
|
+
return cls.get_run_file_prefix(js_idx, js_action_idx) + "_inputs"
|
36
|
+
|
37
|
+
@classmethod
|
38
|
+
def get_run_param_load_file_prefix(cls, js_idx: int, js_action_idx: int):
|
39
|
+
"""Get the prefix to a file in the run directory that the app will load parameter
|
40
|
+
data from."""
|
41
|
+
return cls.get_run_file_prefix(js_idx, js_action_idx) + "_outputs"
|
42
|
+
|
43
|
+
@classmethod
|
44
|
+
def take_snapshot(cls):
|
45
|
+
"""Take a JSONLikeDirSnapShot, and process to ignore files created by the app.
|
46
|
+
|
47
|
+
This includes command files that are invoked by jobscripts, the app log file, and
|
48
|
+
the app standard out/error file.
|
49
|
+
|
50
|
+
"""
|
51
|
+
snapshot = JSONLikeDirSnapShot()
|
52
|
+
snapshot.take(".")
|
53
|
+
ss_js = snapshot.to_json_like()
|
54
|
+
ss_js.pop("root_path") # always the current working directory of the run
|
55
|
+
for k in list(ss_js["data"].keys()):
|
56
|
+
if (
|
57
|
+
k == cls.get_log_file_name()
|
58
|
+
or k == cls.get_std_file_name()
|
59
|
+
or re.match(cls.CMD_FILES_RE_PATTERN, k)
|
60
|
+
):
|
61
|
+
ss_js["data"].pop(k)
|
62
|
+
|
63
|
+
return ss_js
|