hpcflow-new2 0.2.0a149__tar.gz → 0.2.0a153__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 (153) hide show
  1. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/PKG-INFO +1 -1
  2. hpcflow_new2-0.2.0a153/hpcflow/_version.py +1 -0
  3. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/app.py +35 -4
  4. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/cli.py +32 -1
  5. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/cli_common.py +11 -0
  6. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/core/actions.py +2 -0
  7. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/core/errors.py +4 -0
  8. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/core/task.py +8 -0
  9. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/core/utils.py +44 -16
  10. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/core/workflow.py +108 -20
  11. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/demo/cli.py +7 -0
  12. hpcflow_new2-0.2.0a153/hpcflow/sdk/log.py +173 -0
  13. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/persistence/base.py +4 -1
  14. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/persistence/pending.py +26 -0
  15. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/persistence/zarr.py +3 -0
  16. hpcflow_new2-0.2.0a153/hpcflow/tests/data/benchmark_N_elements.yaml +6 -0
  17. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/tests/unit/test_utils.py +45 -1
  18. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/tests/unit/test_workflow_template.py +9 -0
  19. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/pyproject.toml +2 -2
  20. hpcflow_new2-0.2.0a149/hpcflow/_version.py +0 -1
  21. hpcflow_new2-0.2.0a149/hpcflow/sdk/log.py +0 -49
  22. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/README.md +0 -0
  23. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/__init__.py +0 -0
  24. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/__pyinstaller/__init__.py +0 -0
  25. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/__pyinstaller/hook-hpcflow.py +0 -0
  26. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/app.py +0 -0
  27. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/cli.py +0 -0
  28. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/data/demo_data_manifest/__init__.py +0 -0
  29. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/data/demo_data_manifest/demo_data_manifest.json +0 -0
  30. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/data/scripts/__init__.py +0 -0
  31. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/data/scripts/demo_task_1_generate_t1_infile_1.py +0 -0
  32. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/data/scripts/demo_task_1_generate_t1_infile_2.py +0 -0
  33. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/data/scripts/demo_task_1_parse_p3.py +0 -0
  34. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/data/scripts/generate_t1_file_01.py +0 -0
  35. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/data/scripts/main_script_test_direct_in_direct_out.py +0 -0
  36. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/data/scripts/main_script_test_direct_in_direct_out_all_iters_test.py +0 -0
  37. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/data/scripts/main_script_test_direct_in_direct_out_labels.py +0 -0
  38. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/data/scripts/main_script_test_direct_sub_param_in_direct_out.py +0 -0
  39. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/data/scripts/main_script_test_hdf5_in_obj.py +0 -0
  40. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/data/scripts/main_script_test_hdf5_out_obj.py +0 -0
  41. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/data/scripts/main_script_test_json_and_direct_in_json_out.py +0 -0
  42. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/data/scripts/main_script_test_json_in_json_and_direct_out.py +0 -0
  43. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/data/scripts/main_script_test_json_in_json_out.py +0 -0
  44. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/data/scripts/main_script_test_json_in_json_out_labels.py +0 -0
  45. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/data/scripts/main_script_test_json_in_obj.py +0 -0
  46. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/data/scripts/main_script_test_json_out_obj.py +0 -0
  47. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/data/scripts/main_script_test_json_sub_param_in_json_out_labels.py +0 -0
  48. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/data/scripts/parse_t1_file_01.py +0 -0
  49. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/data/template_components/__init__.py +0 -0
  50. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/data/template_components/command_files.yaml +0 -0
  51. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/data/template_components/environments.yaml +0 -0
  52. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/data/template_components/parameters.yaml +0 -0
  53. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/data/template_components/task_schemas.yaml +0 -0
  54. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/data/workflows/__init__.py +0 -0
  55. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/data/workflows/workflow_1.yaml +0 -0
  56. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/examples.ipynb +0 -0
  57. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/__init__.py +0 -0
  58. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/config/__init__.py +0 -0
  59. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/config/callbacks.py +0 -0
  60. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/config/cli.py +0 -0
  61. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/config/config.py +0 -0
  62. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/config/config_file.py +0 -0
  63. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/config/errors.py +0 -0
  64. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/core/__init__.py +0 -0
  65. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/core/command_files.py +0 -0
  66. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/core/commands.py +0 -0
  67. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/core/element.py +0 -0
  68. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/core/environment.py +0 -0
  69. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/core/json_like.py +0 -0
  70. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/core/loop.py +0 -0
  71. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/core/object_list.py +0 -0
  72. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/core/parallel.py +0 -0
  73. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/core/parameters.py +0 -0
  74. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/core/rule.py +0 -0
  75. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/core/task_schema.py +0 -0
  76. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/core/test_utils.py +0 -0
  77. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/core/validation.py +0 -0
  78. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/core/zarr_io.py +0 -0
  79. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/data/__init__.py +0 -0
  80. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/data/config_file_schema.yaml +0 -0
  81. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/data/config_schema.yaml +0 -0
  82. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/data/environments_spec_schema.yaml +0 -0
  83. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/data/files_spec_schema.yaml +0 -0
  84. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/data/parameters_spec_schema.yaml +0 -0
  85. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/data/task_schema_spec_schema.yaml +0 -0
  86. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/data/workflow_spec_schema.yaml +0 -0
  87. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/demo/__init__.py +0 -0
  88. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/helper/__init__.py +0 -0
  89. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/helper/cli.py +0 -0
  90. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/helper/helper.py +0 -0
  91. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/helper/watcher.py +0 -0
  92. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/persistence/__init__.py +0 -0
  93. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/persistence/json.py +0 -0
  94. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/persistence/store_resource.py +0 -0
  95. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/persistence/utils.py +0 -0
  96. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/runtime.py +0 -0
  97. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/submission/__init__.py +0 -0
  98. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/submission/jobscript.py +0 -0
  99. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/submission/jobscript_info.py +0 -0
  100. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/submission/schedulers/__init__.py +0 -0
  101. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/submission/schedulers/direct.py +0 -0
  102. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/submission/schedulers/sge.py +0 -0
  103. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/submission/schedulers/slurm.py +0 -0
  104. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/submission/schedulers/utils.py +0 -0
  105. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/submission/shells/__init__.py +0 -0
  106. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/submission/shells/base.py +0 -0
  107. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/submission/shells/bash.py +0 -0
  108. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/submission/shells/os_version.py +0 -0
  109. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/submission/shells/powershell.py +0 -0
  110. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/submission/submission.py +0 -0
  111. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/sdk/typing.py +0 -0
  112. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/tests/conftest.py +0 -0
  113. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/tests/data/__init__.py +0 -0
  114. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/tests/data/workflow_1.json +0 -0
  115. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/tests/data/workflow_1.yaml +0 -0
  116. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/tests/data/workflow_1_slurm.yaml +0 -0
  117. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/tests/data/workflow_1_wsl.yaml +0 -0
  118. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/tests/data/workflow_test_run_abort.yaml +0 -0
  119. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/tests/schedulers/direct_linux/test_direct_linux_submission.py +0 -0
  120. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/tests/schedulers/slurm/test_slurm_submission.py +0 -0
  121. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/tests/scripts/test_main_scripts.py +0 -0
  122. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/tests/shells/wsl/test_wsl_submission.py +0 -0
  123. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/tests/unit/test_action.py +0 -0
  124. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/tests/unit/test_action_rule.py +0 -0
  125. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/tests/unit/test_app.py +0 -0
  126. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/tests/unit/test_cli.py +0 -0
  127. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/tests/unit/test_command.py +0 -0
  128. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/tests/unit/test_config.py +0 -0
  129. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/tests/unit/test_config_file.py +0 -0
  130. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/tests/unit/test_element.py +0 -0
  131. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/tests/unit/test_element_iteration.py +0 -0
  132. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/tests/unit/test_element_set.py +0 -0
  133. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/tests/unit/test_input_source.py +0 -0
  134. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/tests/unit/test_input_value.py +0 -0
  135. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/tests/unit/test_json_like.py +0 -0
  136. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/tests/unit/test_loop.py +0 -0
  137. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/tests/unit/test_object_list.py +0 -0
  138. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/tests/unit/test_parameter.py +0 -0
  139. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/tests/unit/test_persistence.py +0 -0
  140. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/tests/unit/test_resources.py +0 -0
  141. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/tests/unit/test_run.py +0 -0
  142. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/tests/unit/test_runtime.py +0 -0
  143. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/tests/unit/test_schema_input.py +0 -0
  144. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/tests/unit/test_shell.py +0 -0
  145. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/tests/unit/test_slurm.py +0 -0
  146. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/tests/unit/test_submission.py +0 -0
  147. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/tests/unit/test_task.py +0 -0
  148. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/tests/unit/test_task_schema.py +0 -0
  149. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/tests/unit/test_value_sequence.py +0 -0
  150. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/tests/unit/test_workflow.py +0 -0
  151. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/tests/workflows/test_jobscript.py +0 -0
  152. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/tests/workflows/test_workflows.py +0 -0
  153. {hpcflow_new2-0.2.0a149 → hpcflow_new2-0.2.0a153}/hpcflow/viz_demo.ipynb +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: hpcflow-new2
