dsp-tools 9.1.0.post11__py3-none-any.whl → 18.3.0.post13__py3-none-any.whl
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.
- dsp_tools/__init__.py +4 -0
- dsp_tools/cli/args.py +36 -0
- dsp_tools/cli/call_action.py +51 -231
- dsp_tools/cli/call_action_files_only.py +101 -0
- dsp_tools/cli/call_action_with_network.py +207 -0
- dsp_tools/cli/create_parsers.py +156 -58
- dsp_tools/cli/entry_point.py +56 -26
- dsp_tools/cli/utils.py +87 -0
- dsp_tools/clients/CLAUDE.md +420 -0
- dsp_tools/clients/authentication_client.py +14 -0
- dsp_tools/clients/authentication_client_live.py +66 -0
- dsp_tools/{utils → clients}/connection.py +2 -18
- dsp_tools/clients/connection_live.py +233 -0
- dsp_tools/clients/fuseki_metrics.py +60 -0
- dsp_tools/clients/group_user_clients.py +35 -0
- dsp_tools/clients/group_user_clients_live.py +181 -0
- dsp_tools/clients/legal_info_client.py +23 -0
- dsp_tools/clients/legal_info_client_live.py +132 -0
- dsp_tools/clients/list_client.py +49 -0
- dsp_tools/clients/list_client_live.py +166 -0
- dsp_tools/clients/metadata_client.py +24 -0
- dsp_tools/clients/metadata_client_live.py +47 -0
- dsp_tools/clients/ontology_clients.py +49 -0
- dsp_tools/clients/ontology_create_client_live.py +166 -0
- dsp_tools/clients/ontology_get_client_live.py +80 -0
- dsp_tools/clients/permissions_client.py +68 -0
- dsp_tools/clients/project_client.py +16 -0
- dsp_tools/clients/project_client_live.py +66 -0
- dsp_tools/commands/create/communicate_problems.py +24 -0
- dsp_tools/commands/create/create.py +134 -0
- dsp_tools/commands/create/create_on_server/cardinalities.py +111 -0
- dsp_tools/commands/create/create_on_server/classes.py +99 -0
- dsp_tools/commands/create/create_on_server/complete_ontologies.py +116 -0
- dsp_tools/commands/create/create_on_server/default_permissions.py +134 -0
- dsp_tools/commands/create/create_on_server/group_users.py +165 -0
- dsp_tools/commands/create/create_on_server/lists.py +163 -0
- dsp_tools/commands/create/create_on_server/mappers.py +12 -0
- dsp_tools/commands/create/create_on_server/onto_utils.py +74 -0
- dsp_tools/commands/create/create_on_server/ontology.py +52 -0
- dsp_tools/commands/create/create_on_server/project.py +68 -0
- dsp_tools/commands/create/create_on_server/properties.py +119 -0
- dsp_tools/commands/create/exceptions.py +29 -0
- dsp_tools/commands/create/lists_only.py +66 -0
- dsp_tools/commands/create/models/create_problems.py +87 -0
- dsp_tools/commands/create/models/parsed_ontology.py +88 -0
- dsp_tools/commands/create/models/parsed_project.py +81 -0
- dsp_tools/commands/create/models/rdf_ontology.py +12 -0
- dsp_tools/commands/create/models/server_project_info.py +100 -0
- dsp_tools/commands/create/parsing/parse_lists.py +45 -0
- dsp_tools/commands/create/parsing/parse_ontology.py +243 -0
- dsp_tools/commands/create/parsing/parse_project.py +149 -0
- dsp_tools/commands/create/parsing/parsing_utils.py +40 -0
- dsp_tools/commands/create/project_validate.py +595 -0
- dsp_tools/commands/create/serialisation/ontology.py +119 -0
- dsp_tools/commands/create/serialisation/project.py +44 -0
- dsp_tools/commands/excel2json/CLAUDE.md +101 -0
- dsp_tools/commands/excel2json/json_header.py +57 -23
- dsp_tools/commands/excel2json/{new_lists → lists}/compliance_checks.py +26 -26
- dsp_tools/commands/excel2json/{new_lists/make_new_lists.py → lists/make_lists.py} +19 -18
- dsp_tools/commands/excel2json/{new_lists → lists}/models/input_error.py +1 -12
- dsp_tools/commands/excel2json/{new_lists → lists}/models/serialise.py +9 -5
- dsp_tools/commands/excel2json/{new_lists → lists}/utils.py +4 -4
- dsp_tools/commands/excel2json/models/input_error.py +31 -11
- dsp_tools/commands/excel2json/models/json_header.py +53 -15
- dsp_tools/commands/excel2json/models/ontology.py +4 -3
- dsp_tools/commands/excel2json/{lists.py → old_lists.py} +26 -112
- dsp_tools/commands/excel2json/project.py +78 -34
- dsp_tools/commands/excel2json/properties.py +57 -36
- dsp_tools/commands/excel2json/resources.py +32 -12
- dsp_tools/commands/excel2json/utils.py +20 -1
- dsp_tools/commands/excel2xml/__init__.py +2 -2
- dsp_tools/commands/excel2xml/excel2xml_cli.py +7 -15
- dsp_tools/commands/excel2xml/excel2xml_lib.py +138 -493
- dsp_tools/commands/excel2xml/propertyelement.py +5 -5
- dsp_tools/commands/{project → get}/get.py +29 -13
- dsp_tools/commands/get/get_permissions.py +257 -0
- dsp_tools/commands/get/get_permissions_legacy.py +89 -0
- dsp_tools/commands/{project/models → get/legacy_models}/context.py +6 -6
- dsp_tools/commands/{project/models → get/legacy_models}/group.py +5 -10
- dsp_tools/commands/{project/models → get/legacy_models}/listnode.py +5 -35
- dsp_tools/commands/{project/models → get/legacy_models}/model.py +1 -1
- dsp_tools/commands/{project/models → get/legacy_models}/ontology.py +9 -14
- dsp_tools/commands/{project/models → get/legacy_models}/project.py +13 -6
- dsp_tools/commands/{project/models → get/legacy_models}/propertyclass.py +9 -16
- dsp_tools/commands/{project/models → get/legacy_models}/resourceclass.py +8 -46
- dsp_tools/commands/{project/models → get/legacy_models}/user.py +19 -60
- dsp_tools/commands/get/models/permissions_models.py +10 -0
- dsp_tools/commands/id2iri.py +20 -10
- dsp_tools/commands/ingest_xmlupload/bulk_ingest_client.py +81 -56
- dsp_tools/commands/ingest_xmlupload/create_resources/apply_ingest_id.py +4 -10
- dsp_tools/commands/ingest_xmlupload/create_resources/upload_xml.py +97 -37
- dsp_tools/commands/ingest_xmlupload/create_resources/user_information.py +2 -2
- dsp_tools/commands/ingest_xmlupload/ingest_files/ingest_files.py +9 -10
- dsp_tools/commands/ingest_xmlupload/upload_files/filechecker.py +3 -3
- dsp_tools/commands/ingest_xmlupload/upload_files/input_error.py +2 -10
- dsp_tools/commands/ingest_xmlupload/upload_files/upload_failures.py +12 -2
- dsp_tools/commands/ingest_xmlupload/upload_files/upload_files.py +8 -9
- dsp_tools/commands/resume_xmlupload/resume_xmlupload.py +18 -18
- dsp_tools/commands/start_stack.py +126 -77
- dsp_tools/commands/update_legal/CLAUDE.md +344 -0
- dsp_tools/commands/update_legal/__init__.py +0 -0
- dsp_tools/commands/update_legal/core.py +182 -0
- dsp_tools/commands/update_legal/csv_operations.py +135 -0
- dsp_tools/commands/update_legal/models.py +87 -0
- dsp_tools/commands/update_legal/xml_operations.py +247 -0
- dsp_tools/commands/validate_data/CLAUDE.md +159 -0
- dsp_tools/commands/validate_data/__init__.py +0 -0
- dsp_tools/commands/validate_data/constants.py +59 -0
- dsp_tools/commands/validate_data/mappers.py +143 -0
- dsp_tools/commands/validate_data/models/__init__.py +0 -0
- dsp_tools/commands/validate_data/models/api_responses.py +45 -0
- dsp_tools/commands/validate_data/models/input_problems.py +119 -0
- dsp_tools/commands/validate_data/models/rdf_like_data.py +117 -0
- dsp_tools/commands/validate_data/models/validation.py +106 -0
- dsp_tools/commands/validate_data/prepare_data/__init__.py +0 -0
- dsp_tools/commands/validate_data/prepare_data/get_rdf_like_data.py +296 -0
- dsp_tools/commands/validate_data/prepare_data/make_data_graph.py +91 -0
- dsp_tools/commands/validate_data/prepare_data/prepare_data.py +184 -0
- dsp_tools/commands/validate_data/process_validation_report/__init__.py +0 -0
- dsp_tools/commands/validate_data/process_validation_report/get_user_validation_message.py +358 -0
- dsp_tools/commands/validate_data/process_validation_report/query_validation_result.py +507 -0
- dsp_tools/commands/validate_data/process_validation_report/reformat_validation_results.py +150 -0
- dsp_tools/commands/validate_data/shacl_cli_validator.py +70 -0
- dsp_tools/commands/validate_data/sparql/__init__.py +0 -0
- dsp_tools/commands/{xml_validate/sparql/resource_shacl.py → validate_data/sparql/cardinality_shacl.py} +45 -47
- dsp_tools/commands/validate_data/sparql/construct_shacl.py +92 -0
- dsp_tools/commands/validate_data/sparql/legal_info_shacl.py +36 -0
- dsp_tools/commands/validate_data/sparql/value_shacl.py +357 -0
- dsp_tools/commands/validate_data/utils.py +59 -0
- dsp_tools/commands/validate_data/validate_data.py +283 -0
- dsp_tools/commands/validate_data/validation/__init__.py +0 -0
- dsp_tools/commands/validate_data/validation/check_duplicate_files.py +55 -0
- dsp_tools/commands/validate_data/validation/check_for_unknown_classes.py +67 -0
- dsp_tools/commands/validate_data/validation/get_validation_report.py +94 -0
- dsp_tools/commands/validate_data/validation/validate_ontology.py +107 -0
- dsp_tools/commands/xmlupload/CLAUDE.md +292 -0
- dsp_tools/commands/xmlupload/make_rdf_graph/__init__.py +0 -0
- dsp_tools/commands/xmlupload/make_rdf_graph/constants.py +63 -0
- dsp_tools/commands/xmlupload/make_rdf_graph/jsonld_utils.py +44 -0
- dsp_tools/commands/xmlupload/make_rdf_graph/make_file_value.py +77 -0
- dsp_tools/commands/xmlupload/make_rdf_graph/make_resource_and_values.py +114 -0
- dsp_tools/commands/xmlupload/make_rdf_graph/make_values.py +262 -0
- dsp_tools/commands/xmlupload/models/bitstream_info.py +18 -0
- dsp_tools/commands/xmlupload/models/formatted_text_value.py +0 -25
- dsp_tools/commands/xmlupload/models/ingest.py +56 -70
- dsp_tools/commands/xmlupload/models/input_problems.py +6 -14
- dsp_tools/commands/xmlupload/models/lookup_models.py +21 -0
- dsp_tools/commands/xmlupload/models/permission.py +0 -39
- dsp_tools/commands/xmlupload/models/{deserialise/xmlpermission.py → permissions_parsed.py} +2 -2
- dsp_tools/commands/xmlupload/models/processed/__init__.py +0 -0
- dsp_tools/commands/xmlupload/models/processed/file_values.py +29 -0
- dsp_tools/commands/xmlupload/models/processed/res.py +27 -0
- dsp_tools/commands/xmlupload/models/processed/values.py +101 -0
- dsp_tools/commands/xmlupload/models/rdf_models.py +26 -0
- dsp_tools/commands/xmlupload/models/upload_clients.py +3 -3
- dsp_tools/commands/xmlupload/models/upload_state.py +2 -4
- dsp_tools/commands/xmlupload/prepare_xml_input/__init__.py +0 -0
- dsp_tools/commands/xmlupload/{ark2iri.py → prepare_xml_input/ark2iri.py} +1 -1
- dsp_tools/commands/xmlupload/prepare_xml_input/get_processed_resources.py +252 -0
- dsp_tools/commands/xmlupload/{iiif_uri_validator.py → prepare_xml_input/iiif_uri_validator.py} +2 -14
- dsp_tools/commands/xmlupload/{list_client.py → prepare_xml_input/list_client.py} +15 -10
- dsp_tools/commands/xmlupload/prepare_xml_input/prepare_xml_input.py +67 -0
- dsp_tools/commands/xmlupload/prepare_xml_input/read_validate_xml_file.py +58 -0
- dsp_tools/commands/xmlupload/prepare_xml_input/transform_input_values.py +118 -0
- dsp_tools/commands/xmlupload/resource_create_client.py +7 -468
- dsp_tools/commands/xmlupload/richtext_id2iri.py +37 -0
- dsp_tools/commands/xmlupload/stash/{construct_and_analyze_graph.py → analyse_circular_reference_graph.py} +64 -157
- dsp_tools/commands/xmlupload/stash/create_info_for_graph.py +53 -0
- dsp_tools/commands/xmlupload/stash/graph_models.py +13 -8
- dsp_tools/commands/xmlupload/stash/stash_circular_references.py +48 -115
- dsp_tools/commands/xmlupload/stash/stash_models.py +4 -9
- dsp_tools/commands/xmlupload/stash/upload_stashed_resptr_props.py +34 -40
- dsp_tools/commands/xmlupload/stash/upload_stashed_xml_texts.py +98 -108
- dsp_tools/commands/xmlupload/upload_config.py +8 -0
- dsp_tools/commands/xmlupload/write_diagnostic_info.py +14 -9
- dsp_tools/commands/xmlupload/xmlupload.py +214 -192
- dsp_tools/config/__init__.py +0 -0
- dsp_tools/config/logger_config.py +69 -0
- dsp_tools/{utils → config}/warnings_config.py +4 -1
- dsp_tools/error/__init__.py +0 -0
- dsp_tools/error/custom_warnings.py +39 -0
- dsp_tools/error/exceptions.py +204 -0
- dsp_tools/error/problems.py +10 -0
- dsp_tools/error/xmllib_errors.py +20 -0
- dsp_tools/error/xmllib_warnings.py +54 -0
- dsp_tools/error/xmllib_warnings_util.py +159 -0
- dsp_tools/error/xsd_validation_error_msg.py +19 -0
- dsp_tools/legacy_models/__init__.py +0 -0
- dsp_tools/{models → legacy_models}/datetimestamp.py +7 -7
- dsp_tools/{models → legacy_models}/langstring.py +1 -1
- dsp_tools/{models → legacy_models}/projectContext.py +4 -4
- dsp_tools/resources/schema/data.xsd +108 -83
- dsp_tools/resources/schema/lists-only.json +4 -23
- dsp_tools/resources/schema/project.json +80 -35
- dsp_tools/resources/schema/properties-only.json +1 -4
- dsp_tools/resources/start-stack/docker-compose.override-host.j2 +11 -0
- dsp_tools/resources/start-stack/docker-compose.yml +34 -30
- dsp_tools/resources/start-stack/dsp-app-config.json +45 -0
- dsp_tools/resources/start-stack/dsp-app-config.override-host.j2 +26 -0
- dsp_tools/resources/validate_data/api-shapes-resource-cardinalities.ttl +191 -0
- dsp_tools/resources/validate_data/api-shapes.ttl +804 -0
- dsp_tools/resources/validate_data/shacl-cli-image.yml +4 -0
- dsp_tools/resources/validate_data/validate-ontology.ttl +99 -0
- dsp_tools/utils/ansi_colors.py +32 -0
- dsp_tools/utils/data_formats/__init__.py +0 -0
- dsp_tools/utils/{date_util.py → data_formats/date_util.py} +13 -1
- dsp_tools/utils/data_formats/iri_util.py +30 -0
- dsp_tools/utils/{shared.py → data_formats/shared.py} +1 -35
- dsp_tools/utils/{uri_util.py → data_formats/uri_util.py} +12 -2
- dsp_tools/utils/fuseki_bloating.py +63 -0
- dsp_tools/utils/json_parsing.py +22 -0
- dsp_tools/utils/rdf_constants.py +42 -0
- dsp_tools/utils/rdflib_utils.py +10 -0
- dsp_tools/utils/replace_id_with_iri.py +66 -0
- dsp_tools/utils/request_utils.py +238 -0
- dsp_tools/utils/xml_parsing/__init__.py +0 -0
- dsp_tools/utils/xml_parsing/get_lookups.py +32 -0
- dsp_tools/utils/xml_parsing/get_parsed_resources.py +325 -0
- dsp_tools/utils/xml_parsing/models/__init__.py +0 -0
- dsp_tools/utils/xml_parsing/models/parsed_resource.py +76 -0
- dsp_tools/utils/xml_parsing/parse_clean_validate_xml.py +137 -0
- dsp_tools/xmllib/CLAUDE.md +302 -0
- dsp_tools/xmllib/__init__.py +49 -0
- dsp_tools/xmllib/general_functions.py +877 -0
- dsp_tools/xmllib/internal/__init__.py +0 -0
- dsp_tools/xmllib/internal/checkers.py +162 -0
- dsp_tools/xmllib/internal/circumvent_circular_imports.py +36 -0
- dsp_tools/xmllib/internal/constants.py +46 -0
- dsp_tools/xmllib/internal/input_converters.py +155 -0
- dsp_tools/xmllib/internal/serialise_file_value.py +57 -0
- dsp_tools/xmllib/internal/serialise_resource.py +177 -0
- dsp_tools/xmllib/internal/serialise_values.py +152 -0
- dsp_tools/xmllib/internal/type_aliases.py +11 -0
- dsp_tools/xmllib/models/config_options.py +28 -0
- dsp_tools/xmllib/models/date_formats.py +48 -0
- dsp_tools/xmllib/models/dsp_base_resources.py +1380 -400
- dsp_tools/xmllib/models/internal/__init__.py +0 -0
- dsp_tools/xmllib/models/internal/file_values.py +172 -0
- dsp_tools/xmllib/models/internal/geometry.py +162 -0
- dsp_tools/xmllib/models/{migration_metadata.py → internal/migration_metadata.py} +14 -10
- dsp_tools/xmllib/models/internal/serialise_permissions.py +66 -0
- dsp_tools/xmllib/models/internal/values.py +342 -0
- dsp_tools/xmllib/models/licenses/__init__.py +0 -0
- dsp_tools/xmllib/models/licenses/other.py +59 -0
- dsp_tools/xmllib/models/licenses/recommended.py +107 -0
- dsp_tools/xmllib/models/permissions.py +41 -0
- dsp_tools/xmllib/models/res.py +1782 -0
- dsp_tools/xmllib/models/root.py +313 -26
- dsp_tools/xmllib/value_checkers.py +310 -47
- dsp_tools/xmllib/value_converters.py +765 -8
- dsp_tools-18.3.0.post13.dist-info/METADATA +90 -0
- dsp_tools-18.3.0.post13.dist-info/RECORD +286 -0
- dsp_tools-18.3.0.post13.dist-info/WHEEL +4 -0
- {dsp_tools-9.1.0.post11.dist-info → dsp_tools-18.3.0.post13.dist-info}/entry_points.txt +1 -0
- dsp_tools/commands/project/create/project_create.py +0 -1107
- dsp_tools/commands/project/create/project_create_lists.py +0 -204
- dsp_tools/commands/project/create/project_validate.py +0 -453
- dsp_tools/commands/project/models/project_definition.py +0 -12
- dsp_tools/commands/rosetta.py +0 -124
- dsp_tools/commands/template.py +0 -30
- dsp_tools/commands/xml_validate/api_connection.py +0 -122
- dsp_tools/commands/xml_validate/deserialise_input.py +0 -135
- dsp_tools/commands/xml_validate/make_data_rdf.py +0 -193
- dsp_tools/commands/xml_validate/models/data_deserialised.py +0 -108
- dsp_tools/commands/xml_validate/models/data_rdf.py +0 -214
- dsp_tools/commands/xml_validate/models/input_problems.py +0 -191
- dsp_tools/commands/xml_validate/models/validation.py +0 -29
- dsp_tools/commands/xml_validate/reformat_validaton_result.py +0 -89
- dsp_tools/commands/xml_validate/sparql/construct_shapes.py +0 -16
- dsp_tools/commands/xml_validate/xml_validate.py +0 -151
- dsp_tools/commands/xmlupload/check_consistency_with_ontology.py +0 -253
- dsp_tools/commands/xmlupload/models/deserialise/deserialise_value.py +0 -236
- dsp_tools/commands/xmlupload/models/deserialise/xmlresource.py +0 -171
- dsp_tools/commands/xmlupload/models/namespace_context.py +0 -39
- dsp_tools/commands/xmlupload/models/ontology_lookup_models.py +0 -161
- dsp_tools/commands/xmlupload/models/ontology_problem_models.py +0 -178
- dsp_tools/commands/xmlupload/models/serialise/jsonld_serialiser.py +0 -40
- dsp_tools/commands/xmlupload/models/serialise/serialise_value.py +0 -51
- dsp_tools/commands/xmlupload/ontology_client.py +0 -92
- dsp_tools/commands/xmlupload/project_client.py +0 -91
- dsp_tools/commands/xmlupload/read_validate_xml_file.py +0 -99
- dsp_tools/models/custom_warnings.py +0 -31
- dsp_tools/models/exceptions.py +0 -90
- dsp_tools/resources/0100-template-repo/template.json +0 -45
- dsp_tools/resources/0100-template-repo/template.xml +0 -27
- dsp_tools/resources/start-stack/docker-compose-validation.yml +0 -5
- dsp_tools/resources/start-stack/start-stack-config.yml +0 -4
- dsp_tools/resources/xml_validate/api-shapes.ttl +0 -411
- dsp_tools/resources/xml_validate/replace_namespace.xslt +0 -61
- dsp_tools/utils/connection_live.py +0 -383
- dsp_tools/utils/iri_util.py +0 -14
- dsp_tools/utils/logger_config.py +0 -41
- dsp_tools/utils/set_encoder.py +0 -20
- dsp_tools/utils/xml_utils.py +0 -145
- dsp_tools/utils/xml_validation.py +0 -197
- dsp_tools/utils/xml_validation_models.py +0 -68
- dsp_tools/xmllib/models/file_values.py +0 -78
- dsp_tools/xmllib/models/resource.py +0 -415
- dsp_tools/xmllib/models/values.py +0 -428
- dsp_tools-9.1.0.post11.dist-info/METADATA +0 -130
- dsp_tools-9.1.0.post11.dist-info/RECORD +0 -167
- dsp_tools-9.1.0.post11.dist-info/WHEEL +0 -4
- dsp_tools-9.1.0.post11.dist-info/licenses/LICENSE +0 -674
- /dsp_tools/{commands/excel2json/new_lists → clients}/__init__.py +0 -0
- /dsp_tools/commands/{excel2json/new_lists/models → create}/__init__.py +0 -0
- /dsp_tools/commands/{project → create/create_on_server}/__init__.py +0 -0
- /dsp_tools/commands/{project/create → create/models}/__init__.py +0 -0
- /dsp_tools/commands/{project/models → create/parsing}/__init__.py +0 -0
- /dsp_tools/commands/{xml_validate → create/serialisation}/__init__.py +0 -0
- /dsp_tools/commands/{xml_validate/models → excel2json/lists}/__init__.py +0 -0
- /dsp_tools/commands/{xml_validate/sparql → excel2json/lists/models}/__init__.py +0 -0
- /dsp_tools/commands/excel2json/{new_lists → lists}/models/deserialise.py +0 -0
- /dsp_tools/commands/{xmlupload/models/deserialise → get}/__init__.py +0 -0
- /dsp_tools/commands/{xmlupload/models/serialise → get/legacy_models}/__init__.py +0 -0
- /dsp_tools/commands/{project/models → get/legacy_models}/helpers.py +0 -0
- /dsp_tools/{models → commands/get/models}/__init__.py +0 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
|
|
5
|
+
from dsp_tools.commands.xmlupload.models.permission import Permissions
|
|
6
|
+
from dsp_tools.commands.xmlupload.models.processed.file_values import ProcessedFileValue
|
|
7
|
+
from dsp_tools.commands.xmlupload.models.processed.file_values import ProcessedIIIFUri
|
|
8
|
+
from dsp_tools.commands.xmlupload.models.processed.values import ProcessedValue
|
|
9
|
+
from dsp_tools.legacy_models.datetimestamp import DateTimeStamp
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass
|
|
13
|
+
class ProcessedResource:
|
|
14
|
+
res_id: str
|
|
15
|
+
type_iri: str
|
|
16
|
+
label: str
|
|
17
|
+
permissions: Permissions | None
|
|
18
|
+
values: list[ProcessedValue]
|
|
19
|
+
file_value: ProcessedFileValue | None = None
|
|
20
|
+
iiif_uri: ProcessedIIIFUri | None = None
|
|
21
|
+
migration_metadata: MigrationMetadata | None = None
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass
|
|
25
|
+
class MigrationMetadata:
|
|
26
|
+
iri_str: str | None
|
|
27
|
+
creation_date: DateTimeStamp | None
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Union
|
|
5
|
+
|
|
6
|
+
from dsp_tools.commands.xmlupload.models.formatted_text_value import FormattedTextValue
|
|
7
|
+
from dsp_tools.commands.xmlupload.models.permission import Permissions
|
|
8
|
+
from dsp_tools.utils.data_formats.date_util import Date
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass
|
|
12
|
+
class IntervalFloats:
|
|
13
|
+
start: float
|
|
14
|
+
end: float
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
type ProcessedValueTypes = Union[bool, str, float, int, FormattedTextValue, Date, IntervalFloats]
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@dataclass
|
|
21
|
+
class ProcessedValue:
|
|
22
|
+
value: ProcessedValueTypes
|
|
23
|
+
prop_iri: str
|
|
24
|
+
comment: str | None
|
|
25
|
+
permissions: Permissions | None
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@dataclass
|
|
29
|
+
class ProcessedBoolean(ProcessedValue):
|
|
30
|
+
value: bool
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@dataclass
|
|
34
|
+
class ProcessedColor(ProcessedValue):
|
|
35
|
+
value: str
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@dataclass
|
|
39
|
+
class ProcessedDate(ProcessedValue):
|
|
40
|
+
value: Date
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@dataclass
|
|
44
|
+
class ProcessedDecimal(ProcessedValue):
|
|
45
|
+
value: float
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@dataclass
|
|
49
|
+
class ProcessedGeoname(ProcessedValue):
|
|
50
|
+
value: str
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@dataclass
|
|
54
|
+
class ProcessedGeometry(ProcessedValue):
|
|
55
|
+
value: str
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@dataclass
|
|
59
|
+
class ProcessedInt(ProcessedValue):
|
|
60
|
+
value: int
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@dataclass
|
|
64
|
+
class ProcessedInterval(ProcessedValue):
|
|
65
|
+
value: IntervalFloats
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
@dataclass
|
|
69
|
+
class ProcessedLink(ProcessedValue):
|
|
70
|
+
value: str
|
|
71
|
+
value_uuid: str
|
|
72
|
+
|
|
73
|
+
def __post_init__(self) -> None:
|
|
74
|
+
self.prop_iri = f"{self.prop_iri}Value"
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
@dataclass
|
|
78
|
+
class ProcessedList(ProcessedValue):
|
|
79
|
+
value: str
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
@dataclass
|
|
83
|
+
class ProcessedSimpleText(ProcessedValue):
|
|
84
|
+
value: str
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
@dataclass
|
|
88
|
+
class ProcessedRichtext(ProcessedValue):
|
|
89
|
+
value: FormattedTextValue
|
|
90
|
+
resource_references: set[str]
|
|
91
|
+
value_uuid: str
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
@dataclass
|
|
95
|
+
class ProcessedTime(ProcessedValue):
|
|
96
|
+
value: str
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
@dataclass
|
|
100
|
+
class ProcessedUri(ProcessedValue):
|
|
101
|
+
value: str
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
|
|
5
|
+
from rdflib import URIRef
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@dataclass
|
|
9
|
+
class RDFPropTypeInfo:
|
|
10
|
+
knora_type: URIRef
|
|
11
|
+
knora_prop: URIRef
|
|
12
|
+
xsd_type: URIRef | None = None
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclass
|
|
16
|
+
class AbstractFileValue:
|
|
17
|
+
value: str
|
|
18
|
+
metadata: FileValueMetadata
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@dataclass
|
|
22
|
+
class FileValueMetadata:
|
|
23
|
+
license_iri: str
|
|
24
|
+
copyright_holder: str
|
|
25
|
+
authorships: list[str]
|
|
26
|
+
permissions: str | None
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
from dataclasses import dataclass
|
|
2
2
|
|
|
3
|
-
from dsp_tools.
|
|
3
|
+
from dsp_tools.clients.legal_info_client import LegalInfoClient
|
|
4
4
|
from dsp_tools.commands.xmlupload.models.ingest import AssetClient
|
|
5
|
-
from dsp_tools.commands.xmlupload.
|
|
5
|
+
from dsp_tools.commands.xmlupload.prepare_xml_input.list_client import ListClient
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
@dataclass(frozen=True)
|
|
@@ -10,5 +10,5 @@ class UploadClients:
|
|
|
10
10
|
"""Holds all the clients needed for the upload process."""
|
|
11
11
|
|
|
12
12
|
asset_client: AssetClient
|
|
13
|
-
project_client: ProjectClient
|
|
14
13
|
list_client: ListClient
|
|
14
|
+
legal_info_client: LegalInfoClient
|
|
@@ -2,8 +2,7 @@ from dataclasses import dataclass
|
|
|
2
2
|
from dataclasses import field
|
|
3
3
|
|
|
4
4
|
from dsp_tools.commands.xmlupload.iri_resolver import IriResolver
|
|
5
|
-
from dsp_tools.commands.xmlupload.models.
|
|
6
|
-
from dsp_tools.commands.xmlupload.models.permission import Permissions
|
|
5
|
+
from dsp_tools.commands.xmlupload.models.processed.res import ProcessedResource
|
|
7
6
|
from dsp_tools.commands.xmlupload.stash.stash_models import Stash
|
|
8
7
|
from dsp_tools.commands.xmlupload.upload_config import UploadConfig
|
|
9
8
|
|
|
@@ -14,9 +13,8 @@ class UploadState:
|
|
|
14
13
|
Save the state of an xmlupload, so that after an interruption, it can be resumed.
|
|
15
14
|
"""
|
|
16
15
|
|
|
17
|
-
pending_resources: list[
|
|
16
|
+
pending_resources: list[ProcessedResource]
|
|
18
17
|
pending_stash: Stash | None
|
|
19
18
|
config: UploadConfig
|
|
20
|
-
permissions_lookup: dict[str, Permissions]
|
|
21
19
|
failed_uploads: list[str] = field(default_factory=list)
|
|
22
20
|
iri_resolver: IriResolver = field(default_factory=IriResolver)
|
|
File without changes
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
from typing import cast
|
|
2
|
+
from uuid import uuid4
|
|
3
|
+
|
|
4
|
+
from loguru import logger
|
|
5
|
+
from tqdm import tqdm
|
|
6
|
+
|
|
7
|
+
from dsp_tools.commands.xmlupload.models.lookup_models import XmlReferenceLookups
|
|
8
|
+
from dsp_tools.commands.xmlupload.models.permission import Permissions
|
|
9
|
+
from dsp_tools.commands.xmlupload.models.processed.file_values import ProcessedFileMetadata
|
|
10
|
+
from dsp_tools.commands.xmlupload.models.processed.file_values import ProcessedFileValue
|
|
11
|
+
from dsp_tools.commands.xmlupload.models.processed.file_values import ProcessedIIIFUri
|
|
12
|
+
from dsp_tools.commands.xmlupload.models.processed.res import MigrationMetadata
|
|
13
|
+
from dsp_tools.commands.xmlupload.models.processed.res import ProcessedResource
|
|
14
|
+
from dsp_tools.commands.xmlupload.models.processed.values import ProcessedBoolean
|
|
15
|
+
from dsp_tools.commands.xmlupload.models.processed.values import ProcessedColor
|
|
16
|
+
from dsp_tools.commands.xmlupload.models.processed.values import ProcessedDate
|
|
17
|
+
from dsp_tools.commands.xmlupload.models.processed.values import ProcessedDecimal
|
|
18
|
+
from dsp_tools.commands.xmlupload.models.processed.values import ProcessedGeometry
|
|
19
|
+
from dsp_tools.commands.xmlupload.models.processed.values import ProcessedGeoname
|
|
20
|
+
from dsp_tools.commands.xmlupload.models.processed.values import ProcessedInt
|
|
21
|
+
from dsp_tools.commands.xmlupload.models.processed.values import ProcessedInterval
|
|
22
|
+
from dsp_tools.commands.xmlupload.models.processed.values import ProcessedLink
|
|
23
|
+
from dsp_tools.commands.xmlupload.models.processed.values import ProcessedList
|
|
24
|
+
from dsp_tools.commands.xmlupload.models.processed.values import ProcessedRichtext
|
|
25
|
+
from dsp_tools.commands.xmlupload.models.processed.values import ProcessedSimpleText
|
|
26
|
+
from dsp_tools.commands.xmlupload.models.processed.values import ProcessedTime
|
|
27
|
+
from dsp_tools.commands.xmlupload.models.processed.values import ProcessedUri
|
|
28
|
+
from dsp_tools.commands.xmlupload.models.processed.values import ProcessedValue
|
|
29
|
+
from dsp_tools.commands.xmlupload.prepare_xml_input.ark2iri import convert_ark_v0_to_resource_iri
|
|
30
|
+
from dsp_tools.commands.xmlupload.prepare_xml_input.transform_input_values import TypeTransformerMapper
|
|
31
|
+
from dsp_tools.commands.xmlupload.prepare_xml_input.transform_input_values import assert_is_string
|
|
32
|
+
from dsp_tools.commands.xmlupload.prepare_xml_input.transform_input_values import assert_is_tuple
|
|
33
|
+
from dsp_tools.commands.xmlupload.prepare_xml_input.transform_input_values import transform_boolean
|
|
34
|
+
from dsp_tools.commands.xmlupload.prepare_xml_input.transform_input_values import transform_date
|
|
35
|
+
from dsp_tools.commands.xmlupload.prepare_xml_input.transform_input_values import transform_decimal
|
|
36
|
+
from dsp_tools.commands.xmlupload.prepare_xml_input.transform_input_values import transform_geometry
|
|
37
|
+
from dsp_tools.commands.xmlupload.prepare_xml_input.transform_input_values import transform_integer
|
|
38
|
+
from dsp_tools.commands.xmlupload.prepare_xml_input.transform_input_values import transform_interval
|
|
39
|
+
from dsp_tools.commands.xmlupload.prepare_xml_input.transform_input_values import transform_richtext
|
|
40
|
+
from dsp_tools.commands.xmlupload.prepare_xml_input.transform_input_values import transform_simpletext
|
|
41
|
+
from dsp_tools.commands.xmlupload.richtext_id2iri import find_internal_ids
|
|
42
|
+
from dsp_tools.error.exceptions import XmlUploadAuthorshipsNotFoundError
|
|
43
|
+
from dsp_tools.error.exceptions import XmlUploadListNodeNotFoundError
|
|
44
|
+
from dsp_tools.error.exceptions import XmlUploadPermissionsNotFoundError
|
|
45
|
+
from dsp_tools.legacy_models.datetimestamp import DateTimeStamp
|
|
46
|
+
from dsp_tools.utils.xml_parsing.models.parsed_resource import KnoraValueType
|
|
47
|
+
from dsp_tools.utils.xml_parsing.models.parsed_resource import ParsedFileValue
|
|
48
|
+
from dsp_tools.utils.xml_parsing.models.parsed_resource import ParsedFileValueMetadata
|
|
49
|
+
from dsp_tools.utils.xml_parsing.models.parsed_resource import ParsedMigrationMetadata
|
|
50
|
+
from dsp_tools.utils.xml_parsing.models.parsed_resource import ParsedResource
|
|
51
|
+
from dsp_tools.utils.xml_parsing.models.parsed_resource import ParsedValue
|
|
52
|
+
|
|
53
|
+
TYPE_TRANSFORMER_MAPPER: dict[KnoraValueType, TypeTransformerMapper] = {
|
|
54
|
+
KnoraValueType.BOOLEAN_VALUE: TypeTransformerMapper(ProcessedBoolean, transform_boolean),
|
|
55
|
+
KnoraValueType.COLOR_VALUE: TypeTransformerMapper(ProcessedColor, assert_is_string),
|
|
56
|
+
KnoraValueType.DECIMAL_VALUE: TypeTransformerMapper(ProcessedDecimal, transform_decimal),
|
|
57
|
+
KnoraValueType.DATE_VALUE: TypeTransformerMapper(ProcessedDate, transform_date),
|
|
58
|
+
KnoraValueType.GEOM_VALUE: TypeTransformerMapper(ProcessedGeometry, transform_geometry),
|
|
59
|
+
KnoraValueType.GEONAME_VALUE: TypeTransformerMapper(ProcessedGeoname, assert_is_string),
|
|
60
|
+
KnoraValueType.INT_VALUE: TypeTransformerMapper(ProcessedInt, transform_integer),
|
|
61
|
+
KnoraValueType.INTERVAL_VALUE: TypeTransformerMapper(ProcessedInterval, transform_interval),
|
|
62
|
+
KnoraValueType.TIME_VALUE: TypeTransformerMapper(ProcessedTime, assert_is_string),
|
|
63
|
+
KnoraValueType.SIMPLETEXT_VALUE: TypeTransformerMapper(ProcessedSimpleText, transform_simpletext),
|
|
64
|
+
KnoraValueType.URI_VALUE: TypeTransformerMapper(ProcessedUri, assert_is_string),
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def get_processed_resources(
|
|
69
|
+
resources: list[ParsedResource], lookups: XmlReferenceLookups, is_on_prod_like_server: bool
|
|
70
|
+
) -> list[ProcessedResource]:
|
|
71
|
+
logger.debug("Transform ParsedResource into ProcessedResource")
|
|
72
|
+
progress_bar = tqdm(resources, desc="Preparing data for upload", dynamic_ncols=True)
|
|
73
|
+
return [_get_one_resource(res, lookups, is_on_prod_like_server) for res in progress_bar]
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _get_one_resource(
|
|
77
|
+
resource: ParsedResource, lookups: XmlReferenceLookups, is_on_prod_like_server: bool
|
|
78
|
+
) -> ProcessedResource:
|
|
79
|
+
permissions = _resolve_permission(resource.permissions_id, lookups.permissions)
|
|
80
|
+
values = [_get_one_processed_value(val, lookups) for val in resource.values]
|
|
81
|
+
migration_metadata = None
|
|
82
|
+
file_val, iiif_uri = _resolve_file_value(resource, lookups, is_on_prod_like_server)
|
|
83
|
+
if resource.migration_metadata:
|
|
84
|
+
migration_metadata = _get_resource_migration_metadata(resource.migration_metadata)
|
|
85
|
+
return ProcessedResource(
|
|
86
|
+
res_id=resource.res_id,
|
|
87
|
+
type_iri=resource.res_type,
|
|
88
|
+
label=resource.label,
|
|
89
|
+
permissions=permissions,
|
|
90
|
+
values=values,
|
|
91
|
+
file_value=file_val,
|
|
92
|
+
iiif_uri=iiif_uri,
|
|
93
|
+
migration_metadata=migration_metadata,
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def _get_resource_migration_metadata(metadata: ParsedMigrationMetadata) -> MigrationMetadata:
|
|
98
|
+
res_iri = metadata.iri
|
|
99
|
+
# ARK takes precedence over the IRI,
|
|
100
|
+
# but must be transformed into an IRI as it is only for external reference and not consistent with a DB IRI
|
|
101
|
+
if metadata.ark:
|
|
102
|
+
res_iri = convert_ark_v0_to_resource_iri(metadata.ark)
|
|
103
|
+
date = DateTimeStamp(metadata.creation_date) if metadata.creation_date else None
|
|
104
|
+
return MigrationMetadata(res_iri, date)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def _resolve_file_value(
|
|
108
|
+
resource: ParsedResource, lookups: XmlReferenceLookups, is_on_prod_like_server: bool
|
|
109
|
+
) -> tuple[None | ProcessedFileValue, None | ProcessedIIIFUri]:
|
|
110
|
+
file_val, iiif_uri = None, None
|
|
111
|
+
if not resource.file_value:
|
|
112
|
+
return file_val, iiif_uri
|
|
113
|
+
|
|
114
|
+
if is_on_prod_like_server:
|
|
115
|
+
metadata = _get_file_metadata(resource.file_value.metadata, lookups)
|
|
116
|
+
else:
|
|
117
|
+
metadata = _get_file_metadata_for_test_environments(resource.file_value.metadata, lookups)
|
|
118
|
+
if resource.file_value.value_type == KnoraValueType.STILL_IMAGE_IIIF:
|
|
119
|
+
iiif_uri = _get_iiif_uri_value(resource.file_value, metadata)
|
|
120
|
+
else:
|
|
121
|
+
file_val = _get_file_value(
|
|
122
|
+
val=resource.file_value, metadata=metadata, res_id=resource.res_id, res_label=resource.label
|
|
123
|
+
)
|
|
124
|
+
return file_val, iiif_uri
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def _get_file_value(
|
|
128
|
+
val: ParsedFileValue, metadata: ProcessedFileMetadata, res_id: str, res_label: str
|
|
129
|
+
) -> ProcessedFileValue:
|
|
130
|
+
file_type = cast(KnoraValueType, val.value_type)
|
|
131
|
+
file_val = assert_is_string(val.value)
|
|
132
|
+
return ProcessedFileValue(
|
|
133
|
+
value=file_val,
|
|
134
|
+
file_type=file_type,
|
|
135
|
+
metadata=metadata,
|
|
136
|
+
res_id=res_id,
|
|
137
|
+
res_label=res_label,
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def _get_iiif_uri_value(iiif_uri: ParsedFileValue, metadata: ProcessedFileMetadata) -> ProcessedIIIFUri:
|
|
142
|
+
file_val = assert_is_string(iiif_uri.value)
|
|
143
|
+
return ProcessedIIIFUri(file_val, metadata)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def _get_file_metadata(file_metadata: ParsedFileValueMetadata, lookups: XmlReferenceLookups) -> ProcessedFileMetadata:
|
|
147
|
+
license_iri = assert_is_string(file_metadata.license_iri)
|
|
148
|
+
copyright_holder = assert_is_string(file_metadata.copyright_holder)
|
|
149
|
+
auth_id = assert_is_string(file_metadata.authorship_id)
|
|
150
|
+
authorships = _resolve_authorship(auth_id, lookups.authorships)
|
|
151
|
+
permissions = _resolve_permission(file_metadata.permissions_id, lookups.permissions)
|
|
152
|
+
return ProcessedFileMetadata(
|
|
153
|
+
license_iri=license_iri,
|
|
154
|
+
copyright_holder=copyright_holder,
|
|
155
|
+
authorships=authorships,
|
|
156
|
+
permissions=permissions,
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def _get_file_metadata_for_test_environments(
|
|
161
|
+
metadata: ParsedFileValueMetadata, lookups: XmlReferenceLookups
|
|
162
|
+
) -> ProcessedFileMetadata:
|
|
163
|
+
lic_iri = metadata.license_iri or "http://rdfh.ch/licenses/unknown"
|
|
164
|
+
copy_right = metadata.copyright_holder if metadata.copyright_holder else "DUMMY"
|
|
165
|
+
if not metadata.authorship_id:
|
|
166
|
+
authorship = ["DUMMY"]
|
|
167
|
+
else:
|
|
168
|
+
authorship = _resolve_authorship(metadata.authorship_id, lookups.authorships)
|
|
169
|
+
permissions = _resolve_permission(metadata.permissions_id, lookups.permissions)
|
|
170
|
+
return ProcessedFileMetadata(
|
|
171
|
+
license_iri=lic_iri,
|
|
172
|
+
copyright_holder=copy_right,
|
|
173
|
+
authorships=authorship,
|
|
174
|
+
permissions=permissions,
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def _resolve_authorship(authorship_id: str, lookup: dict[str, list[str]]) -> list[str]:
|
|
179
|
+
if not (found := lookup.get(authorship_id)):
|
|
180
|
+
raise XmlUploadAuthorshipsNotFoundError(f"Could not find authorships for value: {authorship_id}")
|
|
181
|
+
return found
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def _get_one_processed_value(val: ParsedValue, lookups: XmlReferenceLookups) -> ProcessedValue:
|
|
185
|
+
match val.value_type:
|
|
186
|
+
case KnoraValueType.LIST_VALUE:
|
|
187
|
+
return _get_list_value(val, lookups)
|
|
188
|
+
case KnoraValueType.LINK_VALUE:
|
|
189
|
+
return _get_link_value(val, lookups)
|
|
190
|
+
case KnoraValueType.RICHTEXT_VALUE:
|
|
191
|
+
return _get_richtext_value(val, lookups)
|
|
192
|
+
case _ as val_type:
|
|
193
|
+
transformation_mapper = TYPE_TRANSFORMER_MAPPER[val_type]
|
|
194
|
+
return _get_generic_value(val=val, lookups=lookups, transformation_mapper=transformation_mapper)
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def _get_generic_value(
|
|
198
|
+
val: ParsedValue, lookups: XmlReferenceLookups, transformation_mapper: TypeTransformerMapper
|
|
199
|
+
) -> ProcessedValue:
|
|
200
|
+
transformed_value = transformation_mapper.val_transformer(val.value)
|
|
201
|
+
permission_val = _resolve_permission(val.permissions_id, lookups.permissions)
|
|
202
|
+
return transformation_mapper.val_type(transformed_value, val.prop_name, val.comment, permission_val)
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
def _get_link_value(val: ParsedValue, lookups: XmlReferenceLookups) -> ProcessedValue:
|
|
206
|
+
transformed_value = assert_is_string(val.value)
|
|
207
|
+
permission_val = _resolve_permission(val.permissions_id, lookups.permissions)
|
|
208
|
+
link_val: ProcessedValue = ProcessedLink(
|
|
209
|
+
value=transformed_value,
|
|
210
|
+
prop_iri=val.prop_name,
|
|
211
|
+
comment=val.comment,
|
|
212
|
+
permissions=permission_val,
|
|
213
|
+
value_uuid=str(uuid4()),
|
|
214
|
+
)
|
|
215
|
+
return link_val
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def _get_list_value(val: ParsedValue, lookups: XmlReferenceLookups) -> ProcessedValue:
|
|
219
|
+
tuple_val = assert_is_tuple(val.value)
|
|
220
|
+
if not (list_iri := lookups.listnodes.get(tuple_val)):
|
|
221
|
+
raise XmlUploadListNodeNotFoundError(f"Could not find list IRI for value: {tuple_val}")
|
|
222
|
+
permission_val = _resolve_permission(val.permissions_id, lookups.permissions)
|
|
223
|
+
list_val: ProcessedValue = ProcessedList(
|
|
224
|
+
value=list_iri,
|
|
225
|
+
prop_iri=val.prop_name,
|
|
226
|
+
comment=val.comment,
|
|
227
|
+
permissions=permission_val,
|
|
228
|
+
)
|
|
229
|
+
return list_val
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
def _get_richtext_value(val: ParsedValue, lookups: XmlReferenceLookups) -> ProcessedValue:
|
|
233
|
+
transformed_value = transform_richtext(val.value)
|
|
234
|
+
permission_val = _resolve_permission(val.permissions_id, lookups.permissions)
|
|
235
|
+
richtext: ProcessedValue = ProcessedRichtext(
|
|
236
|
+
value=transformed_value,
|
|
237
|
+
prop_iri=val.prop_name,
|
|
238
|
+
comment=val.comment,
|
|
239
|
+
permissions=permission_val,
|
|
240
|
+
resource_references=find_internal_ids(transformed_value.xmlstr),
|
|
241
|
+
value_uuid=str(uuid4()),
|
|
242
|
+
)
|
|
243
|
+
return richtext
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
def _resolve_permission(permissions: str | None, permissions_lookup: dict[str, Permissions]) -> Permissions | None:
|
|
247
|
+
"""Resolve the permission into a string that can be sent to the API."""
|
|
248
|
+
if permissions:
|
|
249
|
+
if not (per := permissions_lookup.get(permissions)):
|
|
250
|
+
raise XmlUploadPermissionsNotFoundError(f"Could not find permissions for value: {permissions}")
|
|
251
|
+
return per
|
|
252
|
+
return None
|
dsp_tools/commands/xmlupload/{iiif_uri_validator.py → prepare_xml_input/iiif_uri_validator.py}
RENAMED
|
@@ -2,25 +2,15 @@ from dataclasses import dataclass
|
|
|
2
2
|
|
|
3
3
|
import requests
|
|
4
4
|
|
|
5
|
-
from dsp_tools.commands.xmlupload.models.input_problems import AllIIIFUriProblems
|
|
6
5
|
from dsp_tools.commands.xmlupload.models.input_problems import IIIFUriProblem
|
|
7
|
-
from dsp_tools.utils.uri_util import is_iiif_uri
|
|
6
|
+
from dsp_tools.utils.data_formats.uri_util import is_iiif_uri
|
|
8
7
|
|
|
9
8
|
|
|
10
9
|
@dataclass(frozen=True)
|
|
11
10
|
class IIIFUriValidator:
|
|
12
11
|
"""Client handling communication with external IIIF-servers to do a health check."""
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
def validate(self) -> AllIIIFUriProblems | None:
|
|
17
|
-
"""Validate the URI and return a list of problems if any."""
|
|
18
|
-
iiif_uri_problems = [res for uri in self.uri_list if (res := self._validate_one_uri(uri)) is not None]
|
|
19
|
-
if iiif_uri_problems:
|
|
20
|
-
return AllIIIFUriProblems(problems=iiif_uri_problems)
|
|
21
|
-
return None
|
|
22
|
-
|
|
23
|
-
def _validate_one_uri(self, uri: str) -> IIIFUriProblem | None:
|
|
13
|
+
def validate_one_uri(self, uri: str) -> IIIFUriProblem | None:
|
|
24
14
|
"""Check if the IIIF-server is reachable. If not, it returns information for error message."""
|
|
25
15
|
regex_has_passed = is_iiif_uri(uri)
|
|
26
16
|
response = self._make_network_call(uri)
|
|
@@ -29,7 +19,6 @@ class IIIFUriValidator:
|
|
|
29
19
|
uri=uri,
|
|
30
20
|
regex_has_passed=regex_has_passed,
|
|
31
21
|
raised_exception_name=response.__class__.__name__,
|
|
32
|
-
original_text=str(response),
|
|
33
22
|
)
|
|
34
23
|
match response.ok, regex_has_passed:
|
|
35
24
|
case True, True:
|
|
@@ -39,7 +28,6 @@ class IIIFUriValidator:
|
|
|
39
28
|
uri=uri,
|
|
40
29
|
regex_has_passed=regex_has_passed,
|
|
41
30
|
status_code=response.status_code,
|
|
42
|
-
original_text=response.text,
|
|
43
31
|
)
|
|
44
32
|
|
|
45
33
|
def _make_network_call(self, uri: str) -> requests.Response | Exception:
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
from collections.abc import Iterable
|
|
3
4
|
from dataclasses import dataclass
|
|
4
5
|
from dataclasses import field
|
|
5
6
|
from typing import Any
|
|
6
|
-
from typing import Iterable
|
|
7
7
|
from typing import Protocol
|
|
8
8
|
from urllib.parse import quote_plus
|
|
9
9
|
|
|
10
10
|
from loguru import logger
|
|
11
11
|
|
|
12
|
-
from dsp_tools.
|
|
12
|
+
from dsp_tools.clients.connection import Connection
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
@dataclass(frozen=True)
|
|
@@ -39,7 +39,10 @@ class ProjectLists:
|
|
|
39
39
|
class ListClient(Protocol):
|
|
40
40
|
"""Interface (protocol) for list-related requests to the DSP-API."""
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
con: Connection
|
|
43
|
+
project_iri: str
|
|
44
|
+
|
|
45
|
+
def get_list_node_id_to_iri_lookup(self) -> dict[tuple[str, str], str]:
|
|
43
46
|
"""Get a lookup of list node names to IRIs."""
|
|
44
47
|
|
|
45
48
|
|
|
@@ -51,27 +54,29 @@ class ListClientLive:
|
|
|
51
54
|
project_iri: str
|
|
52
55
|
list_info: ProjectLists | None = field(init=False, default=None)
|
|
53
56
|
|
|
54
|
-
def get_list_node_id_to_iri_lookup(self) -> dict[str, str]:
|
|
57
|
+
def get_list_node_id_to_iri_lookup(self) -> dict[tuple[str, str], str]:
|
|
55
58
|
"""
|
|
56
59
|
Get a mapping of list node IDs to their respective IRIs.
|
|
57
60
|
A list node ID is structured as follows:
|
|
58
|
-
|
|
61
|
+
`("<list name>", "<node name>") where the list name is the node name of the root node.
|
|
59
62
|
|
|
60
63
|
Returns:
|
|
61
64
|
The mapping of list node IDs to IRIs.
|
|
62
65
|
"""
|
|
63
66
|
if not self.list_info:
|
|
64
67
|
self.list_info = _get_list_info_from_server(self.con, self.project_iri)
|
|
65
|
-
|
|
68
|
+
lookup = dict(_get_node_tuples(self.list_info.lists))
|
|
69
|
+
# Enable referencing list node IRIs in the XML:
|
|
70
|
+
# add a reference of the list node IRIs to themselves (with empty list names)
|
|
71
|
+
lookup.update({("", v): v for v in lookup.values()})
|
|
72
|
+
return lookup
|
|
66
73
|
|
|
67
74
|
|
|
68
|
-
def _get_node_tuples(lists: list[List]) -> Iterable[tuple[str, str]]:
|
|
75
|
+
def _get_node_tuples(lists: list[List]) -> Iterable[tuple[tuple[str, str], str]]:
|
|
69
76
|
for lst in lists:
|
|
70
77
|
list_name = lst.list_name
|
|
71
78
|
for node in lst.nodes:
|
|
72
|
-
|
|
73
|
-
node_id = f"{list_name}:{node_name}"
|
|
74
|
-
yield node_id, node.node_iri
|
|
79
|
+
yield (list_name, node.node_name), node.node_iri
|
|
75
80
|
|
|
76
81
|
|
|
77
82
|
def _get_list_info_from_server(con: Connection, project_iri: str) -> ProjectLists:
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from loguru import logger
|
|
4
|
+
from lxml import etree
|
|
5
|
+
|
|
6
|
+
from dsp_tools.clients.connection import Connection
|
|
7
|
+
from dsp_tools.commands.xmlupload.models.lookup_models import XmlReferenceLookups
|
|
8
|
+
from dsp_tools.commands.xmlupload.models.processed.res import ProcessedResource
|
|
9
|
+
from dsp_tools.commands.xmlupload.models.upload_clients import UploadClients
|
|
10
|
+
from dsp_tools.commands.xmlupload.stash.analyse_circular_reference_graph import generate_upload_order
|
|
11
|
+
from dsp_tools.commands.xmlupload.stash.create_info_for_graph import create_info_for_graph_from_processed_resources
|
|
12
|
+
from dsp_tools.commands.xmlupload.stash.stash_circular_references import stash_circular_references
|
|
13
|
+
from dsp_tools.commands.xmlupload.stash.stash_models import Stash
|
|
14
|
+
from dsp_tools.error.exceptions import BaseError
|
|
15
|
+
from dsp_tools.error.exceptions import InputError
|
|
16
|
+
from dsp_tools.legacy_models.projectContext import ProjectContext
|
|
17
|
+
from dsp_tools.utils.xml_parsing.get_lookups import get_authorship_lookup
|
|
18
|
+
from dsp_tools.utils.xml_parsing.get_lookups import get_permissions_lookup
|
|
19
|
+
from dsp_tools.utils.xml_parsing.get_parsed_resources import get_parsed_resources
|
|
20
|
+
from dsp_tools.utils.xml_parsing.models.parsed_resource import ParsedResource
|
|
21
|
+
|
|
22
|
+
LIST_SEPARATOR = "\n- "
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def get_parsed_resources_and_mappers(
|
|
26
|
+
root: etree._Element, clients: UploadClients
|
|
27
|
+
) -> tuple[list[ParsedResource], XmlReferenceLookups]:
|
|
28
|
+
logger.debug("Get ParsedResource and XML-Lookups from root")
|
|
29
|
+
print("Parsing XML file for upload.")
|
|
30
|
+
parsed_resources = get_parsed_resources(root, clients.legal_info_client.server)
|
|
31
|
+
processed_lookups = _get_xml_reference_lookups(root=root, clients=clients)
|
|
32
|
+
return parsed_resources, processed_lookups
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _get_xml_reference_lookups(root: etree._Element, clients: UploadClients) -> XmlReferenceLookups:
|
|
36
|
+
proj_context = _get_project_context_from_server(
|
|
37
|
+
connection=clients.list_client.con, shortcode=root.attrib["shortcode"]
|
|
38
|
+
)
|
|
39
|
+
permissions_lookup = get_permissions_lookup(root, proj_context)
|
|
40
|
+
authorship_lookup = get_authorship_lookup(root)
|
|
41
|
+
listnode_lookup = clients.list_client.get_list_node_id_to_iri_lookup()
|
|
42
|
+
return XmlReferenceLookups(
|
|
43
|
+
permissions=permissions_lookup,
|
|
44
|
+
listnodes=listnode_lookup,
|
|
45
|
+
authorships=authorship_lookup,
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _get_project_context_from_server(connection: Connection, shortcode: str) -> ProjectContext:
|
|
50
|
+
try:
|
|
51
|
+
proj_context = ProjectContext(con=connection, shortcode=shortcode)
|
|
52
|
+
except BaseError:
|
|
53
|
+
logger.exception("Unable to retrieve project context from DSP server")
|
|
54
|
+
raise InputError("Unable to retrieve project context from DSP server") from None
|
|
55
|
+
return proj_context
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def get_stash_and_upload_order(
|
|
59
|
+
resources: list[ProcessedResource],
|
|
60
|
+
) -> tuple[list[ProcessedResource], Stash | None]:
|
|
61
|
+
logger.debug("Get stash and upload order")
|
|
62
|
+
info_for_graph = create_info_for_graph_from_processed_resources(resources)
|
|
63
|
+
stash_lookup, upload_order = generate_upload_order(info_for_graph)
|
|
64
|
+
sorting_lookup = {res.res_id: res for res in resources}
|
|
65
|
+
sorted_resources = [sorting_lookup[res_id] for res_id in upload_order]
|
|
66
|
+
stash = stash_circular_references(sorted_resources, stash_lookup)
|
|
67
|
+
return sorted_resources, stash
|