easylink 0.1.21__tar.gz → 0.1.22__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.
- {easylink-0.1.21 → easylink-0.1.22}/CHANGELOG.rst +4 -0
- {easylink-0.1.21 → easylink-0.1.22}/PKG-INFO +1 -1
- easylink-0.1.22/src/easylink/_version.py +1 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/configuration.py +4 -3
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/pipeline_schema.py +3 -3
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/pipeline_schema_constants/__init__.py +1 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/pipeline_schema_constants/testing.py +123 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/step.py +45 -13
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink.egg-info/PKG-INFO +1 -1
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink.egg-info/SOURCES.txt +1 -2
- easylink-0.1.22/tests/specifications/unit/pipeline_default_implementations.yaml +24 -0
- easylink-0.1.22/tests/unit/test_pipeline_schema.py +338 -0
- easylink-0.1.21/src/easylink/_version.py +0 -1
- easylink-0.1.21/src/easylink/images/spark_cluster/Dockerfile +0 -16
- easylink-0.1.21/src/easylink/images/spark_cluster/README.md +0 -15
- easylink-0.1.21/tests/unit/test_pipeline_schema.py +0 -182
- {easylink-0.1.21 → easylink-0.1.22}/.bandit +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/.flake8 +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/.github/CODEOWNERS +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/.github/pull_request_template.md +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/.github/workflows/deploy.yml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/.github/workflows/update_readme.yml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/.gitignore +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/.readthedocs.yml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/CONTRIBUTING.rst +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/Jenkinsfile +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/LICENSE +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/Makefile +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/README.rst +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/Makefile +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/nitpick-exceptions +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/_static/style.css +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/_templates/layout.html +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/api_reference/cli.rst +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/api_reference/configuration.rst +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/api_reference/graph_components.rst +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/api_reference/implementation.rst +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/api_reference/index.rst +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/api_reference/pipeline.rst +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/api_reference/pipeline_graph.rst +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/api_reference/pipeline_schema.rst +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/api_reference/pipeline_schema_constants/development.rst +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/api_reference/pipeline_schema_constants/index.rst +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/api_reference/pipeline_schema_constants/testing.rst +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/api_reference/rule.rst +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/api_reference/runner.rst +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/api_reference/step.rst +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/api_reference/utilities/aggregator_utils.rst +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/api_reference/utilities/data_utils.rst +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/api_reference/utilities/general_utils.rst +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/api_reference/utilities/index.rst +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/api_reference/utilities/paths.rst +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/api_reference/utilities/splitter_utils.rst +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/api_reference/utilities/validation_utils.rst +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/concepts/index.rst +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/concepts/pipeline_schema/images/01_step.drawio.png +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/concepts/pipeline_schema/images/02_default_implementation.drawio.png +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/concepts/pipeline_schema/images/03_slots.drawio.png +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/concepts/pipeline_schema/images/04_data_dependency.drawio.png +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/concepts/pipeline_schema/images/05_pipeline_schema.drawio.png +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/concepts/pipeline_schema/images/06_default_input.drawio.png +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/concepts/pipeline_schema/images/07_cloneable_section.drawio.png +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/concepts/pipeline_schema/images/08_cloneable_section_expanded.drawio.png +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/concepts/pipeline_schema/images/09_loopable_section.drawio.png +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/concepts/pipeline_schema/images/10_loopable_section_expanded.drawio.png +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/concepts/pipeline_schema/images/11_cloneable_section_splitter.drawio.png +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/concepts/pipeline_schema/images/12_cloneable_section_splitter_expanded.drawio.png +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/concepts/pipeline_schema/images/13_autoparallel_section.drawio.png +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/concepts/pipeline_schema/images/14_choice_section.drawio.png +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/concepts/pipeline_schema/images/15_choice_section_expanded.drawio.png +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/concepts/pipeline_schema/images/16_step_hierarchy.drawio.png +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/concepts/pipeline_schema/images/18_schema_to_pipeline.drawio.png +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/concepts/pipeline_schema/images/19_schema_to_pipeline_combined.drawio.png +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/concepts/pipeline_schema/images/clustering_sub_steps.drawio.png +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/concepts/pipeline_schema/images/easylink_pipeline_schema.drawio.png +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/concepts/pipeline_schema/images/entity_resolution_sub_steps.drawio.png +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/concepts/pipeline_schema/images/linking_sub_steps.drawio.png +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/concepts/pipeline_schema/index.rst +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/concepts/workarounds.rst +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/conf.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/glossary.rst +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/index.rst +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/user_guide/cli.rst +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/user_guide/index.rst +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/user_guide/tutorials/DAG-common-pipeline.svg +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/user_guide/tutorials/DAG-e2e-pipeline-expanded.svg +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/user_guide/tutorials/DAG-e2e-pipeline.svg +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/user_guide/tutorials/DAG-r-pyspark.svg +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/user_guide/tutorials/environment_slurm.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/user_guide/tutorials/getting_started.rst +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/user_guide/tutorials/impl-config-pipeline.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/user_guide/tutorials/index.rst +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/user_guide/tutorials/input_data.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/user_guide/tutorials/input_file_1.parquet +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/user_guide/tutorials/input_file_2.parquet +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/user_guide/tutorials/input_file_3.parquet +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/docs/source/user_guide/tutorials/r_spark_pipeline.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/pyproject.toml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/python_versions.json +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/pytype.cfg +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/setup.cfg +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/setup.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/__about__.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/__init__.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/cli.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/devtools/implementation_creator.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/graph_components.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/implementation.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/implementation_metadata.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/pipeline.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/pipeline_graph.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/pipeline_schema_constants/development.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/pipeline_schema_constants/main.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/rule.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/runner.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/cascading/exclude_clustered.def +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/cascading/exclude_clustered.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/cascading/exclude_none.def +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/cascading/exclude_none.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/cascading/update_clusters_by_connected_components.def +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/cascading/update_clusters_by_connected_components.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/default/default_clusters_to_links.def +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/default/default_clusters_to_links.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/default/default_determining_exclusions.def +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/default/default_determining_exclusions.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/default/default_removing_records.def +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/default/default_removing_records.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/default/default_schema_alignment.def +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/default/default_schema_alignment.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/default/default_updating_clusters.def +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/default/default_updating_clusters.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/dev/README.md +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/dev/build-containers-local.sh +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/dev/build-containers-remote.sh +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/dev/input_data/create_input_files.ipynb +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/dev/input_data/input_file_1.csv +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/dev/input_data/input_file_1.parquet +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/dev/input_data/input_file_2.csv +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/dev/input_data/input_file_2.parquet +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/dev/python_pandas/README.md +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/dev/python_pandas/dummy_step.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/dev/python_pandas/python_pandas.def +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/dev/python_pyspark/README.md +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/dev/python_pyspark/dummy_step.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/dev/python_pyspark/python_pyspark.def +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/dev/r/README.md +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/dev/r/dummy_step.R +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/dev/r/r-image.def +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/dev/test.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/fastLink/fastLink_evaluating_pairs.R +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/fastLink/fastLink_evaluating_pairs.def +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/fastLink/fastLink_links_to_clusters.R +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/fastLink/fastLink_links_to_clusters.def +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/output_dir/dummy_step_1_for_output_dir_example.def +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/output_dir/dummy_step_1_for_output_dir_example.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/output_dir/dummy_step_2_for_output_dir_example.def +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/output_dir/dummy_step_2_for_output_dir_example.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/rl-dummy/canonicalizing_and_downstream_analysis/dummy_canonicalizing_and_downstream_analysis.def +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/rl-dummy/canonicalizing_and_downstream_analysis/dummy_canonicalizing_and_downstream_analysis.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/rl-dummy/input_data/create_input_files.ipynb +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/rl-dummy/input_data/input_file_1.parquet +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/rl-dummy/input_data/input_file_2.parquet +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/rl-dummy/input_data/known_clusters.parquet +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/rl-dummy/pre-processing/dummy_pre-processing.def +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/rl-dummy/pre-processing/dummy_pre-processing.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/splink/splink_blocking_and_filtering.def +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/splink/splink_blocking_and_filtering.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/splink/splink_evaluating_pairs.def +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/splink/splink_evaluating_pairs.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/splink/splink_links_to_clusters.def +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/steps/splink/splink_links_to_clusters.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/utilities/__init__.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/utilities/aggregator_utils.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/utilities/data_utils.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/utilities/general_utils.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/utilities/paths.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/utilities/spark.smk +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/utilities/splitter_utils.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink/utilities/validation_utils.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink.egg-info/dependency_links.txt +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink.egg-info/entry_points.txt +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink.egg-info/not-zip-safe +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink.egg-info/requires.txt +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/src/easylink.egg-info/top_level.txt +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/__init__.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/conftest.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/e2e/pipeline_splink_dummy_results.csv +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/e2e/test_easylink_run.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/e2e/test_pipelines_main_schema.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/e2e/test_step_types.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/integration/test_compositions.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/integration/test_data_utils.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/integration/test_snakemake.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/integration/test_snakemake_slurm.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/integration/test_snakemake_spark.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/common/environment_local.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/common/input_data.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/common/input_data_one_file.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/common/pipeline.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/e2e/environment_slurm.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/e2e/input_data_dummy.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/e2e/pipeline.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/e2e/pipeline_cascade.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/e2e/pipeline_expanded.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/e2e/pipeline_splink_dummy.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/e2e/pipeline_with_fastLink.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/integration/auto_parallel/pipeline_cloneable_step.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/integration/auto_parallel/pipeline_hierarchical_step.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/integration/auto_parallel/pipeline_loop_step.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/integration/environment_spark_slurm.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/integration/pipeline.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/integration/pipeline_output_dir.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/integration/pipeline_output_dir_default.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/integration/pipeline_spark.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/unit/environment_minimum.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/unit/environment_spark_slurm.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/unit/pipeline.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/unit/pipeline_bad_combined_implementations.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/unit/pipeline_bad_implementation.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/unit/pipeline_bad_loop_formatting.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/unit/pipeline_bad_step.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/unit/pipeline_bad_type_key.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/unit/pipeline_combine_bad_implementation_names.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/unit/pipeline_combine_bad_topology.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/unit/pipeline_combine_two_steps.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/unit/pipeline_combine_with_extra_node.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/unit/pipeline_combine_with_iteration.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/unit/pipeline_combine_with_iteration_cycle.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/unit/pipeline_combine_with_missing_node.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/unit/pipeline_combine_with_parallel.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/unit/pipeline_missing_implementation_name.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/unit/pipeline_missing_implementations.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/unit/pipeline_missing_loop_nodes.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/unit/pipeline_missing_step.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/unit/pipeline_missing_substeps.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/unit/pipeline_missing_type_key.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/unit/pipeline_nested_templated_steps.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/unit/pipeline_out_of_order.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/unit/pipeline_spark.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/unit/pipeline_type_config_mismatch.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/specifications/unit/pipeline_wrong_clone_keys.yaml +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/unit/__init__.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/unit/conftest.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/unit/recipe_strings/python_pandas.txt +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/unit/rule_strings/aggregation_rule.txt +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/unit/rule_strings/auto_parallel_rule.txt +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/unit/rule_strings/checkpoint_rule.txt +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/unit/rule_strings/implemented_rule_local.txt +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/unit/rule_strings/implemented_rule_slurm.txt +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/unit/rule_strings/pipeline_local.txt +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/unit/rule_strings/pipeline_slurm.txt +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/unit/rule_strings/target_rule.txt +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/unit/rule_strings/validation_rule.txt +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/unit/test_cli.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/unit/test_config.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/unit/test_data_utils.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/unit/test_general_utils.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/unit/test_graph_components.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/unit/test_implementation.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/unit/test_implementation_creator.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/unit/test_pipeline.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/unit/test_pipeline_graph.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/unit/test_rule.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/unit/test_runner.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/unit/test_step.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/tests/unit/test_validations.py +0 -0
- {easylink-0.1.21 → easylink-0.1.22}/update_readme.py +0 -0
@@ -0,0 +1 @@
|
|
1
|
+
__version__ = "0.1.22"
|
@@ -184,7 +184,9 @@ class Config(LayeredConfigTree):
|
|
184
184
|
#################
|
185
185
|
|
186
186
|
def _get_schema(self, schema_name: str = "main") -> PipelineSchema:
|
187
|
-
"""
|
187
|
+
"""Gets the requested :class:`~easylink.pipeline_schema.PipelineSchema`.
|
188
|
+
|
189
|
+
The schema is only returned if it validates the pipeline configuration.
|
188
190
|
|
189
191
|
Parameters
|
190
192
|
----------
|
@@ -205,11 +207,10 @@ class Config(LayeredConfigTree):
|
|
205
207
|
Notes
|
206
208
|
-----
|
207
209
|
This acts as the pipeline configuration file's validation method since
|
208
|
-
we can only
|
210
|
+
we can only validate the ``PipelineSchema`` if that file is valid.
|
209
211
|
|
210
212
|
"""
|
211
213
|
errors = defaultdict(dict)
|
212
|
-
# Try each schema until one is validated
|
213
214
|
schema = PipelineSchema.get_schema(schema_name)
|
214
215
|
logs = schema.validate_step(self.pipeline, self.input_data)
|
215
216
|
if logs:
|
@@ -159,10 +159,10 @@ class PipelineSchema(HierarchicalStep):
|
|
159
159
|
)
|
160
160
|
|
161
161
|
@classmethod
|
162
|
-
def get_schema(cls, name: str = "main") ->
|
163
|
-
"""Gets
|
162
|
+
def get_schema(cls, name: str = "main") -> "PipelineSchema":
|
163
|
+
"""Gets the requested ``PipelineSchema``.
|
164
164
|
|
165
|
-
|
165
|
+
This ``PipelineSchema`` represents the fully supported pipelines and is
|
166
166
|
used to validate the user-requested pipeline.
|
167
167
|
|
168
168
|
Parameters
|
@@ -27,4 +27,5 @@ SCHEMA_PARAMS = {
|
|
27
27
|
"auto_parallel_cloneable_step": testing.SCHEMA_PARAMS_AUTO_PARALLEL_CLONEABLE_STEP,
|
28
28
|
"auto_parallel_loop_step": testing.SCHEMA_PARAMS_AUTO_PARALLEL_LOOP_STEP,
|
29
29
|
"auto_parallel_hierarchical_step": testing.SCHEMA_PARAMS_AUTO_PARALLEL_HIERARCHICAL_STEP,
|
30
|
+
"default_implementations": testing.SCHEMA_PARAMS_DEFAULT_IMPLEMENTATIONS,
|
30
31
|
}
|
@@ -640,3 +640,126 @@ EDGES_OUTPUT_DIR = [
|
|
640
640
|
),
|
641
641
|
]
|
642
642
|
SCHEMA_PARAMS_OUTPUT_DIR = (NODES_OUTPUT_DIR, EDGES_OUTPUT_DIR)
|
643
|
+
|
644
|
+
|
645
|
+
NODES_DEFAULT_IMPLEMENTATIONS = [
|
646
|
+
InputStep(),
|
647
|
+
HierarchicalStep(
|
648
|
+
step_name="step_1",
|
649
|
+
input_slots=[
|
650
|
+
InputSlot(
|
651
|
+
name="step_1_main_input",
|
652
|
+
env_var="DUMMY_CONTAINER_MAIN_INPUT_FILE_PATHS",
|
653
|
+
validator=validate_input_file_dummy,
|
654
|
+
),
|
655
|
+
],
|
656
|
+
output_slots=[OutputSlot("step_1_main_output")],
|
657
|
+
nodes=[
|
658
|
+
Step(
|
659
|
+
step_name="step_1a",
|
660
|
+
input_slots=[
|
661
|
+
InputSlot(
|
662
|
+
name="step_1a_main_input",
|
663
|
+
env_var="DUMMY_CONTAINER_MAIN_INPUT_FILE_PATHS",
|
664
|
+
validator=validate_input_file_dummy,
|
665
|
+
),
|
666
|
+
],
|
667
|
+
output_slots=[OutputSlot("step_1a_main_output")],
|
668
|
+
default_implementation="step_1a_python_pandas",
|
669
|
+
),
|
670
|
+
Step(
|
671
|
+
step_name="step_1b",
|
672
|
+
input_slots=[
|
673
|
+
InputSlot(
|
674
|
+
name="step_1b_main_input",
|
675
|
+
env_var="DUMMY_CONTAINER_MAIN_INPUT_FILE_PATHS",
|
676
|
+
validator=validate_input_file_dummy,
|
677
|
+
),
|
678
|
+
],
|
679
|
+
output_slots=[OutputSlot("step_1b_main_output")],
|
680
|
+
default_implementation="step_1b_python_pandas",
|
681
|
+
),
|
682
|
+
],
|
683
|
+
edges=[
|
684
|
+
EdgeParams(
|
685
|
+
source_node="step_1a",
|
686
|
+
target_node="step_1b",
|
687
|
+
output_slot="step_1a_main_output",
|
688
|
+
input_slot="step_1b_main_input",
|
689
|
+
),
|
690
|
+
],
|
691
|
+
input_slot_mappings=[
|
692
|
+
InputSlotMapping(
|
693
|
+
parent_slot="step_1_main_input",
|
694
|
+
child_node="step_1a",
|
695
|
+
child_slot="step_1a_main_input",
|
696
|
+
),
|
697
|
+
],
|
698
|
+
output_slot_mappings=[
|
699
|
+
OutputSlotMapping(
|
700
|
+
parent_slot="step_1_main_output",
|
701
|
+
child_node="step_1b",
|
702
|
+
child_slot="step_1b_main_output",
|
703
|
+
),
|
704
|
+
],
|
705
|
+
default_implementation="step_1_python_pandas",
|
706
|
+
),
|
707
|
+
Step(
|
708
|
+
step_name="step_2",
|
709
|
+
input_slots=[
|
710
|
+
InputSlot(
|
711
|
+
name="step_2_main_input",
|
712
|
+
env_var="DUMMY_CONTAINER_MAIN_INPUT_FILE_PATHS",
|
713
|
+
validator=validate_input_file_dummy,
|
714
|
+
)
|
715
|
+
],
|
716
|
+
output_slots=[OutputSlot("step_2_main_output")],
|
717
|
+
default_implementation="step_2_python_pandas",
|
718
|
+
),
|
719
|
+
LoopStep(
|
720
|
+
template_step=Step(
|
721
|
+
step_name="step_3",
|
722
|
+
input_slots=[
|
723
|
+
InputSlot(
|
724
|
+
name="step_3_main_input",
|
725
|
+
env_var="DUMMY_CONTAINER_MAIN_INPUT_FILE_PATHS",
|
726
|
+
validator=validate_input_file_dummy,
|
727
|
+
)
|
728
|
+
],
|
729
|
+
output_slots=[OutputSlot("step_3_main_output")],
|
730
|
+
),
|
731
|
+
self_edges=[
|
732
|
+
EdgeParams(
|
733
|
+
source_node="step_3",
|
734
|
+
target_node="step_3",
|
735
|
+
output_slot="step_3_main_output",
|
736
|
+
input_slot="step_3_main_input",
|
737
|
+
),
|
738
|
+
],
|
739
|
+
default_implementation="step_3_python_pandas",
|
740
|
+
),
|
741
|
+
CloneableStep(
|
742
|
+
template_step=Step(
|
743
|
+
step_name="step_4",
|
744
|
+
input_slots=[
|
745
|
+
InputSlot(
|
746
|
+
name="step_4_main_input",
|
747
|
+
env_var="DUMMY_CONTAINER_MAIN_INPUT_FILE_PATHS",
|
748
|
+
validator=validate_input_file_dummy,
|
749
|
+
),
|
750
|
+
],
|
751
|
+
output_slots=[
|
752
|
+
OutputSlot(
|
753
|
+
name="step_4_main_output",
|
754
|
+
),
|
755
|
+
],
|
756
|
+
),
|
757
|
+
default_implementation="step_4_python_pandas",
|
758
|
+
),
|
759
|
+
OutputStep(
|
760
|
+
input_slots=[
|
761
|
+
InputSlot(name="result", env_var=None, validator=validate_input_file_dummy)
|
762
|
+
],
|
763
|
+
),
|
764
|
+
]
|
765
|
+
SCHEMA_PARAMS_DEFAULT_IMPLEMENTATIONS = (NODES_DEFAULT_IMPLEMENTATIONS, EDGES_TWO_STEPS)
|
@@ -92,6 +92,7 @@ class Step:
|
|
92
92
|
input_slot_mappings: Iterable[InputSlotMapping] = (),
|
93
93
|
output_slot_mappings: Iterable[OutputSlotMapping] = (),
|
94
94
|
is_auto_parallel: bool = False,
|
95
|
+
default_implementation: str | None = None,
|
95
96
|
) -> None:
|
96
97
|
if not step_name and not name:
|
97
98
|
raise ValueError("All Steps must contain a step_name, name, or both.")
|
@@ -127,6 +128,9 @@ class Step:
|
|
127
128
|
``OutputSlotMappings`` of this ``Step``."""
|
128
129
|
self.is_auto_parallel = is_auto_parallel
|
129
130
|
"""Whether or not this ``Step`` is to be automatically run in parallel."""
|
131
|
+
self.default_implementation = default_implementation
|
132
|
+
"""The default implementation to use for this ``Step`` if the ``Step`` is
|
133
|
+
not explicitly configured in the pipeline specification."""
|
130
134
|
self.parent_step = None
|
131
135
|
"""This ``Step's`` parent ``Step``, if applicable."""
|
132
136
|
self._configuration_state = None
|
@@ -580,6 +584,7 @@ class HierarchicalStep(Step):
|
|
580
584
|
input_slot_mappings=(),
|
581
585
|
output_slot_mappings=(),
|
582
586
|
directly_implemented=True,
|
587
|
+
default_implementation: str | None = None,
|
583
588
|
):
|
584
589
|
super().__init__(
|
585
590
|
step_name,
|
@@ -588,6 +593,7 @@ class HierarchicalStep(Step):
|
|
588
593
|
output_slots,
|
589
594
|
input_slot_mappings,
|
590
595
|
output_slot_mappings,
|
596
|
+
default_implementation=default_implementation,
|
591
597
|
)
|
592
598
|
self.nodes = nodes
|
593
599
|
"""All sub-nodes (i.e. sub-``Steps``) that make up this ``HierarchicalStep``."""
|
@@ -722,13 +728,19 @@ class HierarchicalStep(Step):
|
|
722
728
|
step = self.step_graph.nodes[node]["step"]
|
723
729
|
if isinstance(step, IOStep):
|
724
730
|
continue
|
731
|
+
if step.name not in step_config:
|
732
|
+
default_implementation = self.step_graph.nodes[step.name][
|
733
|
+
"step"
|
734
|
+
].default_implementation
|
735
|
+
step_errors = (
|
736
|
+
{f"step {step.name}": ["The step is not configured."]}
|
737
|
+
if not default_implementation
|
738
|
+
else {}
|
739
|
+
)
|
725
740
|
else:
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
step_errors = step.validate_step(
|
730
|
-
step_config[step.name], combined_implementations, input_data_config
|
731
|
-
)
|
741
|
+
step_errors = step.validate_step(
|
742
|
+
step_config[step.name], combined_implementations, input_data_config
|
743
|
+
)
|
732
744
|
if step_errors:
|
733
745
|
errors.update(step_errors)
|
734
746
|
extra_steps = set(step_config.keys()) - set(self.step_graph.nodes)
|
@@ -830,12 +842,14 @@ class TemplatedStep(Step, ABC):
|
|
830
842
|
def __init__(
|
831
843
|
self,
|
832
844
|
template_step: Step,
|
845
|
+
default_implementation: str | None = None,
|
833
846
|
) -> None:
|
834
847
|
super().__init__(
|
835
848
|
template_step.step_name,
|
836
849
|
template_step.name,
|
837
850
|
template_step.input_slots.values(),
|
838
851
|
template_step.output_slots.values(),
|
852
|
+
default_implementation=default_implementation,
|
839
853
|
)
|
840
854
|
self.step_graph = None
|
841
855
|
"""The :class:`~easylink.graph_components.StepGraph` i.e. the directed acyclic
|
@@ -1110,8 +1124,9 @@ class LoopStep(TemplatedStep):
|
|
1110
1124
|
self,
|
1111
1125
|
template_step: Step | None = None,
|
1112
1126
|
self_edges: Iterable[EdgeParams] = (),
|
1127
|
+
default_implementation: str | None = None,
|
1113
1128
|
) -> None:
|
1114
|
-
super().__init__(template_step)
|
1129
|
+
super().__init__(template_step, default_implementation)
|
1115
1130
|
self.self_edges = self_edges
|
1116
1131
|
""":class:`~easylink.graph_components.EdgeParams` that represent self-edges,
|
1117
1132
|
i.e. edges that connect the output of one loop to the input of the next."""
|
@@ -2181,15 +2196,32 @@ class NonLeafConfigurationState(ConfigurationState):
|
|
2181
2196
|
|
2182
2197
|
This method recursively traverses the ``StepGraph`` and sets the configuration
|
2183
2198
|
state for each ``Step`` until reaching all leaf nodes.
|
2199
|
+
|
2200
|
+
Notes
|
2201
|
+
-----
|
2202
|
+
If a ``Step`` name is missing from the ``step_config``, we know that it
|
2203
|
+
must have a default implementation because we already validated that one
|
2204
|
+
exists during :meth:`HierarchicalStep._validate_step_graph`. In that case,
|
2205
|
+
we manually instantiate and use a ``step_config`` with the default implementation.
|
2184
2206
|
"""
|
2185
2207
|
for sub_node in self._step.step_graph.nodes:
|
2186
2208
|
sub_step = self._step.step_graph.nodes[sub_node]["step"]
|
2187
|
-
|
2188
|
-
|
2189
|
-
|
2190
|
-
|
2191
|
-
|
2192
|
-
|
2209
|
+
try:
|
2210
|
+
step_config = (
|
2211
|
+
self.step_config
|
2212
|
+
if isinstance(sub_step, StandaloneStep)
|
2213
|
+
else self.step_config[sub_step.name]
|
2214
|
+
)
|
2215
|
+
except KeyError:
|
2216
|
+
# We know that any missing keys must have a default implementation
|
2217
|
+
# (because we have already checked that it exists during validation)
|
2218
|
+
step_config = LayeredConfigTree(
|
2219
|
+
{
|
2220
|
+
"implementation": {
|
2221
|
+
"name": sub_step.default_implementation,
|
2222
|
+
}
|
2223
|
+
}
|
2224
|
+
)
|
2193
2225
|
sub_step.set_configuration_state(
|
2194
2226
|
step_config, self.combined_implementations, self.input_data_config
|
2195
2227
|
)
|
@@ -107,8 +107,6 @@ src/easylink.egg-info/not-zip-safe
|
|
107
107
|
src/easylink.egg-info/requires.txt
|
108
108
|
src/easylink.egg-info/top_level.txt
|
109
109
|
src/easylink/devtools/implementation_creator.py
|
110
|
-
src/easylink/images/spark_cluster/Dockerfile
|
111
|
-
src/easylink/images/spark_cluster/README.md
|
112
110
|
src/easylink/pipeline_schema_constants/__init__.py
|
113
111
|
src/easylink/pipeline_schema_constants/development.py
|
114
112
|
src/easylink/pipeline_schema_constants/main.py
|
@@ -223,6 +221,7 @@ tests/specifications/unit/pipeline_combine_with_iteration.yaml
|
|
223
221
|
tests/specifications/unit/pipeline_combine_with_iteration_cycle.yaml
|
224
222
|
tests/specifications/unit/pipeline_combine_with_missing_node.yaml
|
225
223
|
tests/specifications/unit/pipeline_combine_with_parallel.yaml
|
224
|
+
tests/specifications/unit/pipeline_default_implementations.yaml
|
226
225
|
tests/specifications/unit/pipeline_missing_implementation_name.yaml
|
227
226
|
tests/specifications/unit/pipeline_missing_implementations.yaml
|
228
227
|
tests/specifications/unit/pipeline_missing_loop_nodes.yaml
|
@@ -0,0 +1,24 @@
|
|
1
|
+
steps:
|
2
|
+
step_1:
|
3
|
+
substeps:
|
4
|
+
step_1a:
|
5
|
+
implementation:
|
6
|
+
name: step_1a_python_pandas
|
7
|
+
step_1b:
|
8
|
+
implementation:
|
9
|
+
name: step_1b_python_pandas
|
10
|
+
step_2:
|
11
|
+
implementation:
|
12
|
+
name: step_2_python_pandas
|
13
|
+
step_3:
|
14
|
+
iterate:
|
15
|
+
- implementation:
|
16
|
+
name: step_3_python_pandas
|
17
|
+
- implementation:
|
18
|
+
name: step_3_r
|
19
|
+
step_4:
|
20
|
+
clones:
|
21
|
+
- implementation:
|
22
|
+
name: step_4_python_pandas
|
23
|
+
- implementation:
|
24
|
+
name: step_4_r
|