3
- Version: 0.2.0a149
3
+ Version: 0.2.0a153
4
4
  Summary: Computational workflow management
5
5
  License: MIT
6
6
  Author: aplowman
@@ -0,0 +1 @@
1
+ __version__ = "0.2.0a153"
@@ -1,4 +1,5 @@
1
1
  """An hpcflow application."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from collections import defaultdict
@@ -37,7 +38,7 @@ from hpcflow.sdk.core.actions import EARStatus
37
38
  from hpcflow.sdk.core.errors import WorkflowNotFoundError
38
39
  from hpcflow.sdk.core.object_list import ObjectList
39
40
  from hpcflow.sdk.core.utils import (
40
- read_YAML,
41
+ read_YAML_str,
41
42
  read_YAML_file,
42
43
  read_JSON_file,
43
44
  write_YAML_file,
@@ -46,7 +47,7 @@ from hpcflow.sdk.core.utils import (
46
47
  from hpcflow.sdk import sdk_classes, sdk_funcs, get_SDK_logger
47
48
  from hpcflow.sdk.config import Config, ConfigFile
48
49
  from hpcflow.sdk.core import ALL_TEMPLATE_FORMATS
49
- from hpcflow.sdk.log import AppLog
50
+ from hpcflow.sdk.log import AppLog, TimeIt
50
51
  from hpcflow.sdk.persistence import DEFAULT_STORE_FORMAT
51
52
  from hpcflow.sdk.persistence.base import TEMPLATE_COMP_TYPES
52
53
  from hpcflow.sdk.runtime import RunTimeInfo
@@ -95,7 +96,10 @@ class Singleton(type):
95
96
  _instances = {}
96
97
 
97
98
  def __call__(cls, *args, **kwargs):
98
- SDK_logger.info(f"App metaclass __call__ with {args=} {kwargs=}")
99
+ SDK_logger.info(
100
+ f"App metaclass __call__: "
101
+ f"name={kwargs['name']!r}, version={kwargs['version']!r}."
102
+ )
99
103
  if cls not in cls._instances:
100
104
  SDK_logger.info(f"App metaclass initialising new object {kwargs['name']!r}.")
101
105
  cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
@@ -255,6 +259,14 @@ class BaseApp(metaclass=Singleton):
255
259
  def log(self) -> AppLog:
256
260
  return self._log
257
261
 
262
+ @property
263
+ def timeit(self) -> bool:
264
+ return TimeIt.active
265
+
266
+ @timeit.setter
267
+ def timeit(self, value: bool):
268
+ TimeIt.active = bool(value)
269
+
258
270
  @property
259
271
  def template_components(self) -> Dict[str, ObjectList]:
260
272
  if not self.is_template_components_loaded:
@@ -281,6 +293,7 @@ class BaseApp(metaclass=Singleton):
281
293
  warnings.warn("Template components not loaded; loading now.")
282
294
  self._load_template_components()
283
295
 
296
+ @TimeIt.decorator
284
297
  def _load_template_components(self, *include) -> None:
285
298
  """Combine any builtin template components with user-defined template components
