easylink 0.1.17__tar.gz → 0.1.18__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 (221) hide show
  1. {easylink-0.1.17 → easylink-0.1.18}/CHANGELOG.rst +4 -0
  2. {easylink-0.1.17 → easylink-0.1.18}/PKG-INFO +1 -1
  3. easylink-0.1.18/src/easylink/_version.py +1 -0
  4. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/cli.py +9 -0
  5. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/configuration.py +18 -34
  6. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/devtools/implementation_creator.py +13 -11
  7. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/implementation_metadata.yaml +0 -3
  8. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/pipeline_schema.py +12 -13
  9. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/pipeline_schema_constants/__init__.py +3 -4
  10. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/runner.py +5 -7
  11. {easylink-0.1.17 → easylink-0.1.18}/src/easylink.egg-info/PKG-INFO +1 -1
  12. {easylink-0.1.17 → easylink-0.1.18}/tests/e2e/test_easylink_run.py +2 -1
  13. {easylink-0.1.17 → easylink-0.1.18}/tests/e2e/test_step_types.py +2 -1
  14. {easylink-0.1.17 → easylink-0.1.18}/tests/integration/test_compositions.py +5 -11
  15. {easylink-0.1.17 → easylink-0.1.18}/tests/integration/test_snakemake.py +3 -5
  16. {easylink-0.1.17 → easylink-0.1.18}/tests/integration/test_snakemake_slurm.py +2 -3
  17. {easylink-0.1.17 → easylink-0.1.18}/tests/integration/test_snakemake_spark.py +2 -3
  18. {easylink-0.1.17 → easylink-0.1.18}/tests/unit/conftest.py +1 -1
  19. {easylink-0.1.17 → easylink-0.1.18}/tests/unit/test_config.py +24 -6
  20. {easylink-0.1.17 → easylink-0.1.18}/tests/unit/test_implementation_creator.py +13 -3
  21. {easylink-0.1.17 → easylink-0.1.18}/tests/unit/test_pipeline.py +1 -1
  22. {easylink-0.1.17 → easylink-0.1.18}/tests/unit/test_pipeline_graph.py +10 -18
  23. {easylink-0.1.17 → easylink-0.1.18}/tests/unit/test_pipeline_schema.py +15 -19
  24. {easylink-0.1.17 → easylink-0.1.18}/tests/unit/test_runner.py +2 -2
  25. {easylink-0.1.17 → easylink-0.1.18}/tests/unit/test_validations.py +10 -10
  26. easylink-0.1.17/src/easylink/_version.py +0 -1
  27. {easylink-0.1.17 → easylink-0.1.18}/.bandit +0 -0
  28. {easylink-0.1.17 → easylink-0.1.18}/.flake8 +0 -0
  29. {easylink-0.1.17 → easylink-0.1.18}/.github/CODEOWNERS +0 -0
  30. {easylink-0.1.17 → easylink-0.1.18}/.github/pull_request_template.md +0 -0
  31. {easylink-0.1.17 → easylink-0.1.18}/.github/workflows/deploy.yml +0 -0
  32. {easylink-0.1.17 → easylink-0.1.18}/.github/workflows/update_readme.yml +0 -0
  33. {easylink-0.1.17 → easylink-0.1.18}/.gitignore +0 -0
  34. {easylink-0.1.17 → easylink-0.1.18}/.readthedocs.yml +0 -0
  35. {easylink-0.1.17 → easylink-0.1.18}/CONTRIBUTING.rst +0 -0
  36. {easylink-0.1.17 → easylink-0.1.18}/Jenkinsfile +0 -0
  37. {easylink-0.1.17 → easylink-0.1.18}/Makefile +0 -0
  38. {easylink-0.1.17 → easylink-0.1.18}/README.rst +0 -0
  39. {easylink-0.1.17 → easylink-0.1.18}/docs/Makefile +0 -0
  40. {easylink-0.1.17 → easylink-0.1.18}/docs/nitpick-exceptions +0 -0
  41. {easylink-0.1.17 → easylink-0.1.18}/docs/source/_static/style.css +0 -0
  42. {easylink-0.1.17 → easylink-0.1.18}/docs/source/_templates/layout.html +0 -0
  43. {easylink-0.1.17 → easylink-0.1.18}/docs/source/api_reference/cli.rst +0 -0
  44. {easylink-0.1.17 → easylink-0.1.18}/docs/source/api_reference/configuration.rst +0 -0
  45. {easylink-0.1.17 → easylink-0.1.18}/docs/source/api_reference/graph_components.rst +0 -0
  46. {easylink-0.1.17 → easylink-0.1.18}/docs/source/api_reference/implementation.rst +0 -0
  47. {easylink-0.1.17 → easylink-0.1.18}/docs/source/api_reference/index.rst +0 -0
  48. {easylink-0.1.17 → easylink-0.1.18}/docs/source/api_reference/pipeline.rst +0 -0
  49. {easylink-0.1.17 → easylink-0.1.18}/docs/source/api_reference/pipeline_graph.rst +0 -0
  50. {easylink-0.1.17 → easylink-0.1.18}/docs/source/api_reference/pipeline_schema.rst +0 -0
  51. {easylink-0.1.17 → easylink-0.1.18}/docs/source/api_reference/pipeline_schema_constants/development.rst +0 -0
  52. {easylink-0.1.17 → easylink-0.1.18}/docs/source/api_reference/pipeline_schema_constants/index.rst +0 -0
  53. {easylink-0.1.17 → easylink-0.1.18}/docs/source/api_reference/pipeline_schema_constants/testing.rst +0 -0
  54. {easylink-0.1.17 → easylink-0.1.18}/docs/source/api_reference/rule.rst +0 -0
  55. {easylink-0.1.17 → easylink-0.1.18}/docs/source/api_reference/runner.rst +0 -0
  56. {easylink-0.1.17 → easylink-0.1.18}/docs/source/api_reference/step.rst +0 -0
  57. {easylink-0.1.17 → easylink-0.1.18}/docs/source/api_reference/utilities/aggregator_utils.rst +0 -0
  58. {easylink-0.1.17 → easylink-0.1.18}/docs/source/api_reference/utilities/data_utils.rst +0 -0
  59. {easylink-0.1.17 → easylink-0.1.18}/docs/source/api_reference/utilities/general_utils.rst +0 -0
  60. {easylink-0.1.17 → easylink-0.1.18}/docs/source/api_reference/utilities/index.rst +0 -0
  61. {easylink-0.1.17 → easylink-0.1.18}/docs/source/api_reference/utilities/paths.rst +0 -0
  62. {easylink-0.1.17 → easylink-0.1.18}/docs/source/api_reference/utilities/splitter_utils.rst +0 -0
  63. {easylink-0.1.17 → easylink-0.1.18}/docs/source/api_reference/utilities/validation_utils.rst +0 -0
  64. {easylink-0.1.17 → easylink-0.1.18}/docs/source/concepts/index.rst +0 -0
  65. {easylink-0.1.17 → easylink-0.1.18}/docs/source/concepts/pipeline_schema/images/01_step.drawio.png +0 -0
  66. {easylink-0.1.17 → easylink-0.1.18}/docs/source/concepts/pipeline_schema/images/02_default_implementation.drawio.png +0 -0
  67. {easylink-0.1.17 → easylink-0.1.18}/docs/source/concepts/pipeline_schema/images/03_slots.drawio.png +0 -0
  68. {easylink-0.1.17 → easylink-0.1.18}/docs/source/concepts/pipeline_schema/images/04_data_dependency.drawio.png +0 -0
  69. {easylink-0.1.17 → easylink-0.1.18}/docs/source/concepts/pipeline_schema/images/05_pipeline_schema.drawio.png +0 -0
  70. {easylink-0.1.17 → easylink-0.1.18}/docs/source/concepts/pipeline_schema/images/06_default_input.drawio.png +0 -0
  71. {easylink-0.1.17 → easylink-0.1.18}/docs/source/concepts/pipeline_schema/images/07_cloneable_section.drawio.png +0 -0
  72. {easylink-0.1.17 → easylink-0.1.18}/docs/source/concepts/pipeline_schema/images/08_cloneable_section_expanded.drawio.png +0 -0
  73. {easylink-0.1.17 → easylink-0.1.18}/docs/source/concepts/pipeline_schema/images/09_loopable_section.drawio.png +0 -0
  74. {easylink-0.1.17 → easylink-0.1.18}/docs/source/concepts/pipeline_schema/images/10_loopable_section_expanded.drawio.png +0 -0
  75. {easylink-0.1.17 → easylink-0.1.18}/docs/source/concepts/pipeline_schema/images/11_cloneable_section_splitter.drawio.png +0 -0
  76. {easylink-0.1.17 → easylink-0.1.18}/docs/source/concepts/pipeline_schema/images/12_cloneable_section_splitter_expanded.drawio.png +0 -0
  77. {easylink-0.1.17 → easylink-0.1.18}/docs/source/concepts/pipeline_schema/images/13_autoparallel_section.drawio.png +0 -0
  78. {easylink-0.1.17 → easylink-0.1.18}/docs/source/concepts/pipeline_schema/images/14_choice_section.drawio.png +0 -0
  79. {easylink-0.1.17 → easylink-0.1.18}/docs/source/concepts/pipeline_schema/images/15_choice_section_expanded.drawio.png +0 -0
  80. {easylink-0.1.17 → easylink-0.1.18}/docs/source/concepts/pipeline_schema/images/16_step_hierarchy.drawio.png +0 -0
  81. {easylink-0.1.17 → easylink-0.1.18}/docs/source/concepts/pipeline_schema/images/17_draws.drawio.png +0 -0
  82. {easylink-0.1.17 → easylink-0.1.18}/docs/source/concepts/pipeline_schema/images/18_schema_to_pipeline.drawio.png +0 -0
  83. {easylink-0.1.17 → easylink-0.1.18}/docs/source/concepts/pipeline_schema/images/19_schema_to_pipeline_combined.drawio.png +0 -0
  84. {easylink-0.1.17 → easylink-0.1.18}/docs/source/concepts/pipeline_schema/images/clustering_sub_steps.drawio.png +0 -0
  85. {easylink-0.1.17 → easylink-0.1.18}/docs/source/concepts/pipeline_schema/images/easylink_pipeline_schema.drawio.png +0 -0
  86. {easylink-0.1.17 → easylink-0.1.18}/docs/source/concepts/pipeline_schema/images/entity_resolution_sub_steps.drawio.png +0 -0
  87. {easylink-0.1.17 → easylink-0.1.18}/docs/source/concepts/pipeline_schema/index.rst +0 -0
  88. {easylink-0.1.17 → easylink-0.1.18}/docs/source/conf.py +0 -0
  89. {easylink-0.1.17 → easylink-0.1.18}/docs/source/glossary.rst +0 -0
  90. {easylink-0.1.17 → easylink-0.1.18}/docs/source/index.rst +0 -0
  91. {easylink-0.1.17 → easylink-0.1.18}/docs/source/user_guide/cli.rst +0 -0
  92. {easylink-0.1.17 → easylink-0.1.18}/docs/source/user_guide/index.rst +0 -0
  93. {easylink-0.1.17 → easylink-0.1.18}/docs/source/user_guide/tutorials/DAG-common-pipeline.svg +0 -0
  94. {easylink-0.1.17 → easylink-0.1.18}/docs/source/user_guide/tutorials/DAG-e2e-pipeline-expanded.svg +0 -0
  95. {easylink-0.1.17 → easylink-0.1.18}/docs/source/user_guide/tutorials/DAG-e2e-pipeline.svg +0 -0
  96. {easylink-0.1.17 → easylink-0.1.18}/docs/source/user_guide/tutorials/DAG-r-pyspark.svg +0 -0
  97. {easylink-0.1.17 → easylink-0.1.18}/docs/source/user_guide/tutorials/environment_slurm.yaml +0 -0
  98. {easylink-0.1.17 → easylink-0.1.18}/docs/source/user_guide/tutorials/getting_started.rst +0 -0
  99. {easylink-0.1.17 → easylink-0.1.18}/docs/source/user_guide/tutorials/impl-config-pipeline.yaml +0 -0
  100. {easylink-0.1.17 → easylink-0.1.18}/docs/source/user_guide/tutorials/index.rst +0 -0
  101. {easylink-0.1.17 → easylink-0.1.18}/docs/source/user_guide/tutorials/input_data.yaml +0 -0
  102. {easylink-0.1.17 → easylink-0.1.18}/docs/source/user_guide/tutorials/input_file_1.parquet +0 -0
  103. {easylink-0.1.17 → easylink-0.1.18}/docs/source/user_guide/tutorials/input_file_2.parquet +0 -0
  104. {easylink-0.1.17 → easylink-0.1.18}/docs/source/user_guide/tutorials/input_file_3.parquet +0 -0
  105. {easylink-0.1.17 → easylink-0.1.18}/docs/source/user_guide/tutorials/r_spark_pipeline.yaml +0 -0
  106. {easylink-0.1.17 → easylink-0.1.18}/pyproject.toml +0 -0
  107. {easylink-0.1.17 → easylink-0.1.18}/python_versions.json +0 -0
  108. {easylink-0.1.17 → easylink-0.1.18}/pytype.cfg +0 -0
  109. {easylink-0.1.17 → easylink-0.1.18}/setup.cfg +0 -0
  110. {easylink-0.1.17 → easylink-0.1.18}/setup.py +0 -0
  111. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/__about__.py +0 -0
  112. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/__init__.py +0 -0
  113. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/graph_components.py +0 -0
  114. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/images/spark_cluster/Dockerfile +0 -0
  115. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/images/spark_cluster/README.md +0 -0
  116. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/implementation.py +0 -0
  117. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/pipeline.py +0 -0
  118. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/pipeline_graph.py +0 -0
  119. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/pipeline_schema_constants/development.py +0 -0
  120. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/pipeline_schema_constants/testing.py +0 -0
  121. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/rule.py +0 -0
  122. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/step.py +0 -0
  123. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/steps/dev/README.md +0 -0
  124. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/steps/dev/build-containers-local.sh +0 -0
  125. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/steps/dev/build-containers-remote.sh +0 -0
  126. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/steps/dev/input_data/create_input_files.ipynb +0 -0
  127. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/steps/dev/input_data/input_file_1.csv +0 -0
  128. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/steps/dev/input_data/input_file_1.parquet +0 -0
  129. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/steps/dev/input_data/input_file_2.csv +0 -0
  130. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/steps/dev/input_data/input_file_2.parquet +0 -0
  131. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/steps/dev/python_pandas/README.md +0 -0
  132. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/steps/dev/python_pandas/dummy_step.py +0 -0
  133. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/steps/dev/python_pandas/python_pandas.def +0 -0
  134. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/steps/dev/python_pyspark/README.md +0 -0
  135. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/steps/dev/python_pyspark/dummy_step.py +0 -0
  136. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/steps/dev/python_pyspark/python_pyspark.def +0 -0
  137. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/steps/dev/r/README.md +0 -0
  138. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/steps/dev/r/dummy_step.R +0 -0
  139. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/steps/dev/r/r-image.def +0 -0
  140. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/steps/dev/test.py +0 -0
  141. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/steps/output_dir/dummy_step_1_for_output_dir_example.def +0 -0
  142. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/steps/output_dir/dummy_step_1_for_output_dir_example.py +0 -0
  143. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/steps/output_dir/dummy_step_2_for_output_dir_example.def +0 -0
  144. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/steps/output_dir/dummy_step_2_for_output_dir_example.py +0 -0
  145. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/utilities/__init__.py +0 -0
  146. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/utilities/aggregator_utils.py +0 -0
  147. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/utilities/data_utils.py +0 -0
  148. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/utilities/general_utils.py +0 -0
  149. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/utilities/paths.py +0 -0
  150. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/utilities/spark.smk +0 -0
  151. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/utilities/splitter_utils.py +0 -0
  152. {easylink-0.1.17 → easylink-0.1.18}/src/easylink/utilities/validation_utils.py +0 -0
  153. {easylink-0.1.17 → easylink-0.1.18}/src/easylink.egg-info/SOURCES.txt +0 -0
  154. {easylink-0.1.17 → easylink-0.1.18}/src/easylink.egg-info/dependency_links.txt +0 -0
  155. {easylink-0.1.17 → easylink-0.1.18}/src/easylink.egg-info/entry_points.txt +0 -0
  156. {easylink-0.1.17 → easylink-0.1.18}/src/easylink.egg-info/not-zip-safe +0 -0
  157. {easylink-0.1.17 → easylink-0.1.18}/src/easylink.egg-info/requires.txt +0 -0
  158. {easylink-0.1.17 → easylink-0.1.18}/src/easylink.egg-info/top_level.txt +0 -0
  159. {easylink-0.1.17 → easylink-0.1.18}/tests/__init__.py +0 -0
  160. {easylink-0.1.17 → easylink-0.1.18}/tests/conftest.py +0 -0
  161. {easylink-0.1.17 → easylink-0.1.18}/tests/specifications/common/environment_local.yaml +0 -0
  162. {easylink-0.1.17 → easylink-0.1.18}/tests/specifications/common/input_data.yaml +0 -0
  163. {easylink-0.1.17 → easylink-0.1.18}/tests/specifications/common/input_data_one_file.yaml +0 -0
  164. {easylink-0.1.17 → easylink-0.1.18}/tests/specifications/common/pipeline.yaml +0 -0
  165. {easylink-0.1.17 → easylink-0.1.18}/tests/specifications/e2e/environment_slurm.yaml +0 -0
  166. {easylink-0.1.17 → easylink-0.1.18}/tests/specifications/e2e/pipeline.yaml +0 -0
  167. {easylink-0.1.17 → easylink-0.1.18}/tests/specifications/e2e/pipeline_expanded.yaml +0 -0
  168. {easylink-0.1.17 → easylink-0.1.18}/tests/specifications/integration/embarrassingly_parallel/pipeline_hierarchical_step.yaml +0 -0
  169. {easylink-0.1.17 → easylink-0.1.18}/tests/specifications/integration/embarrassingly_parallel/pipeline_loop_step.yaml +0 -0
  170. {easylink-0.1.17 → easylink-0.1.18}/tests/specifications/integration/embarrassingly_parallel/pipeline_parallel_step.yaml +0 -0
  171. {easylink-0.1.17 → easylink-0.1.18}/tests/specifications/integration/environment_spark_slurm.yaml +0 -0
  172. {easylink-0.1.17 → easylink-0.1.18}/tests/specifications/integration/pipeline.yaml +0 -0
  173. {easylink-0.1.17 → easylink-0.1.18}/tests/specifications/integration/pipeline_output_dir.yaml +0 -0
  174. {easylink-0.1.17 → easylink-0.1.18}/tests/specifications/integration/pipeline_output_dir_default.yaml +0 -0
  175. {easylink-0.1.17 → easylink-0.1.18}/tests/specifications/integration/pipeline_spark.yaml +0 -0
  176. {easylink-0.1.17 → easylink-0.1.18}/tests/specifications/unit/environment_minimum.yaml +0 -0
  177. {easylink-0.1.17 → easylink-0.1.18}/tests/specifications/unit/environment_spark_slurm.yaml +0 -0
  178. {easylink-0.1.17 → easylink-0.1.18}/tests/specifications/unit/pipeline.yaml +0 -0
  179. {easylink-0.1.17 → easylink-0.1.18}/tests/specifications/unit/pipeline_bad_combined_implementations.yaml +0 -0
  180. {easylink-0.1.17 → easylink-0.1.18}/tests/specifications/unit/pipeline_bad_implementation.yaml +0 -0
  181. {easylink-0.1.17 → easylink-0.1.18}/tests/specifications/unit/pipeline_bad_loop_formatting.yaml +0 -0
  182. {easylink-0.1.17 → easylink-0.1.18}/tests/specifications/unit/pipeline_bad_step.yaml +0 -0
  183. {easylink-0.1.17 → easylink-0.1.18}/tests/specifications/unit/pipeline_bad_type_key.yaml +0 -0
  184. {easylink-0.1.17 → easylink-0.1.18}/tests/specifications/unit/pipeline_combine_bad_implementation_names.yaml +0 -0
  185. {easylink-0.1.17 → easylink-0.1.18}/tests/specifications/unit/pipeline_combine_bad_topology.yaml +0 -0
  186. {easylink-0.1.17 → easylink-0.1.18}/tests/specifications/unit/pipeline_combine_two_steps.yaml +0 -0
  187. {easylink-0.1.17 → easylink-0.1.18}/tests/specifications/unit/pipeline_combine_with_extra_node.yaml +0 -0
  188. {easylink-0.1.17 → easylink-0.1.18}/tests/specifications/unit/pipeline_combine_with_iteration.yaml +0 -0
  189. {easylink-0.1.17 → easylink-0.1.18}/tests/specifications/unit/pipeline_combine_with_iteration_cycle.yaml +0 -0
  190. {easylink-0.1.17 → easylink-0.1.18}/tests/specifications/unit/pipeline_combine_with_missing_node.yaml +0 -0
  191. {easylink-0.1.17 → easylink-0.1.18}/tests/specifications/unit/pipeline_combine_with_parallel.yaml +0 -0
  192. {easylink-0.1.17 → easylink-0.1.18}/tests/specifications/unit/pipeline_missing_implementation_name.yaml +0 -0
  193. {easylink-0.1.17 → easylink-0.1.18}/tests/specifications/unit/pipeline_missing_implementations.yaml +0 -0
  194. {easylink-0.1.17 → easylink-0.1.18}/tests/specifications/unit/pipeline_missing_loop_nodes.yaml +0 -0
  195. {easylink-0.1.17 → easylink-0.1.18}/tests/specifications/unit/pipeline_missing_step.yaml +0 -0
  196. {easylink-0.1.17 → easylink-0.1.18}/tests/specifications/unit/pipeline_missing_substeps.yaml +0 -0
  197. {easylink-0.1.17 → easylink-0.1.18}/tests/specifications/unit/pipeline_missing_type_key.yaml +0 -0
  198. {easylink-0.1.17 → easylink-0.1.18}/tests/specifications/unit/pipeline_nested_templated_steps.yaml +0 -0
  199. {easylink-0.1.17 → easylink-0.1.18}/tests/specifications/unit/pipeline_out_of_order.yaml +0 -0
  200. {easylink-0.1.17 → easylink-0.1.18}/tests/specifications/unit/pipeline_spark.yaml +0 -0
  201. {easylink-0.1.17 → easylink-0.1.18}/tests/specifications/unit/pipeline_type_config_mismatch.yaml +0 -0
  202. {easylink-0.1.17 → easylink-0.1.18}/tests/specifications/unit/pipeline_wrong_parallel_split_keys.yaml +0 -0
  203. {easylink-0.1.17 → easylink-0.1.18}/tests/unit/__init__.py +0 -0
  204. {easylink-0.1.17 → easylink-0.1.18}/tests/unit/recipe_strings/python_pandas.txt +0 -0
  205. {easylink-0.1.17 → easylink-0.1.18}/tests/unit/rule_strings/aggregation_rule.txt +0 -0
  206. {easylink-0.1.17 → easylink-0.1.18}/tests/unit/rule_strings/checkpoint_rule.txt +0 -0
  207. {easylink-0.1.17 → easylink-0.1.18}/tests/unit/rule_strings/embarrassingly_parallel_rule.txt +0 -0
  208. {easylink-0.1.17 → easylink-0.1.18}/tests/unit/rule_strings/implemented_rule_local.txt +0 -0
  209. {easylink-0.1.17 → easylink-0.1.18}/tests/unit/rule_strings/implemented_rule_slurm.txt +0 -0
  210. {easylink-0.1.17 → easylink-0.1.18}/tests/unit/rule_strings/pipeline_local.txt +0 -0
  211. {easylink-0.1.17 → easylink-0.1.18}/tests/unit/rule_strings/pipeline_slurm.txt +0 -0
  212. {easylink-0.1.17 → easylink-0.1.18}/tests/unit/rule_strings/target_rule.txt +0 -0
  213. {easylink-0.1.17 → easylink-0.1.18}/tests/unit/rule_strings/validation_rule.txt +0 -0
  214. {easylink-0.1.17 → easylink-0.1.18}/tests/unit/test_cli.py +0 -0
  215. {easylink-0.1.17 → easylink-0.1.18}/tests/unit/test_data_utils.py +0 -0
  216. {easylink-0.1.17 → easylink-0.1.18}/tests/unit/test_general_utils.py +0 -0
  217. {easylink-0.1.17 → easylink-0.1.18}/tests/unit/test_graph_components.py +0 -0
  218. {easylink-0.1.17 → easylink-0.1.18}/tests/unit/test_implementation.py +0 -0
  219. {easylink-0.1.17 → easylink-0.1.18}/tests/unit/test_rule.py +0 -0
  220. {easylink-0.1.17 → easylink-0.1.18}/tests/unit/test_step.py +0 -0
  221. {easylink-0.1.17 → easylink-0.1.18}/update_readme.py +0 -0
