tol-sdk 1.6.37__tar.gz → 1.7.1__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.6.37/src/tol_sdk.egg-info → tol_sdk-1.7.1}/PKG-INFO +2 -2
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/pyproject.toml +2 -2
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/api_base/blueprint.py +29 -6
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/api_base/controller.py +14 -5
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/api_client/api_datasource.py +15 -7
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/api_client/client.py +12 -6
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/api_client/converter.py +22 -8
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/api_client/factory.py +5 -3
- tol_sdk-1.7.1/src/tol/api_client/view.py +192 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/benchling/sql/sequencing_request_sequencing_platform_pacbio.sql +196 -84
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/cli/cli.py +1 -1
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/core/__init__.py +1 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/core/http_client.py +4 -2
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/core/operator/cursor.py +5 -3
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/core/operator/detail_getter.py +7 -15
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/core/operator/list_getter.py +3 -1
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/core/operator/page_getter.py +3 -1
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/core/operator/relational.py +9 -4
- tol_sdk-1.7.1/src/tol/core/requested_fields.py +189 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/elastic/elastic_datasource.py +2 -1
- tol_sdk-1.7.1/src/tol/flows/converters/benchling_extraction_to_elastic_extraction_converter.py +49 -0
- tol_sdk-1.7.1/src/tol/flows/converters/benchling_extraction_to_elastic_sequencing_request_converter.py +50 -0
- tol_sdk-1.7.1/src/tol/flows/converters/benchling_sequencing_request_to_elastic_sequencing_request_converter.py +59 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/benchling_tissue_prep_to_elastic_tissue_prep_converter.py +14 -3
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/elastic_sample_to_benchling_tissue_update_converter.py +1 -1
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/elastic_sample_to_elastic_sequencing_request_update_converter.py +4 -1
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/elastic_tolid_to_elastic_genome_note_update_converter.py +4 -1
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/elastic_tolid_to_elastic_sample_update_converter.py +4 -1
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/mlwh/mlwh_datasource.py +2 -2
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sources/sts.py +6 -2
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sql/database.py +80 -44
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sql/factory.py +2 -2
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sql/filter.py +22 -20
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sql/model.py +43 -38
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sql/relationship.py +1 -1
- tol_sdk-1.7.1/src/tol/sql/sql_converter.py +128 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sql/sql_datasource.py +85 -180
- {tol_sdk-1.6.37/src/tol/sql/board → tol_sdk-1.7.1/src/tol/sql/standard}/__init__.py +1 -1
- tol_sdk-1.7.1/src/tol/sql/standard/factory.py +549 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/validators/__init__.py +2 -0
- tol_sdk-1.7.1/src/tol/validators/regex.py +109 -0
- tol_sdk-1.7.1/src/tol/validators/regex_by_value.py +99 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1/src/tol_sdk.egg-info}/PKG-INFO +2 -2
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol_sdk.egg-info/SOURCES.txt +5 -4
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol_sdk.egg-info/requires.txt +1 -1
- tol_sdk-1.6.37/src/tol/api_client/view.py +0 -322
- tol_sdk-1.6.37/src/tol/flows/converters/benchling_extraction_to_elastic_extraction_converter.py +0 -30
- tol_sdk-1.6.37/src/tol/flows/converters/benchling_extraction_to_elastic_sequencing_request_converter.py +0 -29
- tol_sdk-1.6.37/src/tol/flows/converters/benchling_sequencing_request_to_elastic_sequencing_request_converter.py +0 -38
- tol_sdk-1.6.37/src/tol/sql/board/factory.py +0 -341
- tol_sdk-1.6.37/src/tol/sql/loader/__init__.py +0 -6
- tol_sdk-1.6.37/src/tol/sql/loader/factory.py +0 -246
- tol_sdk-1.6.37/src/tol/sql/sql_converter.py +0 -221
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/LICENSE +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/MANIFEST.in +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/README.md +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/setup.cfg +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/certs/cacert.pem +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/__init__.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/actions/__init__.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/actions/action.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/actions/upsert_action.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/api_base/__init__.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/api_base/action.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/api_base/auth/__init__.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/api_base/auth/abc/__init__.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/api_base/auth/abc/auth.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/api_base/auth/abc/authorisation.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/api_base/auth/asserts.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/api_base/auth/blueprint.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/api_base/auth/composite.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/api_base/auth/config.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/api_base/auth/error.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/api_base/misc/__init__.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/api_base/misc/aggregation_body.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/api_base/misc/aggregation_parameters.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/api_base/misc/auth_context.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/api_base/misc/authenticate.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/api_base/misc/data_body.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/api_base/misc/filter_utils.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/api_base/misc/list_get_parameters.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/api_base/misc/relation_url.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/api_base/misc/stats_parameters.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/api_base/pipeline_steps.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/api_base/system.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/api_client/__init__.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/api_client/exception.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/api_client/filter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/api_client/parser.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/api_client/validate.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/barcodes/__init__.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/barcodes/main.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/benchling/__init__.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/benchling/benchling_converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/benchling/benchling_datasource.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/benchling/benchling_warehouse_datasource.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/benchling/sql/__init__.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/benchling/sql/extraction_extraction_type_dna.sql +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/benchling/sql/extraction_extraction_type_lres.sql +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/benchling/sql/extraction_extraction_type_pooled_dna.sql +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/benchling/sql/extraction_extraction_type_rna.sql +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/benchling/sql/pacbio_prep.sql +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/benchling/sql/pooled_pacbio_prep.sql +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/benchling/sql/results_extraction_dna.sql +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/benchling/sql/results_extraction_pooled.sql +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/benchling/sql/results_extraction_rna.sql +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/benchling/sql/results_pacbio_prep.sql +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/benchling/sql/results_pacbio_prep_pooled.sql +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/benchling/sql/sample.sql +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/benchling/sql/sequencing_request_sequencing_platform_hic.sql +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/benchling/sql/sequencing_request_sequencing_platform_rnaseq.sql +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/benchling/sql/sequencing_request_sequencing_platform_wgs.sql +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/benchling/sql/tissue_prep.sql +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/board/__init__.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/board/blueprint.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/bold/__init__.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/bold/bold_datasource.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/bold/client.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/bold/converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/bold/factory.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/bold/parser.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/cli/__init__.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/converter/__init__.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/converter/yaml/__init__.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/converter/yaml/model.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/converter/yaml/yaml_converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/copo/__init__.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/copo/client.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/copo/converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/copo/copo_datasource.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/copo/factory.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/copo/parser.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/core/attribute_metadata.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/core/core_converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/core/data_loader.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/core/data_object.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/core/data_object_converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/core/data_source_attribute_metadata.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/core/data_source_dict.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/core/datasource.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/core/datasource_error.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/core/datasource_filter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/core/datasource_utils.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/core/factory.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/core/operator/__init__.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/core/operator/_filterable.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/core/operator/_writer.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/core/operator/aggregator.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/core/operator/counter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/core/operator/declare.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/core/operator/deleter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/core/operator/enricher.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/core/operator/enum.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/core/operator/group_statter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/core/operator/inserter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/core/operator/operator_config.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/core/operator/statter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/core/operator/summariser.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/core/operator/updater.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/core/operator/upserter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/core/relationship.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/core/session.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/core/validate.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/elastic/__init__.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/elastic/runtime_fields.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/eln/__init__.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/eln/auth.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/eln/eln_datasource.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/eln/entities.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/eln/generators.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/eln/sanitise.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/ena/__init__.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/ena/client.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/ena/converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/ena/ena_datasource.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/ena/ena_methods.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/ena/factory.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/ena/filter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/ena/parser.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/excel/__init__.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/excel/excel.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/excel/excel_datasource.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/excel/s3_factory.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/__init__.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/__init__.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/benchling_entity_to_benchling_worklist_item_converter_factory.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/benchling_sample_casm_to_sts_sample_converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/benchling_sample_to_elastic_sample_converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/benchling_tissue_to_sts_sample_converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/bioscan_extra_pantheon_species_to_elastic_sample_update_converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/bioscan_image_to_elastic_sample_update_converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/bioscan_qc_specimen_to_elastic_sample_update_converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/bioscan_qc_uksi_entry_to_elastic_sample_update_converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/bold_bin_to_elastic_sample_update_converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/bold_sample_to_elastic_sample_update_converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/elastic_object_to_portaldb_object_converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/elastic_sample_to_benchling_tissue_converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/elastic_sample_to_bold_sample_converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/elastic_sample_to_sts_sample_converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/elastic_sequencing_request_to_elastic_run_data_update_converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/elastic_sequencing_request_to_sts_sequencing_request_converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/elastic_species_to_sts_species_converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/elastic_tolid_to_elastic_curation_update_converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/gap_assembly_to_elastic_assembly_analysis_converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/gap_assembly_to_elastic_assembly_converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/genome_notes_genome_note_to_elastic_genome_note_converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/goat_taxon_to_elastic_species_converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/grit_issue_to_elastic_curation_converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/informatics_tolid_to_elastic_tolid_converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/labwhere_location_to_elastic_sample_update_converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/labwhere_location_to_sts_tray_converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/mlwh_extraction_to_elastic_extraction_converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/mlwh_run_data_to_elastic_run_data_converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/mlwh_sequencing_request_to_elastic_sequencing_request_converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/sts_banked_sample_to_elastic_sample_converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/sts_manifest_to_elastic_manifest_converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/sts_project_to_elastic_sample_update_converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/sts_sample_project_to_elastic_sample_converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/sts_sample_to_casm_benchling_converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/sts_sampleset_to_elastic_sampleset_converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/sts_species_to_elastic_species_converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/tolid_specimen_to_elastic_tolid_converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/tolqc_data_to_elastic_run_data_converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/tolqc_sample_to_elastic_sequencing_request_converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/tolqc_species_to_elastic_species_converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/treeofsex_species_to_treeofsexwh_species_converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/converters/treeofsex_upload_to_treeofsex_attribute_converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/logger.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/secrets.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/flows/sequencing_submissions.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/gap/__init__.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/gap/gap_datasource.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/goat/__init__.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/goat/client.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/goat/converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/goat/factory.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/goat/filter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/goat/goat_datasource.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/goat/parser.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/google_sheets/__init__.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/google_sheets/google_sheet_datasource.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/irods/__init__.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/irods/irods_datasource.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/jira/__init__.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/jira/client.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/jira/converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/jira/factory.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/jira/filter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/jira/jira_datasource.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/jira/mapper.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/jira/parser.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/jira/sort.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/json/__init__.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/json/json_datasource.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/json/s3_json_datasource.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/labwhere/__init__.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/labwhere/client.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/labwhere/converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/labwhere/factory.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/labwhere/labwhere_datasource.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/labwhere/parser.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/markdown.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/mlwh/__init__.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/prefect/__init__.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/prefect/converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/prefect/factory.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/prefect/filter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/prefect/prefect_datasource.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/prefect/prefect_object.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/s3/__init__.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/s3/converter.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/s3/factory.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/s3/parser.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/s3/s3_datasource.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sciops/__init__.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sciops/configuration.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sciops/consumer.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sciops/message_builder.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sciops/messages.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sciops/response_processors.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sciops/sequencing_datasource.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/services/__init__.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/services/s3_client.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sources/__init__.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sources/benchling.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sources/benchling_warehouse.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sources/bioscan.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sources/bioscan_extra.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sources/bioscan_image.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sources/bioscan_qc.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sources/bold.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sources/copo.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sources/defaults.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sources/elastic.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sources/ena.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sources/gap.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sources/genome_notes.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sources/goat.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sources/grit.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sources/informatics.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sources/labwhere.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sources/mlwh.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sources/portal.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sources/portal_attributes.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sources/portaldb.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sources/prefect.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sources/sciops.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sources/sts_legacy.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sources/tolid.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sources/tolqc.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sources/tolqc_legacy.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sources/treeofsex.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sources/uksi_qc.py.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sources/workflows.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sql/__init__.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sql/action/__init__.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sql/action/factory.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sql/auth/__init__.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sql/auth/blueprint.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sql/auth/models.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sql/cast.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sql/ds_session.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sql/exception.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sql/ext.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sql/pipeline_step/__init__.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sql/pipeline_step/factory.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sql/session.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sql/sort.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sql/summary/__init__.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sql/summary/factory.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/status/__init__.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/status/status_datasource.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sts/__init__.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sts/sts.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sts/sts_datasource.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/sts/sts_requests.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/treeval/__init__.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/treeval/treeval_datasource.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/utils/__init__.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/utils/csv.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/utils/s3.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/validators/allowed_keys.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/validators/allowed_values.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol/validators/unique_values.py +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol_sdk.egg-info/dependency_links.txt +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol_sdk.egg-info/entry_points.txt +0 -0
- {tol_sdk-1.6.37 → tol_sdk-1.7.1}/src/tol_sdk.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tol-sdk
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.7.1
|
|
4
4
|
Summary: SDK for interaction with ToL, Sanger and external services
|
|
5
5
|
Author-email: ToL Platforms Team <tol-platforms@sanger.ac.uk>
|
|
6
6
|
License: MIT
|
|
@@ -37,7 +37,7 @@ Requires-Dist: atlassian-python-api==3.41.14; extra == "jira"
|
|
|
37
37
|
Provides-Extra: json
|
|
38
38
|
Requires-Dist: minio==7.2.15; extra == "json"
|
|
39
39
|
Provides-Extra: mysql
|
|
40
|
-
Requires-Dist: mysql-connector-python; extra == "mysql"
|
|
40
|
+
Requires-Dist: mysql-connector-python==9.5.0; extra == "mysql"
|
|
41
41
|
Provides-Extra: postgresql
|
|
42
42
|
Requires-Dist: SQLAlchemy==2.0.35; extra == "postgresql"
|
|
43
43
|
Requires-Dist: psycopg2-binary==2.9.9; extra == "postgresql"
|
|
@@ -8,7 +8,7 @@ build-backend = "setuptools.build_meta"
|
|
|
8
8
|
|
|
9
9
|
[project]
|
|
10
10
|
name = "tol-sdk"
|
|
11
|
-
version = "1.
|
|
11
|
+
version = "1.7.1"
|
|
12
12
|
description = "SDK for interaction with ToL, Sanger and external services"
|
|
13
13
|
readme = "README.md"
|
|
14
14
|
authors = [
|
|
@@ -43,7 +43,7 @@ elastic = ["elasticsearch == 7.17.9"]
|
|
|
43
43
|
irods = ["python-irodsclient == 3.1.0"]
|
|
44
44
|
jira = ["atlassian-python-api==3.41.14"]
|
|
45
45
|
json = ["minio == 7.2.15"]
|
|
46
|
-
mysql = ["mysql-connector-python"]
|
|
46
|
+
mysql = ["mysql-connector-python==9.5.0"]
|
|
47
47
|
postgresql = ["SQLAlchemy == 2.0.35", "psycopg2-binary == 2.9.9"]
|
|
48
48
|
prefect = ["prefect == 2.20.18", "griffe < 1.0.0"]
|
|
49
49
|
sheets = [
|
|
@@ -35,6 +35,7 @@ from ..core import DataSource, DataSourceError, OperableDataSource
|
|
|
35
35
|
from ..core.data_source_dict import DataSourceDict
|
|
36
36
|
from ..core.operator import Relational
|
|
37
37
|
from ..core.operator.operator_config import DefaultOperatorConfig, OperatorConfig
|
|
38
|
+
from ..core.requested_fields import ReqFieldsTree
|
|
38
39
|
|
|
39
40
|
|
|
40
41
|
class DataBlueprint(Blueprint):
|
|
@@ -179,6 +180,7 @@ def _core_blueprint(
|
|
|
179
180
|
data_source_dict: dict[str, DataSource],
|
|
180
181
|
url_prefix: str,
|
|
181
182
|
auth_inspector: Optional[AuthInspector] = None,
|
|
183
|
+
include_all_to_ones: bool = True,
|
|
182
184
|
) -> DataBlueprint:
|
|
183
185
|
"""
|
|
184
186
|
Create the core blueprint responsible for managing DataSource endpoints.
|
|
@@ -193,6 +195,8 @@ def _core_blueprint(
|
|
|
193
195
|
url_prefix (str): URL prefix for all data endpoints.
|
|
194
196
|
auth_inspector (Optional[AuthInspector], optional): Authentication
|
|
195
197
|
inspector for request authorisation.
|
|
198
|
+
include_all_to_ones (bool): Whether to fetch or store all to-one related objects
|
|
199
|
+
when fetching or serialising DataObjects.
|
|
196
200
|
|
|
197
201
|
Returns:
|
|
198
202
|
DataBlueprint: A configured blueprint with all data endpoints and error handlers.
|
|
@@ -231,18 +235,30 @@ def _core_blueprint(
|
|
|
231
235
|
hop_limit = None if requested_fields else 1
|
|
232
236
|
|
|
233
237
|
data_source = data_source_dict[object_type]
|
|
238
|
+
|
|
239
|
+
# Build a ReqFieldsTree template for the request
|
|
240
|
+
req_fields_tree = ReqFieldsTree(
|
|
241
|
+
object_type,
|
|
242
|
+
data_source,
|
|
243
|
+
requested_fields,
|
|
244
|
+
include_all_to_ones=include_all_to_ones,
|
|
245
|
+
)
|
|
246
|
+
|
|
234
247
|
view = DefaultView(
|
|
248
|
+
requested_tree=req_fields_tree,
|
|
235
249
|
prefix=url_prefix,
|
|
236
|
-
include_all_to_ones=True,
|
|
237
250
|
hop_limit=hop_limit,
|
|
238
|
-
requested_fields=requested_fields,
|
|
239
251
|
)
|
|
240
|
-
return Controller(data_source, view, auth_inspector=auth_inspector)
|
|
252
|
+
return Controller(data_source, view, req_fields_tree, auth_inspector=auth_inspector)
|
|
241
253
|
|
|
242
254
|
@data_handler.route('/<object_type>/<path:object_id>', methods=['GET']) # Allow slashes
|
|
243
255
|
def get_detail(*, object_type: str, object_id: str):
|
|
244
256
|
"""Get details of a specific object by ID."""
|
|
245
|
-
|
|
257
|
+
request_args = ListGetParameters(request.args)
|
|
258
|
+
controller = __new_controller(
|
|
259
|
+
object_type,
|
|
260
|
+
requested_fields=request_args.requested_fields,
|
|
261
|
+
)
|
|
246
262
|
object_id_unencoded = urllib.parse.unquote(object_id)
|
|
247
263
|
return controller.get_detail(object_type, object_id_unencoded)
|
|
248
264
|
|
|
@@ -325,8 +341,11 @@ def _core_blueprint(
|
|
|
325
341
|
@data_handler.post('/<object_type>:cursor')
|
|
326
342
|
def get_cursor_page(*, object_type: str):
|
|
327
343
|
"""Get a page of results using cursor-based pagination."""
|
|
328
|
-
controller = __new_controller(object_type)
|
|
329
344
|
request_args = ListGetParameters(request.args)
|
|
345
|
+
controller = __new_controller(
|
|
346
|
+
object_type,
|
|
347
|
+
requested_fields=request_args.requested_fields,
|
|
348
|
+
)
|
|
330
349
|
search_after = request.json.get('search_after')
|
|
331
350
|
return controller.get_cursor_page(object_type, request_args, search_after)
|
|
332
351
|
|
|
@@ -369,6 +388,7 @@ def data_blueprint(
|
|
|
369
388
|
url_prefix: str = '/data',
|
|
370
389
|
config_prefix: str = '/_config',
|
|
371
390
|
auth_inspector: Optional[AuthInspector] = None,
|
|
391
|
+
include_all_to_ones: bool = True,
|
|
372
392
|
) -> DataBlueprint:
|
|
373
393
|
"""
|
|
374
394
|
Create a complete data blueprint with both core and configuration endpoints.
|
|
@@ -405,7 +425,10 @@ def data_blueprint(
|
|
|
405
425
|
config_prefix, data_sources, DefaultOperatorConfig(*data_sources)
|
|
406
426
|
)
|
|
407
427
|
core_bp = _core_blueprint(
|
|
408
|
-
DataSourceDict(*data_sources),
|
|
428
|
+
DataSourceDict(*data_sources),
|
|
429
|
+
url_prefix,
|
|
430
|
+
auth_inspector=auth_inspector,
|
|
431
|
+
include_all_to_ones=include_all_to_ones,
|
|
409
432
|
)
|
|
410
433
|
core_bp.register_blueprint(config_bp)
|
|
411
434
|
|
|
@@ -31,7 +31,7 @@ from ..api_client.exception import (
|
|
|
31
31
|
UnsupportedOperationError,
|
|
32
32
|
)
|
|
33
33
|
from ..api_client.view import ResponseDict, View
|
|
34
|
-
from ..core import DataObject, OperableDataSource
|
|
34
|
+
from ..core import DataObject, OperableDataSource, ReqFieldsTree
|
|
35
35
|
from ..core.datasource_filter import AndFilter, DataSourceFilter
|
|
36
36
|
from ..core.operator import (
|
|
37
37
|
Aggregator,
|
|
@@ -160,6 +160,7 @@ class Controller:
|
|
|
160
160
|
self,
|
|
161
161
|
data_source: OperableDataSource,
|
|
162
162
|
view: View,
|
|
163
|
+
requested_tree: ReqFieldsTree | None = None,
|
|
163
164
|
auth_inspector: Optional[AuthInspector] = None,
|
|
164
165
|
) -> None:
|
|
165
166
|
"""
|
|
@@ -173,6 +174,7 @@ class Controller:
|
|
|
173
174
|
"""
|
|
174
175
|
self.__data_source = data_source
|
|
175
176
|
self.__view = view
|
|
177
|
+
self.__requested_tree = requested_tree
|
|
176
178
|
self.__inspector = auth_inspector
|
|
177
179
|
|
|
178
180
|
@property
|
|
@@ -263,13 +265,13 @@ class Controller:
|
|
|
263
265
|
page_size=query_args.page_size,
|
|
264
266
|
object_filters=self.__combine_filters(query_args.filter, ext_and),
|
|
265
267
|
sort_by=query_args.sort_by,
|
|
266
|
-
|
|
268
|
+
requested_tree=self.__requested_tree,
|
|
267
269
|
)
|
|
268
|
-
|
|
270
|
+
meta = {
|
|
269
271
|
'total': total,
|
|
270
272
|
'types': self.__data_source.get_attribute_types(object_type),
|
|
271
273
|
}
|
|
272
|
-
return self.__view.dump_bulk(data_objects, document_meta=
|
|
274
|
+
return self.__view.dump_bulk(data_objects, document_meta=meta)
|
|
273
275
|
|
|
274
276
|
@validate(Counter, 'get_count', OperatorMethod.COUNT)
|
|
275
277
|
def get_count(
|
|
@@ -545,6 +547,7 @@ class Controller:
|
|
|
545
547
|
query_args.page_size,
|
|
546
548
|
self.__combine_filters(query_args.filter, ext_and),
|
|
547
549
|
search_after,
|
|
550
|
+
requested_tree=self.__requested_tree,
|
|
548
551
|
)
|
|
549
552
|
meta = {'search_after': new_search_after}
|
|
550
553
|
|
|
@@ -657,7 +660,13 @@ class Controller:
|
|
|
657
660
|
Raises:
|
|
658
661
|
ObjectNotFoundByIdException: If no object with the given ID exists.
|
|
659
662
|
"""
|
|
660
|
-
data_objects = list(
|
|
663
|
+
data_objects = list(
|
|
664
|
+
self.__data_source.get_by_id(
|
|
665
|
+
object_type,
|
|
666
|
+
[object_id],
|
|
667
|
+
requested_tree=self.__requested_tree,
|
|
668
|
+
)
|
|
669
|
+
)
|
|
661
670
|
if len(data_objects) == 0 or data_objects[0] is None:
|
|
662
671
|
raise ObjectNotFoundByIdException(object_type, object_id)
|
|
663
672
|
return data_objects[0]
|
|
@@ -144,7 +144,11 @@ class ApiDataSource(
|
|
|
144
144
|
|
|
145
145
|
client = self.__client_factory()
|
|
146
146
|
json_responses = (
|
|
147
|
-
client.get_detail(
|
|
147
|
+
client.get_detail(
|
|
148
|
+
object_type,
|
|
149
|
+
id_,
|
|
150
|
+
requested_fields=requested_fields,
|
|
151
|
+
)
|
|
148
152
|
for id_ in object_ids
|
|
149
153
|
)
|
|
150
154
|
json_converter = self.__jc_factory()
|
|
@@ -184,16 +188,17 @@ class ApiDataSource(
|
|
|
184
188
|
session: Optional[OperableSession] = None,
|
|
185
189
|
requested_fields: list[str] | None = None,
|
|
186
190
|
) -> Iterable[DataObject]:
|
|
187
|
-
|
|
188
191
|
if self.__can_cursor(object_type, object_filters):
|
|
189
192
|
return self._get_list_by_cursor(
|
|
190
193
|
object_type,
|
|
191
|
-
object_filters
|
|
194
|
+
object_filters,
|
|
195
|
+
requested_fields=requested_fields,
|
|
192
196
|
)
|
|
193
197
|
else:
|
|
194
198
|
return self.__get_list_regular(
|
|
195
199
|
object_type,
|
|
196
|
-
object_filters
|
|
200
|
+
object_filters,
|
|
201
|
+
requested_fields=requested_fields,
|
|
197
202
|
)
|
|
198
203
|
|
|
199
204
|
@validate('count')
|
|
@@ -266,7 +271,8 @@ class ApiDataSource(
|
|
|
266
271
|
object_type,
|
|
267
272
|
page_size,
|
|
268
273
|
search_after,
|
|
269
|
-
filter_string=filter_string
|
|
274
|
+
filter_string=filter_string,
|
|
275
|
+
requested_fields=requested_fields,
|
|
270
276
|
)
|
|
271
277
|
return self.__jc_factory().convert_cursor_page(transfer)
|
|
272
278
|
|
|
@@ -429,7 +435,8 @@ class ApiDataSource(
|
|
|
429
435
|
def __get_list_regular(
|
|
430
436
|
self,
|
|
431
437
|
object_type: str,
|
|
432
|
-
object_filters: Optional[DataSourceFilter]
|
|
438
|
+
object_filters: Optional[DataSourceFilter],
|
|
439
|
+
requested_fields: list[str] | None = None,
|
|
433
440
|
) -> Iterable[DataObject]:
|
|
434
441
|
|
|
435
442
|
page = 1
|
|
@@ -443,7 +450,8 @@ class ApiDataSource(
|
|
|
443
450
|
object_type,
|
|
444
451
|
page,
|
|
445
452
|
page_size,
|
|
446
|
-
filter_string=filter_string
|
|
453
|
+
filter_string=filter_string,
|
|
454
|
+
requested_fields=requested_fields,
|
|
447
455
|
)
|
|
448
456
|
(results_page, _) = jc_converter.convert_list(transfer)
|
|
449
457
|
|
|
@@ -28,9 +28,13 @@ class JsonApiClient(HttpClient):
|
|
|
28
28
|
config_prefix: str = '/_config',
|
|
29
29
|
token_header: str = 'token',
|
|
30
30
|
retries: int = 5,
|
|
31
|
+
status_forcelist: Optional[list[int]] = None,
|
|
31
32
|
merge_collections: bool | None = None,
|
|
32
33
|
) -> None:
|
|
33
|
-
|
|
34
|
+
kwargs = {'token': token, 'token_header': token_header, 'retries': retries}
|
|
35
|
+
if status_forcelist is not None:
|
|
36
|
+
kwargs['status_forcelist'] = status_forcelist
|
|
37
|
+
super().__init__(**kwargs)
|
|
34
38
|
self.__data_url = f'{api_url}{data_prefix}'
|
|
35
39
|
self.__config_url = f'{self.__data_url}{config_prefix}'
|
|
36
40
|
self.__merge_collections = merge_collections
|
|
@@ -77,7 +81,7 @@ class JsonApiClient(HttpClient):
|
|
|
77
81
|
page_size=page_size,
|
|
78
82
|
filter=filter_string,
|
|
79
83
|
sort_by=sort_string,
|
|
80
|
-
|
|
84
|
+
requested_fields=requested_fields
|
|
81
85
|
)
|
|
82
86
|
headers = self._merge_headers()
|
|
83
87
|
return self.__fetch_list(
|
|
@@ -455,7 +459,9 @@ class JsonApiClient(HttpClient):
|
|
|
455
459
|
return f'{self.__config_url}/return_mode'
|
|
456
460
|
|
|
457
461
|
def __no_none_value_dict(self, **kwargs) -> dict[str, Any]:
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
if v is
|
|
461
|
-
|
|
462
|
+
str_params = {}
|
|
463
|
+
for k, v in kwargs.items():
|
|
464
|
+
if v is None:
|
|
465
|
+
continue
|
|
466
|
+
str_params[k] = ','.join([str(x) for x in v]) if isinstance(v, list) else str(v)
|
|
467
|
+
return str_params
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
from typing import Any, Dict, Optional, Union
|
|
6
6
|
|
|
7
7
|
from .parser import Parser
|
|
8
|
-
from .view import
|
|
9
|
-
from ..core import DataObject
|
|
8
|
+
from .view import DefaultView
|
|
9
|
+
from ..core import DataObject, DataSource, ReqFieldsTree
|
|
10
10
|
from ..core.relationship import RelationshipConfig
|
|
11
11
|
|
|
12
12
|
|
|
@@ -25,7 +25,7 @@ JsonRelationshipConfig = dict[
|
|
|
25
25
|
]
|
|
26
26
|
|
|
27
27
|
|
|
28
|
-
class JsonApiConverter
|
|
28
|
+
class JsonApiConverter:
|
|
29
29
|
|
|
30
30
|
"""
|
|
31
31
|
Converts from JSON:API transfers to instances of
|
|
@@ -142,26 +142,40 @@ class JsonApiConverter():
|
|
|
142
142
|
)
|
|
143
143
|
|
|
144
144
|
|
|
145
|
-
class DataObjectConverter
|
|
145
|
+
class DataObjectConverter:
|
|
146
146
|
|
|
147
147
|
"""
|
|
148
148
|
Converts from instances of `DataObject` to
|
|
149
149
|
JSON:API transfers.
|
|
150
150
|
"""
|
|
151
151
|
|
|
152
|
-
def __init__(
|
|
153
|
-
self
|
|
152
|
+
def __init__(
|
|
153
|
+
self,
|
|
154
|
+
data_source: DataSource,
|
|
155
|
+
prefix: str | None = None,
|
|
156
|
+
) -> None:
|
|
157
|
+
self.__data_source = data_source
|
|
158
|
+
self.__prefix = prefix
|
|
159
|
+
|
|
160
|
+
def __build_view(self, object_type):
|
|
161
|
+
req_fields_tree = ReqFieldsTree(object_type, self.__data_source)
|
|
162
|
+
return DefaultView(req_fields_tree, self.__prefix)
|
|
154
163
|
|
|
155
164
|
def convert(self, input_: DataObject) -> JsonApiTransfer:
|
|
156
165
|
"""
|
|
157
166
|
Converts a single `DataObject` instance to a JsonApiTransfer
|
|
158
167
|
"""
|
|
159
168
|
|
|
160
|
-
|
|
169
|
+
view = self.__build_view(input_.type)
|
|
170
|
+
return view.dump(input_)
|
|
161
171
|
|
|
162
172
|
def convert_list(self, input_: list[DataObject]) -> JsonApiTransfer:
|
|
163
173
|
"""
|
|
164
174
|
Converts a `list` of `DataObject` instances to a JsonApiTransfer
|
|
165
175
|
"""
|
|
166
176
|
|
|
167
|
-
|
|
177
|
+
if not input_:
|
|
178
|
+
msg = 'Cannot convert empty list'
|
|
179
|
+
raise ValueError(msg)
|
|
180
|
+
view = self.__build_view(input_[0].type)
|
|
181
|
+
return view.dump_bulk(input_)
|
|
@@ -17,7 +17,6 @@ from .converter import (
|
|
|
17
17
|
)
|
|
18
18
|
from .filter import DefaultApiFilter
|
|
19
19
|
from .parser import DefaultParser
|
|
20
|
-
from .view import DefaultView
|
|
21
20
|
from ..core import DataSource
|
|
22
21
|
|
|
23
22
|
|
|
@@ -66,8 +65,7 @@ class _ConverterFactory:
|
|
|
66
65
|
Returns an instantiated `DataObjectConverter`.
|
|
67
66
|
"""
|
|
68
67
|
|
|
69
|
-
|
|
70
|
-
return DataObjectConverter(view)
|
|
68
|
+
return DataObjectConverter(self.__data_source, prefix=self.__prefix)
|
|
71
69
|
|
|
72
70
|
def json_converter_factory(self) -> JsonConverterFactory:
|
|
73
71
|
"""
|
|
@@ -87,6 +85,7 @@ def _get_client_factory(
|
|
|
87
85
|
token: Optional[str],
|
|
88
86
|
data_prefix: str,
|
|
89
87
|
retries: int,
|
|
88
|
+
status_forcelist: list[int],
|
|
90
89
|
merge_collections: bool | None,
|
|
91
90
|
) -> Callable[[], JsonApiClient]:
|
|
92
91
|
"""
|
|
@@ -99,6 +98,7 @@ def _get_client_factory(
|
|
|
99
98
|
token=token,
|
|
100
99
|
data_prefix=data_prefix,
|
|
101
100
|
retries=retries,
|
|
101
|
+
status_forcelist=status_forcelist,
|
|
102
102
|
merge_collections=merge_collections,
|
|
103
103
|
)
|
|
104
104
|
|
|
@@ -113,6 +113,7 @@ def create_api_datasource(
|
|
|
113
113
|
|
|
114
114
|
data_prefix: str = '/data',
|
|
115
115
|
retries: int = 5,
|
|
116
|
+
status_forcelist: Optional[list[int]] = None,
|
|
116
117
|
merge_collections: bool | None = None,
|
|
117
118
|
) -> ApiDataSource:
|
|
118
119
|
"""
|
|
@@ -127,6 +128,7 @@ def create_api_datasource(
|
|
|
127
128
|
token=token,
|
|
128
129
|
data_prefix=data_prefix,
|
|
129
130
|
retries=retries,
|
|
131
|
+
status_forcelist=status_forcelist,
|
|
130
132
|
merge_collections=merge_collections,
|
|
131
133
|
)
|
|
132
134
|
manager = _ConverterFactory(data_prefix)
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2022 Genome Research Ltd.
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: MIT
|
|
4
|
+
|
|
5
|
+
import urllib
|
|
6
|
+
from abc import ABC, abstractmethod
|
|
7
|
+
from datetime import date
|
|
8
|
+
from typing import Any, Dict, Iterable, List, Optional, Union
|
|
9
|
+
|
|
10
|
+
from ..core import DataObject
|
|
11
|
+
from ..core.requested_fields import ReqFieldsTree
|
|
12
|
+
|
|
13
|
+
DocumentMeta = Dict[str, Any]
|
|
14
|
+
DumpDict = Dict[str, Any]
|
|
15
|
+
DumpDictMany = List[DumpDict]
|
|
16
|
+
ResponseDict = Dict[str, Union[DumpDict, DumpDictMany]]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class View(ABC):
|
|
20
|
+
"""
|
|
21
|
+
Provides an MVC-esque View class. Can serialize both an individual
|
|
22
|
+
DataObject, as well as an Iterable of DataObject instances.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
@abstractmethod
|
|
26
|
+
def dump(
|
|
27
|
+
self,
|
|
28
|
+
data_object: DataObject,
|
|
29
|
+
document_meta: Optional[DocumentMeta] = None,
|
|
30
|
+
) -> ResponseDict:
|
|
31
|
+
"""
|
|
32
|
+
Create a JSON:API response for an individual DataObject result
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
@abstractmethod
|
|
36
|
+
def dump_bulk(
|
|
37
|
+
self,
|
|
38
|
+
data_objects: Iterable[DataObject],
|
|
39
|
+
document_meta: Optional[DocumentMeta] = None,
|
|
40
|
+
) -> ResponseDict:
|
|
41
|
+
"""
|
|
42
|
+
Create a JSON:API response for an Iterable of DataObject results
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
RelationshipDump = dict[str, dict[str, str]]
|
|
47
|
+
AllRelationshipsDump = dict[str, RelationshipDump]
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class DefaultView(View):
|
|
51
|
+
"""
|
|
52
|
+
Provides a default implementation of the View ABC.
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
def __init__(
|
|
56
|
+
self,
|
|
57
|
+
requested_tree: ReqFieldsTree,
|
|
58
|
+
prefix: str = '',
|
|
59
|
+
hop_limit: Optional[int] = None,
|
|
60
|
+
) -> None:
|
|
61
|
+
"""
|
|
62
|
+
Args:
|
|
63
|
+
|
|
64
|
+
- prefix - the URL prefix on which the
|
|
65
|
+
data blueprint is served
|
|
66
|
+
- hop_limit - the maximum recursion limit
|
|
67
|
+
on including related to-one
|
|
68
|
+
objects. Default no limit
|
|
69
|
+
- requested_tree - a tree data structure of the
|
|
70
|
+
requested fields for the query
|
|
71
|
+
"""
|
|
72
|
+
|
|
73
|
+
self.__prefix = prefix
|
|
74
|
+
self.__hop_limit = hop_limit
|
|
75
|
+
self.__requested_tree = requested_tree
|
|
76
|
+
|
|
77
|
+
def dump(
|
|
78
|
+
self,
|
|
79
|
+
data_object: DataObject,
|
|
80
|
+
document_meta: Optional[DocumentMeta] = None,
|
|
81
|
+
) -> ResponseDict:
|
|
82
|
+
response = {
|
|
83
|
+
'data': self.__dump_object(
|
|
84
|
+
data_object,
|
|
85
|
+
tree=self.__requested_tree,
|
|
86
|
+
),
|
|
87
|
+
}
|
|
88
|
+
if document_meta is not None:
|
|
89
|
+
response['meta'] = document_meta
|
|
90
|
+
return response
|
|
91
|
+
|
|
92
|
+
def dump_bulk(
|
|
93
|
+
self,
|
|
94
|
+
data_objects: Iterable[DataObject],
|
|
95
|
+
document_meta: Optional[DocumentMeta] = None,
|
|
96
|
+
) -> ResponseDict:
|
|
97
|
+
dumped = [
|
|
98
|
+
self.__dump_object(
|
|
99
|
+
data_object,
|
|
100
|
+
tree=self.__requested_tree,
|
|
101
|
+
)
|
|
102
|
+
for data_object in data_objects
|
|
103
|
+
]
|
|
104
|
+
response = {'data': dumped}
|
|
105
|
+
if document_meta is not None:
|
|
106
|
+
response['meta'] = document_meta
|
|
107
|
+
return response
|
|
108
|
+
|
|
109
|
+
def __dump_object(
|
|
110
|
+
self,
|
|
111
|
+
data_object: DataObject,
|
|
112
|
+
tree: ReqFieldsTree,
|
|
113
|
+
) -> DumpDict:
|
|
114
|
+
dump = {'type': data_object.type, 'id': data_object.id}
|
|
115
|
+
# Stub trees are created by requested_fields paths ending in ".id"
|
|
116
|
+
if not tree.is_stub:
|
|
117
|
+
self.__add_attributes(data_object, dump, tree)
|
|
118
|
+
if tree.has_relationships:
|
|
119
|
+
self.__add_relationships(data_object, dump, tree)
|
|
120
|
+
return dump
|
|
121
|
+
|
|
122
|
+
def __add_attributes(
|
|
123
|
+
self,
|
|
124
|
+
data_object: DataObject,
|
|
125
|
+
dump: DumpDict,
|
|
126
|
+
tree: ReqFieldsTree | None,
|
|
127
|
+
):
|
|
128
|
+
if tree and (attr_names := tree.attribute_names):
|
|
129
|
+
# Only add requested attributes
|
|
130
|
+
dump['attributes'] = self.__convert_attributes(
|
|
131
|
+
{name: getattr(data_object, name) for name in attr_names}
|
|
132
|
+
)
|
|
133
|
+
elif data_object.attributes:
|
|
134
|
+
# Default behaviour is to add all attributes
|
|
135
|
+
dump['attributes'] = self.__convert_attributes(data_object.attributes)
|
|
136
|
+
|
|
137
|
+
def __add_relationships(
|
|
138
|
+
self,
|
|
139
|
+
data_object: DataObject,
|
|
140
|
+
dump: DumpDict,
|
|
141
|
+
tree: ReqFieldsTree | None = None,
|
|
142
|
+
) -> DumpDict:
|
|
143
|
+
rel_dict = self.__dump_to_one_relationships(
|
|
144
|
+
data_object, tree
|
|
145
|
+
) | self.__dump_to_many_relationships(data_object, tree)
|
|
146
|
+
if rel_dict:
|
|
147
|
+
dump['relationships'] = rel_dict
|
|
148
|
+
|
|
149
|
+
def __dump_to_one_relationships(
|
|
150
|
+
self,
|
|
151
|
+
data_object: DataObject,
|
|
152
|
+
tree: ReqFieldsTree,
|
|
153
|
+
) -> RelationshipDump:
|
|
154
|
+
to_ones = {}
|
|
155
|
+
for name in tree.to_one_names():
|
|
156
|
+
if name in data_object._to_one_objects:
|
|
157
|
+
one_dump = None
|
|
158
|
+
if one := data_object._to_one_objects.get(name):
|
|
159
|
+
if sub_tree := tree.get_sub_tree(name):
|
|
160
|
+
one_dump = {'data': self.__dump_object(one, tree=sub_tree)}
|
|
161
|
+
else:
|
|
162
|
+
one_dump = {'data': {'type': one.type, 'id': one.id}}
|
|
163
|
+
to_ones[name] = one_dump
|
|
164
|
+
return to_ones
|
|
165
|
+
|
|
166
|
+
def __dump_to_many_relationships(
|
|
167
|
+
self,
|
|
168
|
+
data_object: DataObject,
|
|
169
|
+
tree: ReqFieldsTree,
|
|
170
|
+
) -> RelationshipDump:
|
|
171
|
+
quoted_id = urllib.parse.quote(str(data_object.id), safe='')
|
|
172
|
+
to_many = {}
|
|
173
|
+
for name in tree.to_many_names():
|
|
174
|
+
if sub_tree := tree.get_sub_tree(name):
|
|
175
|
+
to_many[name] = {
|
|
176
|
+
'data': [
|
|
177
|
+
self.__dump_object(x, tree=sub_tree) for x in getattr(data_object, name)
|
|
178
|
+
]
|
|
179
|
+
}
|
|
180
|
+
else:
|
|
181
|
+
link = f'{self.__prefix}/{data_object.type}/{quoted_id}/{name}'
|
|
182
|
+
to_many[name] = {'links': {'related': link}}
|
|
183
|
+
return to_many
|
|
184
|
+
|
|
185
|
+
def __convert_attributes(self, attributes: dict[str, Any]) -> dict[str, Any]:
|
|
186
|
+
return {k: self.__convert_value(v) for k, v in attributes.items()}
|
|
187
|
+
|
|
188
|
+
def __convert_value(self, __v: Any) -> Any:
|
|
189
|
+
if isinstance(__v, date):
|
|
190
|
+
# `datetime` is a subclass of `date`
|
|
191
|
+
return __v.isoformat()
|
|
192
|
+
return __v
|