286
299
  and initialise list objects."""
@@ -366,7 +379,7 @@ class BaseApp(metaclass=Singleton):
366
379
  fh = resources.open_text(package, resource)
367
380
  SDK_logger.info(f"Parsing file as YAML: {fh.name!r}")
368
381
  comp_dat = fh.read()
369
- components[comp_type] = read_YAML(comp_dat)
382
+ components[comp_type] = read_YAML_str(comp_dat)
370
383
  fh.close()
371
384
 
372
385
  return components
@@ -625,6 +638,7 @@ class BaseApp(metaclass=Singleton):
625
638
  shutil.rmtree(self.user_cache_hostname_dir)
626
639
  self._ensure_user_cache_hostname_dir()
627
640
 
641
+ @TimeIt.decorator
628
642
  def _load_config(self, config_dir, config_key, **overrides) -> None:
629
643
  self.logger.info("Loading configuration.")
630
644
  self._ensure_user_data_dir()
@@ -714,6 +728,7 @@ class BaseApp(metaclass=Singleton):
714
728
  self._config_files = {}
715
729
  self._load_config(config_dir, config_key, **overrides)
716
730
 
731
+ @TimeIt.decorator
717
732
  def _load_scripts(self):
718
733
  # TODO: load custom directories / custom functions (via decorator)
719
734
 
@@ -1126,6 +1141,7 @@ class BaseApp(metaclass=Singleton):
1126
1141
  ts_fmt: Optional[str] = None,
1127
1142
  ts_name_fmt: Optional[str] = None,
1128
1143
  store_kwargs: Optional[Dict] = None,
1144
+ variables: Optional[Dict[str, str]] = None,
1129
1145
  ) -> get_app_attribute("Workflow"):
1130
1146
  """Generate a new {app_name} workflow from a file or string containing a workflow
