tol-sdk 1.7.2__tar.gz → 1.7.4__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.
- {tol_sdk-1.7.2/src/tol_sdk.egg-info → tol_sdk-1.7.4}/PKG-INFO +1 -1
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/pyproject.toml +1 -1
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/api_base/pipeline_steps.py +8 -5
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/s3/__init__.py +1 -0
- {tol_sdk-1.7.2/src/tol/sql/summary → tol_sdk-1.7.4/src/tol/s3/data_upload}/__init__.py +0 -3
- tol_sdk-1.7.4/src/tol/s3/data_upload/blueprint.py +83 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/services/s3_client.py +5 -3
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sql/pipeline_step/factory.py +1 -1
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sql/standard/factory.py +54 -1
- tol_sdk-1.7.4/src/tol/validators/unique_values.py +100 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4/src/tol_sdk.egg-info}/PKG-INFO +1 -1
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol_sdk.egg-info/SOURCES.txt +2 -2
- tol_sdk-1.7.2/src/tol/sql/summary/factory.py +0 -91
- tol_sdk-1.7.2/src/tol/validators/unique_values.py +0 -72
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/LICENSE +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/MANIFEST.in +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/README.md +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/setup.cfg +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/certs/cacert.pem +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/actions/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/actions/action.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/actions/upsert_action.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/api_base/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/api_base/action.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/api_base/auth/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/api_base/auth/abc/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/api_base/auth/abc/auth.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/api_base/auth/abc/authorisation.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/api_base/auth/asserts.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/api_base/auth/blueprint.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/api_base/auth/composite.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/api_base/auth/config.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/api_base/auth/error.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/api_base/blueprint.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/api_base/controller.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/api_base/misc/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/api_base/misc/aggregation_body.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/api_base/misc/aggregation_parameters.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/api_base/misc/auth_context.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/api_base/misc/authenticate.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/api_base/misc/data_body.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/api_base/misc/filter_utils.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/api_base/misc/list_get_parameters.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/api_base/misc/relation_url.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/api_base/misc/stats_parameters.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/api_base/system.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/api_client/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/api_client/api_datasource.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/api_client/client.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/api_client/converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/api_client/exception.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/api_client/factory.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/api_client/filter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/api_client/parser.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/api_client/validate.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/api_client/view.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/barcodes/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/barcodes/main.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/benchling/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/benchling/benchling_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/benchling/benchling_datasource.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/benchling/benchling_warehouse_datasource.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/benchling/sql/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/benchling/sql/extraction_extraction_type_dna.sql +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/benchling/sql/extraction_extraction_type_lres.sql +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/benchling/sql/extraction_extraction_type_pooled_dna.sql +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/benchling/sql/extraction_extraction_type_rna.sql +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/benchling/sql/pacbio_prep.sql +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/benchling/sql/pooled_pacbio_prep.sql +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/benchling/sql/results_extraction_dna.sql +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/benchling/sql/results_extraction_pooled.sql +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/benchling/sql/results_extraction_rna.sql +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/benchling/sql/results_pacbio_prep.sql +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/benchling/sql/results_pacbio_prep_pooled.sql +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/benchling/sql/sample.sql +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/benchling/sql/sequencing_request_sequencing_platform_hic.sql +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/benchling/sql/sequencing_request_sequencing_platform_pacbio.sql +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/benchling/sql/sequencing_request_sequencing_platform_rnaseq.sql +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/benchling/sql/sequencing_request_sequencing_platform_wgs.sql +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/benchling/sql/tissue_prep.sql +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/board/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/board/blueprint.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/bold/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/bold/bold_datasource.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/bold/client.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/bold/converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/bold/factory.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/bold/parser.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/cli/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/cli/cli.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/converter/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/converter/yaml/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/converter/yaml/model.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/converter/yaml/yaml_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/copo/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/copo/client.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/copo/converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/copo/copo_datasource.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/copo/factory.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/copo/parser.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/core/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/core/attribute_metadata.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/core/core_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/core/data_loader.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/core/data_object.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/core/data_object_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/core/data_source_attribute_metadata.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/core/data_source_dict.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/core/datasource.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/core/datasource_error.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/core/datasource_filter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/core/datasource_utils.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/core/factory.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/core/http_client.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/core/operator/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/core/operator/_filterable.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/core/operator/_writer.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/core/operator/aggregator.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/core/operator/counter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/core/operator/cursor.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/core/operator/declare.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/core/operator/deleter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/core/operator/detail_getter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/core/operator/enricher.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/core/operator/enum.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/core/operator/group_statter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/core/operator/inserter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/core/operator/list_getter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/core/operator/operator_config.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/core/operator/page_getter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/core/operator/relational.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/core/operator/statter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/core/operator/summariser.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/core/operator/updater.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/core/operator/upserter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/core/relationship.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/core/requested_fields.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/core/session.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/core/validate.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/elastic/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/elastic/elastic_datasource.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/elastic/runtime_fields.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/eln/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/eln/auth.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/eln/eln_datasource.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/eln/entities.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/eln/generators.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/eln/sanitise.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/ena/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/ena/client.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/ena/converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/ena/ena_datasource.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/ena/ena_methods.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/ena/factory.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/ena/filter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/ena/parser.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/excel/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/excel/excel.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/excel/excel_datasource.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/excel/s3_factory.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/benchling_entity_to_benchling_worklist_item_converter_factory.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/benchling_extraction_to_elastic_extraction_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/benchling_extraction_to_elastic_sequencing_request_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/benchling_sample_casm_to_sts_sample_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/benchling_sample_to_elastic_sample_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/benchling_sequencing_request_to_elastic_sequencing_request_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/benchling_tissue_prep_to_elastic_tissue_prep_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/benchling_tissue_to_sts_sample_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/bioscan_extra_pantheon_species_to_elastic_sample_update_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/bioscan_image_to_elastic_sample_update_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/bioscan_qc_specimen_to_elastic_sample_update_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/bioscan_qc_uksi_entry_to_elastic_sample_update_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/bold_bin_to_elastic_sample_update_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/bold_sample_to_elastic_sample_update_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/elastic_object_to_portaldb_object_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/elastic_sample_to_benchling_tissue_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/elastic_sample_to_benchling_tissue_update_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/elastic_sample_to_bold_sample_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/elastic_sample_to_elastic_sequencing_request_update_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/elastic_sample_to_sts_sample_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/elastic_sequencing_request_to_elastic_run_data_update_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/elastic_sequencing_request_to_sts_sequencing_request_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/elastic_species_to_sts_species_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/elastic_tolid_to_elastic_curation_update_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/elastic_tolid_to_elastic_genome_note_update_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/elastic_tolid_to_elastic_sample_update_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/gap_assembly_to_elastic_assembly_analysis_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/gap_assembly_to_elastic_assembly_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/genome_notes_genome_note_to_elastic_genome_note_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/goat_taxon_to_elastic_species_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/grit_issue_to_elastic_curation_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/informatics_tolid_to_elastic_tolid_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/labwhere_location_to_elastic_sample_update_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/labwhere_location_to_sts_tray_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/mlwh_extraction_to_elastic_extraction_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/mlwh_run_data_to_elastic_run_data_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/mlwh_sequencing_request_to_elastic_sequencing_request_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/sts_banked_sample_to_elastic_sample_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/sts_manifest_to_elastic_manifest_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/sts_project_to_elastic_sample_update_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/sts_sample_project_to_elastic_sample_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/sts_sample_to_casm_benchling_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/sts_sampleset_to_elastic_sampleset_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/sts_species_to_elastic_species_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/tolid_specimen_to_elastic_tolid_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/tolqc_data_to_elastic_run_data_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/tolqc_sample_to_elastic_sequencing_request_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/tolqc_species_to_elastic_species_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/treeofsex_species_to_treeofsexwh_species_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/converters/treeofsex_upload_to_treeofsex_attribute_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/logger.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/secrets.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/flows/sequencing_submissions.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/gap/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/gap/gap_datasource.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/goat/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/goat/client.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/goat/converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/goat/factory.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/goat/filter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/goat/goat_datasource.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/goat/parser.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/google_sheets/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/google_sheets/google_sheet_datasource.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/irods/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/irods/irods_datasource.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/jira/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/jira/client.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/jira/converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/jira/factory.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/jira/filter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/jira/jira_datasource.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/jira/mapper.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/jira/parser.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/jira/sort.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/json/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/json/json_datasource.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/json/s3_json_datasource.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/labwhere/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/labwhere/client.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/labwhere/converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/labwhere/factory.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/labwhere/labwhere_datasource.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/labwhere/parser.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/markdown.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/mlwh/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/mlwh/mlwh_datasource.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/prefect/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/prefect/converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/prefect/factory.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/prefect/filter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/prefect/prefect_datasource.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/prefect/prefect_object.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/s3/converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/s3/factory.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/s3/parser.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/s3/s3_datasource.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sciops/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sciops/configuration.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sciops/consumer.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sciops/message_builder.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sciops/messages.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sciops/response_processors.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sciops/sequencing_datasource.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/services/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sources/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sources/benchling.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sources/benchling_warehouse.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sources/bioscan.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sources/bioscan_extra.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sources/bioscan_image.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sources/bioscan_qc.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sources/bold.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sources/copo.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sources/defaults.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sources/elastic.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sources/ena.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sources/gap.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sources/genome_notes.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sources/goat.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sources/grit.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sources/informatics.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sources/labwhere.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sources/mlwh.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sources/portal.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sources/portal_attributes.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sources/portaldb.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sources/prefect.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sources/sciops.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sources/sts.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sources/sts_legacy.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sources/tolid.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sources/tolqc.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sources/tolqc_legacy.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sources/treeofsex.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sources/uksi_qc.py.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sources/workflows.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sql/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sql/action/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sql/action/factory.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sql/auth/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sql/auth/blueprint.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sql/auth/models.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sql/cast.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sql/database.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sql/ds_session.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sql/exception.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sql/ext.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sql/factory.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sql/filter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sql/model.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sql/pipeline_step/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sql/relationship.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sql/session.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sql/sort.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sql/sql_converter.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sql/sql_datasource.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sql/standard/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/status/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/status/status_datasource.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sts/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sts/sts.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sts/sts_datasource.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/sts/sts_requests.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/treeval/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/treeval/treeval_datasource.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/utils/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/utils/csv.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/utils/s3.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/validators/__init__.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/validators/allowed_keys.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/validators/allowed_values.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/validators/regex.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol/validators/regex_by_value.py +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol_sdk.egg-info/dependency_links.txt +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol_sdk.egg-info/entry_points.txt +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol_sdk.egg-info/requires.txt +0 -0
- {tol_sdk-1.7.2 → tol_sdk-1.7.4}/src/tol_sdk.egg-info/top_level.txt +0 -0
|
@@ -49,7 +49,7 @@ REQUIRED_FIELDS: List = [
|
|
|
49
49
|
def pipeline_steps_blueprint(
|
|
50
50
|
sql_ds: SqlDataSource,
|
|
51
51
|
prefect_ds: PrefectDataSource,
|
|
52
|
-
role: str | None =
|
|
52
|
+
role: str | None = None,
|
|
53
53
|
url_prefix: str = '/run-pipeline',
|
|
54
54
|
|
|
55
55
|
ctx_getter: CtxGetter = default_ctx_getter,
|
|
@@ -155,7 +155,7 @@ def pipeline_steps_blueprint(
|
|
|
155
155
|
'deployment_name': flow_name,
|
|
156
156
|
'parameters': flow_params,
|
|
157
157
|
'tags': [
|
|
158
|
-
'app_name:
|
|
158
|
+
f'app_name: {os.environ.get("APP_NAME", "tol")}',
|
|
159
159
|
],
|
|
160
160
|
}
|
|
161
161
|
)
|
|
@@ -190,10 +190,13 @@ def pipeline_steps_blueprint(
|
|
|
190
190
|
def run_pipeline_steps() -> tuple[dict[str, Any], int]:
|
|
191
191
|
|
|
192
192
|
ctx = ctx_getter()
|
|
193
|
-
|
|
193
|
+
if role is not None:
|
|
194
|
+
if not ctx or not ctx.authenticated:
|
|
195
|
+
raise ForbiddenError()
|
|
196
|
+
if role not in ctx.roles:
|
|
197
|
+
raise ForbiddenError()
|
|
194
198
|
|
|
195
|
-
|
|
196
|
-
raise ForbiddenError()
|
|
199
|
+
user_id = ctx.user_id if ctx and ctx.authenticated else None
|
|
197
200
|
|
|
198
201
|
body: dict[str, Any] = request.json.get('data', {})
|
|
199
202
|
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2025 Genome Research Ltd.
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: MIT
|
|
4
|
+
|
|
5
|
+
from tempfile import NamedTemporaryFile
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from flask import Blueprint, request, send_file
|
|
9
|
+
|
|
10
|
+
from ...api_base import (
|
|
11
|
+
custom_blueprint,
|
|
12
|
+
)
|
|
13
|
+
from ...services.s3_client import S3Client
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
ALLOWED_EXTENSIONS: set[str] = {'csv', 'json', 'xlsx'}
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def allowed_file(filename: str) -> bool:
|
|
20
|
+
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def data_upload_blueprint(
|
|
24
|
+
url_prefix: str = '/pipeline/data_upload',
|
|
25
|
+
) -> Blueprint:
|
|
26
|
+
|
|
27
|
+
data_upload_blueprint = custom_blueprint(
|
|
28
|
+
name='data_upload',
|
|
29
|
+
url_prefix=url_prefix
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
@data_upload_blueprint.route('/upload', methods=['POST'])
|
|
33
|
+
def upload_file() -> tuple[dict[str, str], int]:
|
|
34
|
+
file = request.files['file']
|
|
35
|
+
s3_bucket: str = request.form.get('s3_bucket')
|
|
36
|
+
|
|
37
|
+
if not file:
|
|
38
|
+
return {'error': 'No file provided'}, 400
|
|
39
|
+
|
|
40
|
+
if not allowed_file(file.filename):
|
|
41
|
+
return {'error': 'File type not allowed'}, 400
|
|
42
|
+
|
|
43
|
+
if not s3_bucket:
|
|
44
|
+
return {'error': 'S3 bucket not specified'}, 400
|
|
45
|
+
|
|
46
|
+
try:
|
|
47
|
+
s3_client = S3Client()
|
|
48
|
+
with NamedTemporaryFile() as temp_file:
|
|
49
|
+
file.save(temp_file.name)
|
|
50
|
+
s3_client.put_object(s3_bucket, file.filename, temp_file.name)
|
|
51
|
+
|
|
52
|
+
return {'message': 'File uploaded successfully'}, 200
|
|
53
|
+
|
|
54
|
+
except Exception as e:
|
|
55
|
+
return {'error': f'Failed to upload file: {str(e)}'}, 500
|
|
56
|
+
|
|
57
|
+
@data_upload_blueprint.route('/download', methods=['POST'])
|
|
58
|
+
def download_file() -> tuple[dict[str, str], int]:
|
|
59
|
+
body: dict[str, Any] = request.json.get('data', {})
|
|
60
|
+
|
|
61
|
+
if 's3_bucket' not in body or 'file_name' not in body:
|
|
62
|
+
return {'error': 'S3 bucket or file name not specified'}, 400
|
|
63
|
+
|
|
64
|
+
bucket_name = body['s3_bucket']
|
|
65
|
+
file_name = body['file_name']
|
|
66
|
+
|
|
67
|
+
try:
|
|
68
|
+
s3_client = S3Client()
|
|
69
|
+
|
|
70
|
+
with NamedTemporaryFile() as temp_file:
|
|
71
|
+
s3_client.get_object(bucket_name, file_name, temp_file.name)
|
|
72
|
+
download_name = request.json.get('download_name', file_name)
|
|
73
|
+
|
|
74
|
+
return send_file(
|
|
75
|
+
temp_file.name,
|
|
76
|
+
as_attachment=True,
|
|
77
|
+
download_name=download_name,
|
|
78
|
+
mimetype='application/octet-stream'
|
|
79
|
+
)
|
|
80
|
+
except Exception as e:
|
|
81
|
+
return {'error': f'Failed to download file: {str(e)}'}, 500
|
|
82
|
+
|
|
83
|
+
return data_upload_blueprint
|
|
@@ -26,7 +26,7 @@ class S3Client:
|
|
|
26
26
|
secure = os.getenv('S3_SECURE', 'true').lower() == 'true'
|
|
27
27
|
|
|
28
28
|
self.client = Minio(
|
|
29
|
-
self.s3_uri,
|
|
29
|
+
endpoint=self.s3_uri,
|
|
30
30
|
access_key=self.access_key,
|
|
31
31
|
secret_key=self.secret_key,
|
|
32
32
|
secure=secure
|
|
@@ -39,7 +39,8 @@ class S3Client:
|
|
|
39
39
|
file_path: str
|
|
40
40
|
) -> None:
|
|
41
41
|
|
|
42
|
-
self.client.fget_object(bucket_name,
|
|
42
|
+
self.client.fget_object(bucket_name=bucket_name,
|
|
43
|
+
object_name=object_name, file_path=file_path)
|
|
43
44
|
|
|
44
45
|
def list_objects(
|
|
45
46
|
self,
|
|
@@ -55,4 +56,5 @@ class S3Client:
|
|
|
55
56
|
file_path: str
|
|
56
57
|
) -> None:
|
|
57
58
|
|
|
58
|
-
self.client.fput_object(bucket_name,
|
|
59
|
+
self.client.fput_object(bucket_name=bucket_name,
|
|
60
|
+
object_name=object_name, file_path=file_path)
|
|
@@ -37,6 +37,7 @@ class StandardModels(IterableABC[type[Model]]):
|
|
|
37
37
|
data_source_config: type[Model]
|
|
38
38
|
data_source_config_attribute: type[Model]
|
|
39
39
|
data_source_config_relationship: type[Model]
|
|
40
|
+
data_source_config_summary: type[Model]
|
|
40
41
|
component: type[Model]
|
|
41
42
|
component_zone: type[Model]
|
|
42
43
|
zone: type[Model]
|
|
@@ -61,6 +62,7 @@ class StandardModels(IterableABC[type[Model]]):
|
|
|
61
62
|
self.view_board,
|
|
62
63
|
self.view,
|
|
63
64
|
self.board,
|
|
65
|
+
self.data_source_config_summary,
|
|
64
66
|
self.data_source_config_relationship,
|
|
65
67
|
self.data_source_config_attribute,
|
|
66
68
|
self.loader_instance,
|
|
@@ -458,7 +460,6 @@ def create_standard_models(
|
|
|
458
460
|
|
|
459
461
|
name: Mapped[str] = mapped_column(nullable=False)
|
|
460
462
|
object_type: Mapped[str] = mapped_column(nullable=False)
|
|
461
|
-
name: Mapped[str] = mapped_column(nullable=False)
|
|
462
463
|
display_name: Mapped[str] = mapped_column(nullable=True)
|
|
463
464
|
description: Mapped[str] = mapped_column(nullable=True)
|
|
464
465
|
available_on_relationships: Mapped[bool] = mapped_column(nullable=False, default=True)
|
|
@@ -484,6 +485,53 @@ def create_standard_models(
|
|
|
484
485
|
foreign_keys=[data_source_config_id]
|
|
485
486
|
)
|
|
486
487
|
|
|
488
|
+
class DataSourceConfigSummary(base_model_class):
|
|
489
|
+
__tablename__ = 'data_source_config_summary'
|
|
490
|
+
|
|
491
|
+
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) # noqa A003
|
|
492
|
+
|
|
493
|
+
source_object_type: Mapped[str] = mapped_column(nullable=False)
|
|
494
|
+
destination_object_type: Mapped[str] = mapped_column(nullable=True)
|
|
495
|
+
|
|
496
|
+
object_filters: Mapped[dict] = mapped_column(
|
|
497
|
+
JSONB,
|
|
498
|
+
nullable=False,
|
|
499
|
+
default={}
|
|
500
|
+
)
|
|
501
|
+
|
|
502
|
+
group_by: Mapped[dict] = mapped_column(
|
|
503
|
+
JSONB,
|
|
504
|
+
nullable=False,
|
|
505
|
+
default=[]
|
|
506
|
+
)
|
|
507
|
+
|
|
508
|
+
stats_fields: Mapped[dict] = mapped_column(
|
|
509
|
+
JSONB,
|
|
510
|
+
nullable=False,
|
|
511
|
+
default=[]
|
|
512
|
+
)
|
|
513
|
+
|
|
514
|
+
stats: Mapped[dict] = mapped_column(
|
|
515
|
+
JSONB,
|
|
516
|
+
nullable=False,
|
|
517
|
+
default=[]
|
|
518
|
+
)
|
|
519
|
+
|
|
520
|
+
prefix: Mapped[str] = mapped_column(
|
|
521
|
+
nullable=False,
|
|
522
|
+
default=''
|
|
523
|
+
)
|
|
524
|
+
|
|
525
|
+
data_source_config_id: Mapped[int] = mapped_column(
|
|
526
|
+
ForeignKey('data_source_config.id'),
|
|
527
|
+
nullable=False
|
|
528
|
+
)
|
|
529
|
+
|
|
530
|
+
data_source_config: Mapped['DataSourceConfig'] = relationship( # noqa F821
|
|
531
|
+
back_populates='data_source_config_summaries',
|
|
532
|
+
foreign_keys=[data_source_config_id]
|
|
533
|
+
)
|
|
534
|
+
|
|
487
535
|
class DataSourceConfig(base_model_class):
|
|
488
536
|
__tablename__ = 'data_source_config'
|
|
489
537
|
|
|
@@ -504,6 +552,10 @@ def create_standard_models(
|
|
|
504
552
|
back_populates='data_source_config',
|
|
505
553
|
foreign_keys=[DataSourceConfigRelationship.data_source_config_id]
|
|
506
554
|
)
|
|
555
|
+
data_source_config_summaries: Mapped[list['DataSourceConfigSummary']] = relationship(
|
|
556
|
+
back_populates='data_source_config',
|
|
557
|
+
foreign_keys=[DataSourceConfigSummary.data_source_config_id]
|
|
558
|
+
)
|
|
507
559
|
|
|
508
560
|
class _UserMixin:
|
|
509
561
|
|
|
@@ -538,6 +590,7 @@ def create_standard_models(
|
|
|
538
590
|
data_source_config=DataSourceConfig,
|
|
539
591
|
data_source_config_attribute=DataSourceConfigAttribute,
|
|
540
592
|
data_source_config_relationship=DataSourceConfigRelationship,
|
|
593
|
+
data_source_config_summary=DataSourceConfigSummary,
|
|
541
594
|
component=Component,
|
|
542
595
|
component_zone=ComponentZone,
|
|
543
596
|
zone=Zone,
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2025 Genome Research Ltd.
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: MIT
|
|
4
|
+
|
|
5
|
+
from tol.core import DataObject
|
|
6
|
+
from tol.core.validate import Validator
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class UniqueValuesValidator(Validator):
|
|
10
|
+
"""
|
|
11
|
+
Validates that a stream of `DataObject` instances
|
|
12
|
+
contains unique values for specified keys.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
def __init__(
|
|
16
|
+
self,
|
|
17
|
+
unique_keys: list[list[str] | str],
|
|
18
|
+
*,
|
|
19
|
+
detail: str = 'Value is not unique',
|
|
20
|
+
is_error: bool = True,
|
|
21
|
+
) -> None:
|
|
22
|
+
|
|
23
|
+
super().__init__()
|
|
24
|
+
|
|
25
|
+
self.__keys = unique_keys
|
|
26
|
+
self.__detail = detail
|
|
27
|
+
self.__is_error = is_error
|
|
28
|
+
self.__duplicates: dict[str, list[str]] = {}
|
|
29
|
+
self.__existing_values: dict[str, set] = {}
|
|
30
|
+
for key in self.__keys:
|
|
31
|
+
if isinstance(key, str):
|
|
32
|
+
self.__existing_values[key] = set()
|
|
33
|
+
elif isinstance(key, list):
|
|
34
|
+
concat_key = '/'.join(key)
|
|
35
|
+
self.__existing_values[concat_key] = set()
|
|
36
|
+
|
|
37
|
+
def _validate_data_object(
|
|
38
|
+
self,
|
|
39
|
+
obj: DataObject
|
|
40
|
+
) -> None:
|
|
41
|
+
|
|
42
|
+
for unique_key in self.__keys:
|
|
43
|
+
if isinstance(unique_key, list):
|
|
44
|
+
concat = ''
|
|
45
|
+
for key in unique_key:
|
|
46
|
+
concat = concat + '/' + (str(obj.attributes[key]))
|
|
47
|
+
if concat in self.__existing_values['/'.join(unique_key)]:
|
|
48
|
+
self._duplicate_checks(
|
|
49
|
+
key=key,
|
|
50
|
+
value=concat
|
|
51
|
+
)
|
|
52
|
+
else:
|
|
53
|
+
self.__existing_values['/'.join(unique_key)].add(concat)
|
|
54
|
+
|
|
55
|
+
else:
|
|
56
|
+
if obj.attributes[unique_key] in self.__existing_values[unique_key]:
|
|
57
|
+
self._duplicate_checks(
|
|
58
|
+
key=unique_key,
|
|
59
|
+
value=obj.attributes[unique_key]
|
|
60
|
+
)
|
|
61
|
+
else:
|
|
62
|
+
self.__existing_values[unique_key].add(obj.attributes[unique_key])
|
|
63
|
+
|
|
64
|
+
def _duplicate_checks(
|
|
65
|
+
self,
|
|
66
|
+
key: str,
|
|
67
|
+
value: str
|
|
68
|
+
):
|
|
69
|
+
if key not in self.__duplicates:
|
|
70
|
+
self.__duplicates[key] = []
|
|
71
|
+
self.__duplicates[key].append(value)
|
|
72
|
+
|
|
73
|
+
def _post_validation(
|
|
74
|
+
self,
|
|
75
|
+
obj: DataObject,
|
|
76
|
+
) -> None:
|
|
77
|
+
for key in self.__duplicates:
|
|
78
|
+
self.__add_result(
|
|
79
|
+
obj=obj,
|
|
80
|
+
key=key,
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
def __add_result(
|
|
84
|
+
self,
|
|
85
|
+
obj: DataObject,
|
|
86
|
+
key: str,
|
|
87
|
+
) -> None:
|
|
88
|
+
|
|
89
|
+
if self.__is_error:
|
|
90
|
+
self.add_error(
|
|
91
|
+
object_id=obj.id,
|
|
92
|
+
detail=self.__detail,
|
|
93
|
+
field=key,
|
|
94
|
+
)
|
|
95
|
+
else:
|
|
96
|
+
self.add_warning(
|
|
97
|
+
object_id=obj.id,
|
|
98
|
+
detail=self.__detail,
|
|
99
|
+
field=key,
|
|
100
|
+
)
|
|
@@ -247,6 +247,8 @@ src/tol/s3/converter.py
|
|
|
247
247
|
src/tol/s3/factory.py
|
|
248
248
|
src/tol/s3/parser.py
|
|
249
249
|
src/tol/s3/s3_datasource.py
|
|
250
|
+
src/tol/s3/data_upload/__init__.py
|
|
251
|
+
src/tol/s3/data_upload/blueprint.py
|
|
250
252
|
src/tol/sciops/__init__.py
|
|
251
253
|
src/tol/sciops/configuration.py
|
|
252
254
|
src/tol/sciops/consumer.py
|
|
@@ -311,8 +313,6 @@ src/tol/sql/pipeline_step/__init__.py
|
|
|
311
313
|
src/tol/sql/pipeline_step/factory.py
|
|
312
314
|
src/tol/sql/standard/__init__.py
|
|
313
315
|
src/tol/sql/standard/factory.py
|
|
314
|
-
src/tol/sql/summary/__init__.py
|
|
315
|
-
src/tol/sql/summary/factory.py
|
|
316
316
|
src/tol/status/__init__.py
|
|
317
317
|
src/tol/status/status_datasource.py
|
|
318
318
|
src/tol/sts/__init__.py
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
# SPDX-FileCopyrightText: 2025 Genome Research Ltd.
|
|
2
|
-
#
|
|
3
|
-
# SPDX-License-Identifier: MIT
|
|
4
|
-
|
|
5
|
-
from __future__ import annotations
|
|
6
|
-
|
|
7
|
-
from collections.abc import Iterable as IterableABC
|
|
8
|
-
from dataclasses import dataclass
|
|
9
|
-
from typing import Iterator
|
|
10
|
-
|
|
11
|
-
from sqlalchemy.dialects.postgresql import JSONB
|
|
12
|
-
from sqlalchemy.orm import (
|
|
13
|
-
Mapped,
|
|
14
|
-
mapped_column
|
|
15
|
-
)
|
|
16
|
-
|
|
17
|
-
from ..model import Model
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
@dataclass(frozen=True, kw_only=True)
|
|
21
|
-
class SummaryModels(IterableABC[type[Model]]):
|
|
22
|
-
"""
|
|
23
|
-
Contains the needed models for summarys.
|
|
24
|
-
|
|
25
|
-
"""
|
|
26
|
-
|
|
27
|
-
summary: type[Model]
|
|
28
|
-
|
|
29
|
-
def __iter__(self) -> Iterator[type[Model]]:
|
|
30
|
-
"""
|
|
31
|
-
Returns in order they should be deleted
|
|
32
|
-
"""
|
|
33
|
-
|
|
34
|
-
return iter(
|
|
35
|
-
[
|
|
36
|
-
self.summary
|
|
37
|
-
]
|
|
38
|
-
)
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
def create_summary_models(
|
|
42
|
-
base_model_class: type[Model]
|
|
43
|
-
) -> SummaryModels:
|
|
44
|
-
"""
|
|
45
|
-
Creates all needed models (and joining tables) for
|
|
46
|
-
summaries.
|
|
47
|
-
|
|
48
|
-
Returns a `SummaryModels` instance that functions like an
|
|
49
|
-
`Iterable`.
|
|
50
|
-
"""
|
|
51
|
-
|
|
52
|
-
class Summary(base_model_class):
|
|
53
|
-
__tablename__ = 'summary'
|
|
54
|
-
|
|
55
|
-
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) # noqa A003
|
|
56
|
-
|
|
57
|
-
source_object_type: Mapped[str] = mapped_column(nullable=False)
|
|
58
|
-
destination_object_type: Mapped[str] = mapped_column(nullable=True)
|
|
59
|
-
|
|
60
|
-
object_filters: Mapped[dict] = mapped_column(
|
|
61
|
-
JSONB,
|
|
62
|
-
nullable=False,
|
|
63
|
-
default={}
|
|
64
|
-
)
|
|
65
|
-
|
|
66
|
-
group_by: Mapped[dict] = mapped_column(
|
|
67
|
-
JSONB,
|
|
68
|
-
nullable=False,
|
|
69
|
-
default=[]
|
|
70
|
-
)
|
|
71
|
-
|
|
72
|
-
stats_fields: Mapped[dict] = mapped_column(
|
|
73
|
-
JSONB,
|
|
74
|
-
nullable=False,
|
|
75
|
-
default=[]
|
|
76
|
-
)
|
|
77
|
-
|
|
78
|
-
stats: Mapped[dict] = mapped_column(
|
|
79
|
-
JSONB,
|
|
80
|
-
nullable=False,
|
|
81
|
-
default=[]
|
|
82
|
-
)
|
|
83
|
-
|
|
84
|
-
prefix: Mapped[str] = mapped_column(
|
|
85
|
-
nullable=False,
|
|
86
|
-
default=''
|
|
87
|
-
)
|
|
88
|
-
|
|
89
|
-
return SummaryModels(
|
|
90
|
-
summary=Summary,
|
|
91
|
-
)
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
# SPDX-FileCopyrightText: 2025 Genome Research Ltd.
|
|
2
|
-
#
|
|
3
|
-
# SPDX-License-Identifier: MIT
|
|
4
|
-
|
|
5
|
-
from tol.core import DataObject
|
|
6
|
-
from tol.core.validate import Validator
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class UniqueValuesValidator(Validator):
|
|
10
|
-
"""
|
|
11
|
-
Validates that a stream of `DataObject` instances
|
|
12
|
-
contains unique values for specified keys.
|
|
13
|
-
"""
|
|
14
|
-
|
|
15
|
-
def __init__(
|
|
16
|
-
self,
|
|
17
|
-
unique_keys: list[str],
|
|
18
|
-
*,
|
|
19
|
-
detail: str = 'Value is not unique',
|
|
20
|
-
is_error: bool = True,
|
|
21
|
-
) -> None:
|
|
22
|
-
|
|
23
|
-
super().__init__()
|
|
24
|
-
|
|
25
|
-
self.__keys = unique_keys
|
|
26
|
-
self.__detail = detail
|
|
27
|
-
self.__is_error = is_error
|
|
28
|
-
self.__duplicates: dict[str, list[str]] = {}
|
|
29
|
-
self.__existing_values: dict[str, set] = {key: set() for key in unique_keys}
|
|
30
|
-
|
|
31
|
-
def _validate_data_object(
|
|
32
|
-
self,
|
|
33
|
-
obj: DataObject
|
|
34
|
-
) -> None:
|
|
35
|
-
|
|
36
|
-
for key in obj.attributes:
|
|
37
|
-
if key in self.__keys:
|
|
38
|
-
if obj.attributes[key] in self.__existing_values[key]:
|
|
39
|
-
if key not in self.__duplicates:
|
|
40
|
-
self.__duplicates[key] = []
|
|
41
|
-
self.__duplicates[key].append(obj.attributes[key])
|
|
42
|
-
else:
|
|
43
|
-
self.__existing_values[key].add(obj.attributes[key])
|
|
44
|
-
|
|
45
|
-
def _post_validation(
|
|
46
|
-
self,
|
|
47
|
-
obj: DataObject,
|
|
48
|
-
) -> None:
|
|
49
|
-
for key in self.__duplicates:
|
|
50
|
-
self.__add_result(
|
|
51
|
-
obj=obj,
|
|
52
|
-
key=key,
|
|
53
|
-
)
|
|
54
|
-
|
|
55
|
-
def __add_result(
|
|
56
|
-
self,
|
|
57
|
-
obj: DataObject,
|
|
58
|
-
key: str,
|
|
59
|
-
) -> None:
|
|
60
|
-
|
|
61
|
-
if self.__is_error:
|
|
62
|
-
self.add_error(
|
|
63
|
-
object_id=obj.id,
|
|
64
|
-
detail=self.__detail,
|
|
65
|
-
field=key,
|
|
66
|
-
)
|
|
67
|
-
else:
|
|
68
|
-
self.add_warning(
|
|
69
|
-
object_id=obj.id,
|
|
70
|
-
detail=self.__detail,
|
|
71
|
-
field=key,
|
|
72
|
-
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|