@@ -1,3 +1,7 @@
1
+ **0.1.18 - 5/14/25**
2
+
3
+ - Refactor to use a single pipeline schema rather than multiple potential schemas
4
+
1
5
  **0.1.17 - 5/14/25**
2
6
 
3
7
  - Support directories as step intermediates
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: easylink
3
- Version: 0.1.17
3
+ Version: 0.1.18
4
4
  Summary: Research repository for the EasyLink ER ecosystem project.
5
5
  Home-page: https://github.com/ihmeuw/easylink
6
6
  Author: The EasyLink developers
@@ -0,0 +1 @@
1
+ __version__ = "0.1.18"
@@ -91,6 +91,11 @@ SHARED_OPTIONS = [
91
91
  default=False,
92
92
  help="Do not save the results in a timestamped sub-directory of ``--output-dir``.",
93
93
  ),
94
+ click.option(
95
+ "--schema",
96
+ hidden=True,
97
+ default="main",
98
+ ),
94
99
  ]
95
100
 
96
101
  VERBOSE_WITH_DEBUGGER_OPTIONS = [
@@ -165,6 +170,7 @@ def run(
165
170
  input_data: str,
166
171
  output_dir: str | None,
167
172
  no_timestamp: bool,
173
+ schema: str,
168
174
  computing_environment: str | None,
169
175
  verbose: int,
170
176
  with_debugger: bool,
@@ -190,6 +196,7 @@ def run(
190
196
  input_data=input_data,
191
197
  computing_environment=computing_environment,
192
198
  results_dir=results_dir,
199
+ schema_name=schema,
193
200
  )
194
201
  logger.info("*** FINISHED ***")
195
202
 
@@ -201,6 +208,7 @@ def generate_dag(
201
208
  input_data: str,
202
209
  output_dir: str | None,
203
210
  no_timestamp: bool,
211
+ schema: str,
204
212
  verbose: int,
205
213
  with_debugger: bool,
206
214
  ) -> None:
@@ -223,6 +231,7 @@ def generate_dag(
223
231
  input_data=input_data,
224
232
  computing_environment=None,
225
233
  results_dir=results_dir,
234
+ schema_name=schema,
226
235
  )
227
236
  logger.info("*** DAG saved to result directory ***")
228
237
 
@@ -14,7 +14,7 @@ from typing import Any
14
14
 
15
15
  from layered_config_tree import LayeredConfigTree
16
16
 
17
- from easylink.pipeline_schema import PIPELINE_SCHEMAS, PipelineSchema
17
+ from easylink.pipeline_schema import PipelineSchema
18
18
  from easylink.utilities.data_utils import load_yaml
19
19
  from easylink.utilities.general_utils import exit_with_validation_error
20
20
 
@@ -67,9 +67,8 @@ class Config(LayeredConfigTree):
67
67
  A dictionary of all specifications required to run the pipeline. This
68
68
  includes the pipeline, input data, and computing environment specifications,
69
69
  as well as the results directory.
70
- potential_schemas
71
- A list of potential schemas to validate the pipeline configuration against.
72
- This is primarily used for testing purposes. Defaults to the supported schemas.
70
+ schema_name
71
+ The name of the schema to validate the pipeline configuration against.
73
72
 
74
73
  Attributes
75
74
  ----------
@@ -82,22 +81,14 @@ class Config(LayeredConfigTree):
82
81
  input_data
83
82
  The input data filepaths.
84
83
  schema
85
- The :class:`~easylink.pipeline_schema.PipelineSchema` that successfully
86
- validated the requested pipeline.
87
-
88
- Notes
89
- -----
90
- The requested pipeline is checked against a set of supported
91
- ``PipelineSchemas``. The first schema that successfully validates is assumed
92
- to be the correct one and is attached to the ``Config`` object and its
93
- :meth:`~easylink.pipeline_schema.PipelineSchema.configure_pipeline`
94
- method is called.
84
+ The :class:`~easylink.pipeline_schema.PipelineSchema`.
85
+
95
86
  """
96
87
 
97
88
  def __init__(
98
89
  self,
99
90
  config_params: dict[str, Any],
100
- potential_schemas: PipelineSchema | list[PipelineSchema] = PIPELINE_SCHEMAS,
91
+ schema_name: str = "main",
101
92
  ) -> None:
102
93
  super().__init__(layers=["initial_data", "default", "user_configured"])
103
94
  self.update(DEFAULT_ENVIRONMENT, layer="default")
@@ -108,9 +99,7 @@ class Config(LayeredConfigTree):
108
99
  # Set slurm defaults to empty dict instead of None so that we don't get errors
109
100
  # in slurm_resources property
110
101
  self.update({"environment": {"slurm": {}}}, layer="default")
111
- if not isinstance(potential_schemas, list):
112
- potential_schemas = [potential_schemas]
113
- self.update({"schema": self._get_schema(potential_schemas)}, layer="initial_data")
102
+ self.update({"schema": self._get_schema(schema_name)}, layer="initial_data")
114
103
  self.schema.configure_pipeline(self.pipeline, self.input_data)
115
104
  self._validate()
116
105
  self.freeze()
@@ -173,22 +162,22 @@ class Config(LayeredConfigTree):
173
162
  # Setup Methods #
174
163
  #################
175
164
 
176
- def _get_schema(self, potential_schemas: list[PipelineSchema]) -> PipelineSchema:
165
+ def _get_schema(self, schema_name: str = "main") -> PipelineSchema:
177
166
  """Returns the first :class:`~easylink.pipeline_schema.PipelineSchema` that validates the requested pipeline.
178
167
 
179
168
  Parameters
180
169
  ----------
181
- potential_schemas
182
- ``PipelineSchemas`` to validate the pipeline configuration against.
170
+ schema_name
171
+ The name of the specific ``PipelineSchema`` to validate the pipeline configuration against.
183
172
 
184
173
  Returns
185
174
  -------
186
- The first ``PipelineSchema`` that validates the requested pipeline configuration.
175
+ The requested ``PipelineSchema`` if it validates the requested pipeline configuration.
187
176
 
188
177
  Raises
189
178
  ------
190
179
  SystemExit
191
- If the pipeline configuration is not valid for any of the ``potential_schemas``,
180
+ If the pipeline configuration is not valid for the requested schema,
192
181
  the program exits with a non-zero code and all validation errors found
193
182
  are logged.
194
183
 
@@ -197,20 +186,15 @@ class Config(LayeredConfigTree):
197
186
  This acts as the pipeline configuration file's validation method since
198
187
  we can only find a matching ``PipelineSchema`` if that file is valid.
199
188
 
200
- This method returns the *first* ``PipelineSchema`` that validates and does
201
- not attempt to check additional ones.
202
189
  """
203
190
  errors = defaultdict(dict)
204
191
  # Try each schema until one is validated
205
- for schema in potential_schemas:
206
- logs = schema.validate_step(self.pipeline, self.input_data)
207
- if logs:
208
- errors[PIPELINE_ERRORS_KEY][schema.name] = logs
209
- pass # try the next schema
210
- else: # schema was validated
211
- return schema
212
- # No schemas were validated
213
- exit_with_validation_error(dict(errors))
192
+ schema = PipelineSchema.get_schema(schema_name)
193
+ logs = schema.validate_step(self.pipeline, self.input_data)
194
+ if logs:
195
+ errors[PIPELINE_ERRORS_KEY][schema.name] = logs
196
+ exit_with_validation_error(dict(errors))
197
+ return schema
214
198
 
215
199
  def _validate(self) -> None:
216
200
  """Validates the ``Config``.
@@ -19,7 +19,7 @@ from typing import cast
19
19
  import yaml
20
20
  from loguru import logger
21
21
 
22
- from easylink.pipeline_schema_constants import ALLOWED_SCHEMA_PARAMS
22
+ from easylink.pipeline_schema_constants import SCHEMA_PARAMS
23
23
  from easylink.step import (
24
24
  ChoiceStep,
25
25
  EmbarrassinglyParallelStep,
@@ -244,17 +244,17 @@ class ImplementationCreator:
244
244
  @staticmethod
245
245
  def _extract_output_slot(script_path: Path, step_name: str) -> str:
246
246
  """Extracts the name of the output slot that this script is implementing."""
247
- schema = ImplementationCreator._extract_pipeline_schema(script_path)
248
- implementable_steps = ImplementationCreator._extract_implementable_steps(schema)
247
+ schema_name = ImplementationCreator._extract_pipeline_schema_name(script_path)
248
+ implementable_steps = ImplementationCreator._extract_implementable_steps(schema_name)
249
249
  step_names = [step.name for step in implementable_steps]
250
250
  if step_name not in step_names:
251
251
  raise ValueError(
252
- f"'{step_name}' does not exist as an implementable step in the '{schema}' pipeline schema. "
252
+ f"'{step_name}' does not exist as an implementable step in the '{schema_name}' pipeline schema. "
253
253
  )
254
254
  duplicates = list(set([step for step in step_names if step_names.count(step) > 1]))
255
255
  if duplicates:
256
256
  raise ValueError(
257
- f"Multiple implementable steps with the same name found in the '{schema}' "
257
+ f"Multiple implementable steps with the same name found in the '{schema_name}' "
258
258
  f"pipeline schema: {duplicates}."
259
259
  )
260
260
  implemented_step = [step for step in implementable_steps if step.name == step_name][0]
@@ -266,7 +266,7 @@ class ImplementationCreator:
266
266
  return list(implemented_step.output_slots)[0]
267
267
 
268
268
  @staticmethod
269
- def _extract_implementable_steps(schema: str) -> list[Step]:
269
+ def _extract_implementable_steps(schema_name: str) -> list[Step]:
270
270
  """Extracts all implementable steps from the pipeline schema.
271
271
 
272
272
  This method recursively traverses the pipeline schema specified in the script
@@ -296,8 +296,7 @@ class ImplementationCreator:
296
296
  implementable_steps.append(node)
297
297
  return
298
298
 
299
- schema_steps = ALLOWED_SCHEMA_PARAMS[schema][0]
300
-
299
+ schema_steps, _edges = SCHEMA_PARAMS[schema_name]
301
300
  implementable_steps: list[Step] = []
302
301
  for schema_step in schema_steps:
303
302
  _process_step(schema_step)
@@ -305,7 +304,7 @@ class ImplementationCreator:
305
304
  return implementable_steps
306
305
 
307
306
  @staticmethod
308
- def _extract_pipeline_schema(script_path: Path) -> str:
307
+ def _extract_pipeline_schema_name(script_path: Path) -> str:
309
308
  """Extracts the relevant pipeline schema name.
310
309
 
311
310
  The expectation is that the output slot's name is specified within the script
@@ -316,8 +315,11 @@ class ImplementationCreator:
316
315
 
317
316
  If no pipeline schema is specified, "main" will be used by default.
318
317
  """
319
- schema = _extract_metadata("PIPELINE_SCHEMA", script_path)
320
- return "main" if len(schema) == 0 else schema[0]
318
+ schema_name_list: list[str] = _extract_metadata("PIPELINE_SCHEMA", script_path)
319
+ schema_name = "main" if len(schema_name_list) == 0 else schema_name_list[0]
320
+ if schema_name not in SCHEMA_PARAMS:
321
+ raise ValueError(f"Pipeline schema '{schema_name}' is not supported.")
322
+ return schema_name
321
323
 
322
324
  @staticmethod
323
325
  def _write_metadata(info: dict[str, dict[str, str]]) -> None:
@@ -204,9 +204,6 @@ dummy_step_1_for_output_dir_example_default:
204
204
  - step_1_for_output_dir_example
205
205
  image_path: /mnt/team/simulation_science/priv/engineering/er_ecosystem/images/zmbc/dummy_step_1_for_output_dir_example.sif
206
206
  script_cmd: python /dummy_step_1_for_output_dir_example.py
207
- # leave outputs out for testing purposes
208
- # outputs:
209
- # step_1_main_output_directory: output_dir/
210
207
  dummy_step_2_for_output_dir_example:
211
208
  steps:
212
209
  - step_2_for_output_dir_example
@@ -14,7 +14,7 @@ from pathlib import Path
14
14
  from layered_config_tree import LayeredConfigTree
15
15
 
16
16
  from easylink.graph_components import EdgeParams, ImplementationGraph
17
- from easylink.pipeline_schema_constants import ALLOWED_SCHEMA_PARAMS
17
+ from easylink.pipeline_schema_constants import SCHEMA_PARAMS
18
18
  from easylink.step import HierarchicalStep, NonLeafConfigurationState, Step
19
19
 
20
20
 
@@ -39,7 +39,7 @@ class PipelineSchema(HierarchicalStep):
39
39
 
40
40
  Notes
41
41
  -----
42
- All ``PipelineSchema`` instances are intended to be created by the :meth:`_get_schemas`
42
+ A ``PipelineSchema`` is intended to be constructed by the :meth:`get_schema`
43
43
  class method.
44
44
 
45
45
  The ``PipelineSchema`` is a high-level abstraction; it represents the desired
@@ -159,22 +159,21 @@ class PipelineSchema(HierarchicalStep):
159
159
  )
160
160
 
161
161
  @classmethod
162
- def _get_schemas(cls) -> list["PipelineSchema"]:
162
+ def get_schema(cls, name: str = "main") -> list["PipelineSchema"]:
163
163
  """Gets all allowable ``PipelineSchemas``.
164
164
 
165
165
  These ``PipelineSchemas`` represent the fully supported pipelines and are
166
166
  used to validate the user-requested pipeline.
167
167
 
168
+ Parameters
169
+ ----------
170
+ name
171
+ The name of the ``PipelineSchema`` to get.
172
+
168
173
  Returns
169
174
  -------
170
- All allowable ``PipelineSchemas``.
175
+ The requested ``PipelineSchema``.
171
176
  """
172
- return [
173
- cls(name, nodes=nodes, edges=edges)
174
- for name, (nodes, edges) in ALLOWED_SCHEMA_PARAMS.items()
175
- ]
176
-
177
-
178
- PIPELINE_SCHEMAS = PipelineSchema._get_schemas()
179
- """All allowable :class:`PipelineSchemas<PipelineSchema>` to validate the requested
180
- pipeline against."""
177
+ if name not in SCHEMA_PARAMS:
178
+ raise ValueError(f"Pipeline schema '{name}' is not supported.")
179
+ return cls(name, *SCHEMA_PARAMS[name])
@@ -11,11 +11,10 @@ package defines the nodes and edges required to instantiate such ``PipelineSchem
11
11
 
12
12
  from easylink.pipeline_schema_constants import development, testing
13
13
 
14
- ALLOWED_SCHEMA_PARAMS = {
14
+ SCHEMA_PARAMS = {
15
+ "main": "TODO",
16
+ # development and testing
15
17
  "development": development.SCHEMA_PARAMS,
16
- }
17
-
18
- TESTING_SCHEMA_PARAMS = {
19
18
  "integration": testing.SCHEMA_PARAMS_ONE_STEP,
20
19
  "output_dir": testing.SCHEMA_PARAMS_OUTPUT_DIR,
21
20
  "combine_bad_topology": testing.SCHEMA_PARAMS_BAD_COMBINED_TOPOLOGY,
@@ -19,7 +19,6 @@ from snakemake.cli import main as snake_main
19
19
 
20
20
  from easylink.configuration import Config, load_params_from_specification
21
21
  from easylink.pipeline import Pipeline
22
- from easylink.pipeline_schema import PIPELINE_SCHEMAS, PipelineSchema
23
22
  from easylink.utilities.data_utils import (
24
23
  copy_configuration_files_to_results_directory,
25
24
  create_results_directory,
@@ -35,8 +34,8 @@ def main(
35
34
  input_data: str | Path,
36
35
  computing_environment: str | Path | None,
37
36
  results_dir: str | Path,
38
- debug=False,
39
- potential_schemas: PipelineSchema | list[PipelineSchema] = PIPELINE_SCHEMAS,
37
+ schema_name: str = "main",
38
+ debug: bool = False,
40
39
  ) -> None:
41
40
  """Runs an EasyLink command.
42
41
 
@@ -60,17 +59,16 @@ def main(
60
59
  to run the pipeline on. If None, the pipeline will be run locally.
61
60
  results_dir
62
61
  The directory to write results and incidental files (logs, etc.) to.
62
+ schema_name
63
+ The name of the schema to validate the pipeline configuration against.
63
64
  debug
64
65
  If False (the default), will suppress some of the workflow output. This
65
66
  is intended to only be used for testing and development purposes.
66
- potential_schemas
67
- A list of potential schemas to validate the pipeline configuration against.
68
- This is primarily used for testing purposes. Defaults to the supported schemas.
69
67
  """
70
68
  config_params = load_params_from_specification(
71
69
  pipeline_specification, input_data, computing_environment, results_dir
72
70
  )
73
- config = Config(config_params, potential_schemas)
71
+ config = Config(config_params, schema_name)
74
72
  pipeline = Pipeline(config)
75
73
  # After validation is completed, create the results directory
76
74
  create_results_directory(Path(results_dir))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: easylink
3
- Version: 0.1.17
3
+ Version: 0.1.18
4
4
  Summary: Research repository for the EasyLink ER ecosystem project.
5
5
  Home-page: https://github.com/ihmeuw/easylink
6
6
  Author: The EasyLink developers
@@ -63,7 +63,8 @@ def test_easylink_run(
63
63
  f"-i {SPECIFICATIONS_DIR / input_data} "
64
64
  f"-e {SPECIFICATIONS_DIR / computing_environment} "
65
65
  f"-o {str(test_specific_results_dir)} "
66
- "--no-timestamp"
66
+ "--no-timestamp "
67
+ "--schema development "
67
68
  )
68
69
  subprocess.run(
69
70
  cmd,
@@ -57,7 +57,8 @@ def test_step_types(
57
57
  f"-i {SPECIFICATIONS_DIR / input_data} "
58
58
  f"-e {SPECIFICATIONS_DIR / computing_environment} "
59
59
  f"-o {str(test_specific_results_dir)} "
60
- "--no-timestamp"
60
+ "--no-timestamp "
61
+ "--schema development "
61
62
  )
62
63
  subprocess.run(
63
64
  cmd,
@@ -6,7 +6,7 @@ import pyarrow.parquet as pq
6
6
  import pytest
7
7
 
8
8
  from easylink.pipeline_schema import PipelineSchema
9
- from easylink.pipeline_schema_constants import TESTING_SCHEMA_PARAMS
9
+ from easylink.pipeline_schema_constants import SCHEMA_PARAMS
10
10
  from easylink.runner import main
11
11
  from easylink.utilities.data_utils import load_yaml
12
12
  from tests.conftest import SPECIFICATIONS_DIR
@@ -20,11 +20,8 @@ def test_looping_embarrassingly_parallel_step(test_specific_results_dir: Path) -
20
20
  pipeline_specification = EP_SPECIFICATIONS_DIR / "pipeline_loop_step.yaml"
21
21
  input_data = COMMON_SPECIFICATIONS_DIR / "input_data.yaml"
22
22
 
23
- # Load the schema to test against
24
- schema = PipelineSchema("looping_ep_step", *TESTING_SCHEMA_PARAMS["looping_ep_step"])
25
-
26
23
  _run_pipeline_and_confirm_finished(
27
- schema, test_specific_results_dir, pipeline_specification, input_data
24
+ "looping_ep_step", test_specific_results_dir, pipeline_specification, input_data
28
25
  )
29
26
 
30
27
  intermediate_results_dir = test_specific_results_dir / "intermediate"
@@ -137,11 +134,8 @@ def test_embarrassingly_parallel_sections(
137
134
  pipeline_specification = EP_SPECIFICATIONS_DIR / pipeline_spec
138
135
  input_data = COMMON_SPECIFICATIONS_DIR / "input_data.yaml"
139
136
 
140
- # Load the schema to test against
141
- schema = PipelineSchema(schema_name, *TESTING_SCHEMA_PARAMS[schema_name])
142
-
143
137
  _run_pipeline_and_confirm_finished(
144
- schema, test_specific_results_dir, pipeline_specification, input_data
138
+ schema_name, test_specific_results_dir, pipeline_specification, input_data
145
139
  )
146
140
 
147
141
  intermediate_results_dir = test_specific_results_dir / "intermediate"
@@ -185,7 +179,7 @@ def test_embarrassingly_parallel_sections(
185
179
 
186
180
 
187
181
  def _run_pipeline_and_confirm_finished(
188
- schema: PipelineSchema,
182
+ schema_name: str,
189
183
  results_dir: Path,
190
184
  pipeline_specification: Path,
191
185
  input_data: Path,
@@ -199,7 +193,7 @@ def _run_pipeline_and_confirm_finished(
199
193
  input_data=input_data,
200
194
  computing_environment=computing_environment,
201
195
  results_dir=results_dir,
202
- potential_schemas=schema,
196
+ schema_name=schema_name,
203
197
  )
204
198
  assert pytest_wrapped_e.value.code == 0
205
199
 
@@ -2,7 +2,7 @@
2
2
  import pytest
3
3
 
4
4
  from easylink.pipeline_schema import PipelineSchema
5
- from easylink.pipeline_schema_constants import TESTING_SCHEMA_PARAMS
5
+ from easylink.pipeline_schema_constants import SCHEMA_PARAMS
6
6
  from easylink.runner import main
7
7
  from tests.conftest import SPECIFICATIONS_DIR
8
8
 
@@ -10,8 +10,7 @@ from tests.conftest import SPECIFICATIONS_DIR
10
10
  @pytest.mark.slow
11
11
  def test_missing_results(test_specific_results_dir, mocker, caplog):
12
12
  """Test that the pipeline fails when a step is missing output files."""
13
- nodes, edges = TESTING_SCHEMA_PARAMS["integration"]
14
- mocker.patch("easylink.pipeline_schema.ALLOWED_SCHEMA_PARAMS", TESTING_SCHEMA_PARAMS)
13
+ nodes, edges = SCHEMA_PARAMS["integration"]
15
14
  mocker.patch(
16
15
  "easylink.configuration.Config._get_schema",
17
16
  return_value=PipelineSchema("integration", nodes=nodes, edges=edges),
@@ -39,8 +38,7 @@ def test_missing_results(test_specific_results_dir, mocker, caplog):
39
38
  @pytest.mark.parametrize("outputs_specified", [True, False])
40
39
  def test_outputting_a_directory(outputs_specified: bool, test_specific_results_dir, mocker):
41
40
  """Test that the pipeline fails when a step is missing output files."""
42
- nodes, edges = TESTING_SCHEMA_PARAMS["output_dir"]
43
- mocker.patch("easylink.pipeline_schema.ALLOWED_SCHEMA_PARAMS", TESTING_SCHEMA_PARAMS)
41
+ nodes, edges = SCHEMA_PARAMS["output_dir"]
44
42
  mocker.patch(
45
43
  "easylink.configuration.Config._get_schema",
46
44
  return_value=PipelineSchema("output_dir", nodes=nodes, edges=edges),
@@ -6,7 +6,7 @@ import pytest
6
6
  from pytest_mock import MockerFixture
7
7
 
8
8
  from easylink.pipeline_schema import PipelineSchema
9
- from easylink.pipeline_schema_constants import TESTING_SCHEMA_PARAMS
9
+ from easylink.pipeline_schema_constants import SCHEMA_PARAMS
10
10
  from easylink.runner import main
11
11
  from easylink.utilities.general_utils import is_on_slurm
12
12
  from tests.conftest import SPECIFICATIONS_DIR
@@ -21,8 +21,7 @@ def test_slurm(
21
21
  test_specific_results_dir: Path, mocker: MockerFixture, caplog: pytest.LogCaptureFixture
22
22
  ) -> None:
23
23
  """Test that the pipeline runs on SLURM with appropriate resources."""
24
- nodes, edges = TESTING_SCHEMA_PARAMS["integration"]
25
- mocker.patch("easylink.pipeline_schema.ALLOWED_SCHEMA_PARAMS", TESTING_SCHEMA_PARAMS)
24
+ nodes, edges = SCHEMA_PARAMS["integration"]
26
25
  mocker.patch(
27
26
  "easylink.configuration.Config._get_schema",
28
27
  return_value=PipelineSchema("integration", nodes=nodes, edges=edges),
@@ -6,7 +6,7 @@ import pytest
6
6
  import yaml
7
7
 
8
8
  from easylink.pipeline_schema import PipelineSchema
9
- from easylink.pipeline_schema_constants import TESTING_SCHEMA_PARAMS
9
+ from easylink.pipeline_schema_constants import SCHEMA_PARAMS
10
10
  from easylink.runner import main
11
11
  from easylink.utilities.general_utils import is_on_slurm
12
12
  from tests.conftest import SPECIFICATIONS_DIR
@@ -19,8 +19,7 @@ from tests.conftest import SPECIFICATIONS_DIR
19
19
  )
20
20
  def test_spark_slurm(test_specific_results_dir, mocker, caplog):
21
21
  """Test that the pipeline runs spark on SLURM with appropriate resources."""
22
- nodes, edges = TESTING_SCHEMA_PARAMS["integration"]
23
- mocker.patch("easylink.pipeline_schema.ALLOWED_SCHEMA_PARAMS", TESTING_SCHEMA_PARAMS)
22
+ nodes, edges = SCHEMA_PARAMS["integration"]
24
23
  mocker.patch(
25
24
  "easylink.configuration.Config._get_schema",
26
25
  return_value=PipelineSchema("integration", nodes=nodes, edges=edges),
@@ -155,4 +155,4 @@ def default_config_params(default_config_paths) -> dict[str, Path]:
155
155
  @pytest.fixture()
156
156
  def default_config(default_config_params) -> Config:
157
157
  """A good/known Config object"""
158
- return Config(default_config_params)
158
+ return Config(default_config_params, schema_name="development")
@@ -12,12 +12,28 @@ from easylink.configuration import (
12
12
  _load_computing_environment,
13
13
  _load_input_data_paths,
14
14
  )
15
- from easylink.pipeline_schema import PIPELINE_SCHEMAS
15
+ from easylink.pipeline_schema import PipelineSchema
16
+ from easylink.step import NonLeafConfigurationState
16
17
 
17
18
 
18
19
  def test__get_schema(default_config: Config) -> None:
19
20
  """Test default config gets "development schema", without errors"""
20
- assert default_config.schema == PIPELINE_SCHEMAS[0]
21
+ # We cannot assert equality of the config's schema object and a different instance
22
+ # from PipelineSchema.get_schema("development"), so instead just check that
23
+ # some of the attrs are the same.
24
+ schema = default_config.schema
25
+ assert isinstance(schema, PipelineSchema)
26
+ assert schema.name == schema.step_name == "development"
27
+ assert schema.config_key == "substeps"
28
+ assert isinstance(schema.configuration_state, NonLeafConfigurationState)
29
+ assert [node.name for node in schema.nodes] == [
30
+ "input_data",
31
+ "step_1",
32
+ "step_2",
33
+ "step_3",
34
+ "choice_section",
35
+ "results",
36
+ ]
21
37
 
22
38
 
23
39
  def test_load_params_from_specification(
@@ -121,7 +137,7 @@ def test_required_attributes(mocker, default_config_params, key, value):
121
137
  if value:
122
138
  config_params["environment"][key] = value
123
139
  env_dict = {key: value} if value else {}
124
- retrieved = Config(config_params).environment[key]
140
+ retrieved = Config(config_params, "development").environment[key]
125
141
  expected = DEFAULT_ENVIRONMENT["environment"].copy()
126
142
  expected.update(env_dict)
127
143
  assert retrieved == expected[key]
@@ -143,7 +159,7 @@ def test_implementation_resource_requests(default_config_params, resource_reques
143
159
  config_params = default_config_params
144
160
  if resource_request:
145
161
  config_params["environment"][key] = resource_request
146
- config = Config(config_params)
162
+ config = Config(config_params, "development")
147
163
  env_dict = {key: resource_request.copy()} if resource_request else {}
148
164
  retrieved = config.environment[key].to_dict()
149
165
  expected = DEFAULT_ENVIRONMENT["environment"][key].copy()
@@ -191,7 +207,7 @@ def test_spark_requests(default_config_params, spark_request, requires_spark):
191
207
 
192
208
  if spark_request:
193
209
  config_params["environment"][key] = spark_request
194
- retrieved = Config(config_params).environment[key].to_dict()
210
+ retrieved = Config(config_params, "development").environment[key].to_dict()
195
211
  expected_env_dict = {key: spark_request.copy()} if spark_request else {}
196
212
  expected = LayeredConfigTree(SPARK_DEFAULTS, layers=["initial_data", "user"])
197
213
  if spark_request:
@@ -206,6 +222,8 @@ def test_combined_implementations(default_config_params, is_default):
206
222
  config_params = default_config_params
207
223
  if not is_default:
208
224
  config_params["pipeline"]["combined_implementations"] = combined_dict
209
- combined_implementations = Config(config_params).pipeline.combined_implementations
225
+ combined_implementations = Config(
226
+ config_params, "development"
227
+ ).pipeline.combined_implementations
210
228
  expected = {} if is_default else combined_dict
211
229
  assert combined_implementations.to_dict() == expected
@@ -30,7 +30,6 @@ MULTIPLE_METADATA = """
30
30
  # STEP_NAME: step_1
31
31
  # REQUIREMENTS: pandas==2.1.2 pyarrow pyyaml"""
32
32
 
33
-
34
33
  MULTIPLE_STEPS_METADATA = """
35
34
  # STEP_NAME: step_1, step_2
36
35
  # REQUIREMENTS: pandas==2.1.2 pyarrow pyyaml"""
@@ -89,11 +88,22 @@ def test__extract_requirements_raises(tmp_path: Path) -> None:
89
88
  (MISSING_METADATA, "main"),
90
89
  ],
91
90
  )
92
- def test__extract_pipeline_schema(script_content: str, expected: str, tmp_path: Path) -> None:
91
+ def test__extract_pipeline_schema_name(
92
+ script_content: str, expected: str, tmp_path: Path
93
+ ) -> None:
93
94
  script_path = tmp_path / "foo_step.py"
94
95
  with open(script_path, "w") as file:
95
96
  file.write(script_content)
96
- assert ImplementationCreator._extract_pipeline_schema(script_path) == expected
97
+ assert ImplementationCreator._extract_pipeline_schema_name(script_path) == expected
98
+
99
+
100
+ def test__extract_pipeline_schema_name_raises(tmp_path: Path) -> None:
101
+ script_path = tmp_path / "foo_step.py"
102
+ metadata_str = GOOD_METADATA.replace("development", "some-non-existing-schema")
103
+ with open(script_path, "w") as file:
104
+ file.write(metadata_str)
105
+ with pytest.raises(ValueError, match="is not supported"):
106
+ ImplementationCreator._extract_pipeline_schema_name(script_path)
97
107
 
98
108
 
99
109
  def test__extract_implementable_steps(tmp_path: Path) -> None:
@@ -27,7 +27,7 @@ def test_build_snakefile(
27
27
  config_paths["computing_environment"] = f"{test_dir}/spark_environment.yaml"
28
28
 
29
29
  config_params = load_params_from_specification(**config_paths)
30
- config = Config(config_params)
30
+ config = Config(config_params, "development")
31
31
  mocker.patch("easylink.implementation.Implementation.validate", return_value={})
32
32
  pipeline = Pipeline(config)
33
33
  create_results_directory(results_dir)