1131
1147
  template parametrisation.
@@ -1160,6 +1176,8 @@ class BaseApp(metaclass=Singleton):
1160
1176
  includes a timestamp.
1161
1177
  store_kwargs
1162
1178
  Keyword arguments to pass to the store's `write_empty_workflow` method.
1179
+ variables
1180
+ String variables to substitute in `template_file_or_str`.
1163
1181
  """
1164
1182
 
1165
1183
  self.API_logger.info("make_workflow called")
@@ -1172,6 +1190,7 @@ class BaseApp(metaclass=Singleton):
1172
1190
  "ts_fmt": ts_fmt,
1173
1191
  "ts_name_fmt": ts_name_fmt,
1174
1192
  "store_kwargs": store_kwargs,
1193
+ "variables": variables,
1175
1194
  }
1176
1195
 
1177
1196
  if not is_string:
@@ -1212,6 +1231,7 @@ class BaseApp(metaclass=Singleton):
1212
1231
  ts_fmt: Optional[str] = None,
1213
1232
  ts_name_fmt: Optional[str] = None,
1214
1233
  store_kwargs: Optional[Dict] = None,
1234
+ variables: Optional[Dict[str, str]] = None,
1215
1235
  JS_parallelism: Optional[bool] = None,
1216
1236
  wait: Optional[bool] = False,
1217
1237
  add_to_known: Optional[bool] = True,
@@ -1252,6 +1272,8 @@ class BaseApp(metaclass=Singleton):
1252
1272
  includes a timestamp.
1253
1273
  store_kwargs
1254
1274
  Keyword arguments to pass to the store's `write_empty_workflow` method.
1275
+ variables
1276
+ String variables to substitute in `template_file_or_str`.
1255
1277
  JS_parallelism
1256
1278
  If True, allow multiple jobscripts to execute simultaneously. Raises if set to
1257
1279
  True but the store type does not support the `jobscript_parallelism` feature. If
@@ -1282,6 +1304,7 @@ class BaseApp(metaclass=Singleton):
1282
1304
  ts_fmt=ts_fmt,
1283
1305
  ts_name_fmt=ts_name_fmt,
1284
1306
  store_kwargs=store_kwargs,
1307
+ variables=variables,
1285
1308
  )
1286
1309
  return wk.submit(
1287
1310
  JS_parallelism=JS_parallelism,
@@ -1302,6 +1325,7 @@ class BaseApp(metaclass=Singleton):
1302
1325
  ts_fmt: Optional[str] = None,
1303
1326
  ts_name_fmt: Optional[str] = None,
1304
1327
  store_kwargs: Optional[Dict] = None,
1328
+ variables: Optional[Dict[str, str]] = None,
1305
1329
  ) -> get_app_attribute("Workflow"):
1306
1330
  """Generate a new {app_name} workflow from a builtin demo workflow template.
1307
1331
 
@@ -1333,6 +1357,8 @@ class BaseApp(metaclass=Singleton):
1333
1357
  includes a timestamp.
1334
1358
  store_kwargs
1335
1359
  Keyword arguments to pass to the store's `write_empty_workflow` method.
1360
+ variables
1361
+ String variables to substitute in the demo workflow template file.
1336
1362
  """
1337
1363
 
1338
1364
  self.API_logger.info("make_demo_workflow called")
@@ -1348,6 +1374,7 @@ class BaseApp(metaclass=Singleton):
1348
1374
  ts_fmt=ts_fmt,
1349
1375
  ts_name_fmt=ts_name_fmt,
1350
1376
  store_kwargs=store_kwargs,
1377
+ variables=variables,
1351
1378
  )
1352
1379
  return wk
1353
1380
 
@@ -1362,6 +1389,7 @@ class BaseApp(metaclass=Singleton):
1362
1389
  ts_fmt: Optional[str] = None,
1363
1390
  ts_name_fmt: Optional[str] = None,
1364
1391
  store_kwargs: Optional[Dict] = None,
1392
+ variables: Optional[Dict[str, str]] = None,
1365
1393
  JS_parallelism: Optional[bool] = None,
1366
1394
  wait: Optional[bool] = False,
1367
1395
  add_to_known: Optional[bool] = True,
@@ -1399,6 +1427,8 @@ class BaseApp(metaclass=Singleton):
1399
1427
  includes a timestamp.
1400
1428
  store_kwargs
1401
1429
  Keyword arguments to pass to the store's `write_empty_workflow` method.
1430
+ variables
1431
+ String variables to substitute in the demo workflow template file.
1402
1432
  JS_parallelism
1403
1433
  If True, allow multiple jobscripts to execute simultaneously. Raises if set to
1404
1434
  True but the store type does not support the `jobscript_parallelism` feature. If
@@ -1428,6 +1458,7 @@ class BaseApp(metaclass=Singleton):
1428
1458
  ts_fmt=ts_fmt,
1429
1459
  ts_name_fmt=ts_name_fmt,
1430
1460
  store_kwargs=store_kwargs,
1461
+ variables=variables,
1431
1462
  )
1432
1463
  return wk.submit(
1433
1464
  JS_parallelism=JS_parallelism,
@@ -19,6 +19,7 @@ from hpcflow.sdk.cli_common import (
19
19
  store_option,
20
20
  ts_fmt_option,
21
21
  ts_name_fmt_option,
22
+ variables_option,
22
23
  js_parallelism_option,
23
24
  wait_option,
24
25
  add_to_known_opt,
@@ -31,6 +32,7 @@ from hpcflow.sdk.cli_common import (
31
32
  unzip_log_opt,
32
33
  )
33
34
  from hpcflow.sdk.helper.cli import get_helper_CLI
35
+ from hpcflow.sdk.log import TimeIt
34
36
  from hpcflow.sdk.submission.shells import ALL_SHELLS
35
37
 
36
38
  string_option = click.option(
@@ -68,6 +70,7 @@ def _make_API_CLI(app):
68
70
  @store_option
69
71
  @ts_fmt_option
70
72
  @ts_name_fmt_option
73
+ @variables_option
71
74
  def make_workflow(
72
75
  template_file_or_str,
73
76
  string,
@@ -78,6 +81,7 @@ def _make_API_CLI(app):
78
81
  store,
79
82
  ts_fmt=None,
80
83
  ts_name_fmt=None,
84
+ variables=None,
81
85
  ):
82
86
  """Generate a new {app_name} workflow.
83
87
 
@@ -95,6 +99,7 @@ def _make_API_CLI(app):
95
99
  store=store,
96
100
  ts_fmt=ts_fmt,
97
101
  ts_name_fmt=ts_name_fmt,
102
+ variables=dict(variables),
98
103
  )
99
104
  click.echo(wk.path)
100
105
 
@@ -108,6 +113,7 @@ def _make_API_CLI(app):
108
113
  @store_option
109
114
  @ts_fmt_option
110
115
  @ts_name_fmt_option
116
+ @variables_option
111
117
  @js_parallelism_option
112
118
  @wait_option
113
119
  @add_to_known_opt
@@ -123,6 +129,7 @@ def _make_API_CLI(app):
123
129
  store,
124
130
  ts_fmt=None,
125
131
  ts_name_fmt=None,
132
+ variables=None,
126
133
  js_parallelism=None,
127
134
  wait=False,
128
135
  add_to_known=True,
@@ -146,6 +153,7 @@ def _make_API_CLI(app):
146
153
  store=store,
147
154
  ts_fmt=ts_fmt,
148
155
  ts_name_fmt=ts_name_fmt,
156
+ variables=dict(variables),
149
157
  JS_parallelism=js_parallelism,
150
158
  wait=wait,
151
159
  add_to_known=add_to_known,
@@ -1032,9 +1040,27 @@ def make_cli(app):
1032
1040
  nargs=2,
1033
1041
  multiple=True,
1034
1042
  )
1043
+ @click.option(
1044
+ "--timeit",
1045
+ help=(
1046
+ "Time function pathways as the code executes and write out a summary at the "
1047
+ "end. Only functions decorated by `TimeIt.decorator` are included."
1048
+ ),
1049
+ is_flag=True,
1050
+ )
1051
+ @click.option(
1052
+ "--timeit-file",
1053
+ help=(
1054
+ "Time function pathways as the code executes and write out a summary at the "
1055
+ "end to a text file given by this file path. Only functions decorated by "
1056
+ "`TimeIt.decorator` are included."
1057
+ ),
1058
+ )
1035
1059
  @click.pass_context
1036
- def new_CLI(ctx, config_dir, config_key, with_config):
1060
+ def new_CLI(ctx, config_dir, config_key, with_config, timeit, timeit_file):
1037
1061
  app.run_time_info.from_CLI = True
1062
+ TimeIt.active = timeit or timeit_file
1063
+ TimeIt.file_path = timeit_file
1038
1064
  if ctx.invoked_subcommand != "manage":
1039
1065
  # load the config
1040
1066
  overrides = {kv[0]: kv[1] for kv in with_config}
@@ -1048,6 +1074,11 @@ def make_cli(app):
1048
1074
  click.echo(f"{colored(err.__class__.__name__, 'red')}: {err}")
1049
1075
  ctx.exit(1)
1050
1076
 
1077
+ @new_CLI.result_callback()
1078
+ def post_execution(*args, **kwargs):
1079
+ if TimeIt.active:
1080
+ TimeIt.summarise_string()
1081
+
1051
1082
  @new_CLI.command()
1052
1083
  @click.argument("name")
1053
1084
  @click.option("--use-current-env", is_flag=True, default=False)
@@ -63,6 +63,17 @@ ts_name_fmt_option = click.option(
63
63
  "includes a timestamp."
64
64
  ),
65
65
  )
66
+ variables_option = click.option(
67
+ "-v",
68
+ "--var",
69
+ "variables",
70
+ type=(str, str),
71
+ multiple=True,
72
+ help=(
73
+ "Workflow template variable value to be substituted in to the template file or "
74
+ "string. Multiple variable values can be specified."
75
+ ),
76
+ )
66
77
  js_parallelism_option = click.option(
67
78
  "--js-parallelism",
68
79
  help=(
@@ -29,6 +29,7 @@ from hpcflow.sdk.core.utils import (
29
29
  split_param_label,
30
30
  swap_nested_dict_keys,
31
31
  )
32
+ from hpcflow.sdk.log import TimeIt
32
33
 
33
34
 
34
35
  ACTION_SCOPE_REGEX = r"(\w*)(?:\[(.*)\])?"
@@ -1720,6 +1721,7 @@ class Action(JSONLike):
1720
1721
  def get_output_file_labels(self):
1721
1722
  return tuple(i.label for i in self.output_files)
1722
1723
 
1724
+ @TimeIt.decorator
1723
1725
  def generate_data_index(
1724
1726
  self,
1725
1727
  act_idx,
@@ -387,3 +387,7 @@ class UnknownScriptDataParameter(ValueError):
387
387
 
388
388
  class UnknownScriptDataKey(ValueError):
389
389
  pass
390
+
391
+
392
+ class MissingVariableSubstitutionError(KeyError):
393
+ pass
@@ -10,6 +10,7 @@ from valida.rules import Rule
10
10
 
11
11
  from hpcflow.sdk import app
12
12
  from hpcflow.sdk.core.task_schema import TaskSchema
13
+ from hpcflow.sdk.log import TimeIt
13
14
  from hpcflow.sdk.submission.shells import DEFAULT_SHELL_NAMES
14
15
  from .json_like import ChildObjectSpec, JSONLike
15
16
  from .element import ElementGroup
@@ -719,6 +720,7 @@ class Task(JSONLike):
719
720
  """Find the nesting order for a task sequence."""
720
721
  return self.nesting_order[seq.normalised_path] if len(seq.values) > 1 else -1
721
722
 
723
+ @TimeIt.decorator
722
724
  def _prepare_persistent_outputs(self, workflow, local_element_idx_range):
723
725
  # TODO: check that schema is present when adding task? (should this be here?)
724
726
 
@@ -1790,6 +1792,7 @@ class WorkflowTask:
1790
1792
 
1791
1793
  return element_dat_idx
1792
1794
 
1795
+ @TimeIt.decorator
1793
1796
  def initialise_EARs(self) -> List[int]:
1794
1797
  """Try to initialise any uninitialised EARs of this task."""
1795
1798
  initialised = []
@@ -1815,6 +1818,7 @@ class WorkflowTask:
1815
1818
  self.workflow.set_EARs_initialised(iter_i.id_)
1816
1819
  return initialised
1817
1820
 
1821
+ @TimeIt.decorator
1818
1822
  def _initialise_element_iter_EARs(self, element_iter: app.ElementIteration) -> None:
1819
1823
  # keys are (act_idx, EAR_idx):
1820
1824
  all_data_idx = {}
@@ -1878,6 +1882,7 @@ class WorkflowTask:
1878
1882
  for pid, src in param_src_updates.items():
1879
1883
  self.workflow._store.update_param_source(pid, src)
1880
1884
 
1885
+ @TimeIt.decorator
1881
1886
  def _add_element_set(self, element_set):
1882
1887
  """
1883
1888
  Returns
@@ -1982,6 +1987,7 @@ class WorkflowTask:
1982
1987
  return_indices=return_indices,
1983
1988
  )
1984
1989
 
1990
+ @TimeIt.decorator
1985
1991
  def _add_elements(
1986
1992
  self,
1987
1993
  base_element=None,
@@ -2153,6 +2159,7 @@ class WorkflowTask:
2153
2159
 
2154
2160
  return deps
2155
2161
 
2162
+ @TimeIt.decorator
2156
2163
  def get_dependent_tasks(
2157
2164
  self,
2158
2165
  as_objects: bool = False,
@@ -2251,6 +2258,7 @@ class WorkflowTask:
2251
2258
 
2252
2259
  return params
2253
2260
 
2261
+ @TimeIt.decorator
2254
2262
  def _get_merged_parameter_data(
2255
2263
  self,
2256
2264
  data_index,
@@ -15,7 +15,7 @@ import string
15
15
  import subprocess
16
16
  from datetime import datetime, timezone
17
17
  import sys
18
- from typing import Optional, Tuple, Type, Union, List
18
+ from typing import Dict, Optional, Tuple, Type, Union, List
19
19
  import fsspec
20
20
  import numpy as np
21
21
 
@@ -27,7 +27,9 @@ from hpcflow.sdk.core.errors import (
27
27
  ContainerKeyError,
28
28
  FromSpecMissingObjectError,
29
29
  InvalidIdentifier,
30
+ MissingVariableSubstitutionError,
30
31
  )
32
+ from hpcflow.sdk.log import TimeIt
31
33
  from hpcflow.sdk.typing import PathLike
32
34
 
33
35
 
@@ -385,19 +387,42 @@ def check_in_object_list(spec_name, spec_pos=1, obj_list_pos=2):
385
387
  return decorator
386
388
 
387
389
 
388
- def read_YAML(loadable_yaml, typ="safe"):
390
+ def substitute_string_vars(string, variables: Dict[str, str] = None):
391
+ variables = variables or {}
392
+
393
+ def var_repl(match_obj):
394
+ var_name = match_obj.group(1)
395
+ try:
396
+ out = str(variables[var_name])
397
+ except KeyError:
398
+ raise MissingVariableSubstitutionError(
399
+ f"The variable {var_name!r} referenced in the string does not match any "
400
+ f"of the provided variables: {list(variables)!r}."
401
+ )
402
+ return out
403
+
404
+ new_str = re.sub(
405
+ pattern=r"\<\<var:(.*?)\>\>",
406
+ repl=var_repl,
407
+ string=string,
408
+ )
409
+ return new_str
410
+
411
+
412
+ @TimeIt.decorator
413
+ def read_YAML_str(yaml_str, typ="safe", variables: Dict[str, str] = None):
414
+ """Load a YAML string."""
415
+ if variables:
416
+ yaml_str = substitute_string_vars(yaml_str, variables=variables)
389
417
  yaml = YAML(typ=typ)
390
- return yaml.load(loadable_yaml)
418
+ return yaml.load(yaml_str)
391
419
 
392
420
 
393
- def read_YAML_file(path: PathLike, typ="safe"):
394
- if is_fsspec_url(str(path)):
395
- with fsspec.open(path, "rt") as f:
396
- data = f.read()
397
- loadable_yaml = data
398
- else:
399
- loadable_yaml = Path(path)
400
- return read_YAML(loadable_yaml, typ=typ)
421
+ @TimeIt.decorator
422
+ def read_YAML_file(path: PathLike, typ="safe", variables: Dict[str, str] = None):
423
+ with fsspec.open(path, "rt") as f:
424
+ yaml_str = f.read()
425
+ return read_YAML_str(yaml_str, typ=typ, variables=variables)
401
426
 
402
427
 
403
428
  def write_YAML_file(obj, path: PathLike, typ="safe"):
@@ -406,13 +431,16 @@ def write_YAML_file(obj, path: PathLike, typ="safe"):
406
431
  yaml.dump(obj, fp)
407
432
 
408
433
 
409
- def read_JSON_string(string: str):
410
- return json.loads(string)
434
+ def read_JSON_string(json_str: str, variables: Dict[str, str] = None):
435
+ if variables:
436
+ json_str = substitute_string_vars(json_str, variables=variables)
437
+ return json.loads(json_str)
411
438
 
412
439
 
413
- def read_JSON_file(path):
414
- with Path(path).open("rt") as fh:
415
- return json.load(fh)
440
+ def read_JSON_file(path, variables: Dict[str, str] = None):
441
+ with fsspec.open(path, "rt") as f:
442
+ json_str = f.read()
443
+ return read_JSON_string(json_str, variables=variables)
416
444
 
417
445
 
418
446
  def write_JSON_file(obj, path: PathLike):