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,99 @@
|
|
|
1
|
+
@prefix sh: <http://www.w3.org/ns/shacl#> .
|
|
2
|
+
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
|
|
3
|
+
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
|
|
4
|
+
@prefix owl: <http://www.w3.org/2002/07/owl#> .
|
|
5
|
+
@prefix knora-api: <http://api.knora.org/ontology/knora-api/v2#> .
|
|
6
|
+
|
|
7
|
+
@prefix api-shapes: <http://api.knora.org/ontology/knora-api/shapes/v2#> .
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
api-shapes:FindMissingMaxCardinality_Seqnum_OntologyShape
|
|
11
|
+
a sh:NodeShape ;
|
|
12
|
+
sh:targetClass owl:Class ;
|
|
13
|
+
sh:sparql [
|
|
14
|
+
a sh:SPARQLConstraint ;
|
|
15
|
+
sh:select """
|
|
16
|
+
PREFIX owl: <http://www.w3.org/2002/07/owl#>
|
|
17
|
+
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
|
|
18
|
+
PREFIX knora-api: <http://api.knora.org/ontology/knora-api/v2#>
|
|
19
|
+
|
|
20
|
+
SELECT $this ?path WHERE {
|
|
21
|
+
$this a owl:Class ;
|
|
22
|
+
rdfs:subClassOf ?restriction .
|
|
23
|
+
?restriction a owl:Restriction ;
|
|
24
|
+
owl:onProperty ?path .
|
|
25
|
+
|
|
26
|
+
?path rdfs:subPropertyOf* knora-api:seqnum .
|
|
27
|
+
|
|
28
|
+
FILTER NOT EXISTS {
|
|
29
|
+
?restriction owl:maxCardinality|owl:cardinality 1
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
""" ;
|
|
33
|
+
sh:message "seqnum must either have cardinality 1 or 0-1."
|
|
34
|
+
] ;
|
|
35
|
+
sh:severity sh:Violation .
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
api-shapes:FindMissingSeqnum_OntologyShape
|
|
39
|
+
a sh:NodeShape ;
|
|
40
|
+
sh:targetClass owl:Class ;
|
|
41
|
+
sh:sparql [
|
|
42
|
+
a sh:SPARQLConstraint ;
|
|
43
|
+
sh:select """
|
|
44
|
+
PREFIX owl: <http://www.w3.org/2002/07/owl#>
|
|
45
|
+
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
|
|
46
|
+
PREFIX knora-api: <http://api.knora.org/ontology/knora-api/v2#>
|
|
47
|
+
|
|
48
|
+
SELECT $this ?path WHERE {
|
|
49
|
+
|
|
50
|
+
$this a owl:Class ;
|
|
51
|
+
rdfs:subClassOf ?restrictionIsPartOf .
|
|
52
|
+
?restrictionIsPartOf a owl:Restriction ;
|
|
53
|
+
owl:onProperty ?path .
|
|
54
|
+
?path rdfs:subPropertyOf* knora-api:isPartOf .
|
|
55
|
+
|
|
56
|
+
FILTER NOT EXISTS {
|
|
57
|
+
$this a owl:Class ;
|
|
58
|
+
rdfs:subClassOf ?restrictionSeqnum .
|
|
59
|
+
?restrictionSeqnum a owl:Restriction ;
|
|
60
|
+
owl:onProperty ?seqnumProp .
|
|
61
|
+
?seqnumProp rdfs:subPropertyOf* knora-api:seqnum .
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
""" ;
|
|
65
|
+
sh:message "A class with a cardinality for isPartOf also requires a cardinality for seqnum."
|
|
66
|
+
] ;
|
|
67
|
+
sh:severity sh:Violation .
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
api-shapes:FindMissingIsPartOf_OntologyShape
|
|
71
|
+
a sh:NodeShape ;
|
|
72
|
+
sh:targetClass owl:Class ;
|
|
73
|
+
sh:sparql [
|
|
74
|
+
a sh:SPARQLConstraint ;
|
|
75
|
+
sh:select """
|
|
76
|
+
PREFIX owl: <http://www.w3.org/2002/07/owl#>
|
|
77
|
+
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
|
|
78
|
+
PREFIX knora-api: <http://api.knora.org/ontology/knora-api/v2#>
|
|
79
|
+
|
|
80
|
+
SELECT $this ?path WHERE {
|
|
81
|
+
|
|
82
|
+
$this a owl:Class ;
|
|
83
|
+
rdfs:subClassOf ?restrictionSeqnum .
|
|
84
|
+
?restrictionSeqnum a owl:Restriction ;
|
|
85
|
+
owl:onProperty ?path .
|
|
86
|
+
?path rdfs:subPropertyOf* knora-api:seqnum .
|
|
87
|
+
|
|
88
|
+
FILTER NOT EXISTS {
|
|
89
|
+
$this a owl:Class ;
|
|
90
|
+
rdfs:subClassOf ?restrictionIsPartOf .
|
|
91
|
+
?restrictionIsPartOf a owl:Restriction ;
|
|
92
|
+
owl:onProperty ?isPartOfProp .
|
|
93
|
+
?isPartOfProp rdfs:subPropertyOf* knora-api:isPartOf .
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
""" ;
|
|
97
|
+
sh:message "A class with a cardinality for seqnum also requires a cardinality for isPartOf."
|
|
98
|
+
] ;
|
|
99
|
+
sh:severity sh:Violation .
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# These are ANSI escape codes which can be used to configure the print output on the terminal
|
|
2
|
+
# http://www.lihaoyi.com/post/BuildyourownCommandLinewithANSIescapecodes.html
|
|
3
|
+
# The semicolon separates different configurations
|
|
4
|
+
|
|
5
|
+
# All codes must start with an escape sequence, it may differ in different languages, in Python "\u001b[" works
|
|
6
|
+
SEQUENCE_START = "\u001b["
|
|
7
|
+
|
|
8
|
+
# the "m" at the end signals,
|
|
9
|
+
# that the configuration code is finished and after that the string that should be printed starts
|
|
10
|
+
SEQUENCE_END = "m"
|
|
11
|
+
|
|
12
|
+
# reset to the default setting of the console
|
|
13
|
+
RESET_TO_DEFAULT = f"{SEQUENCE_START}0{SEQUENCE_END}"
|
|
14
|
+
|
|
15
|
+
BOLD = f"{SEQUENCE_START}1{SEQUENCE_END}" # 1 (bold) ; 32 (green)
|
|
16
|
+
|
|
17
|
+
# If you want to change for example both the text color and the background color you can combine the sequences
|
|
18
|
+
# for example: BACKGROUND_BOLD_MAGENTA + YELLOW -> magenta background with yellow text
|
|
19
|
+
|
|
20
|
+
# Colored Text
|
|
21
|
+
BOLD_GREEN = f"{SEQUENCE_START}1;32{SEQUENCE_END}" # 1 (bold) ; 32 (green)
|
|
22
|
+
BOLD_RED = f"{SEQUENCE_START}1;31{SEQUENCE_END}" # 1 (bold) ; 31 (red)
|
|
23
|
+
BOLD_CYAN = f"{SEQUENCE_START}1;36{SEQUENCE_END}" # 1 (bold) ; 36 (cyan)
|
|
24
|
+
BOLD_YELLOW = f"{SEQUENCE_START}1;33{SEQUENCE_END}" # 1 (bold) ; 33 (yellow)
|
|
25
|
+
YELLOW = f"{SEQUENCE_START}0;33{SEQUENCE_END}" # 0 (normal font) ; 33 (yellow)
|
|
26
|
+
RED = f"{SEQUENCE_START}0;31{SEQUENCE_END}" # 0 (normal font) ; 31 (red)
|
|
27
|
+
|
|
28
|
+
# Colored Background
|
|
29
|
+
BACKGROUND_BOLD_RED = f"{SEQUENCE_START}1;41{SEQUENCE_END}" # 1 (bold) ; 41 (background red)
|
|
30
|
+
BACKGROUND_BOLD_YELLOW = f"{SEQUENCE_START}1;43{SEQUENCE_END}" # 1 (bold) ; 43 (background yellow)
|
|
31
|
+
BACKGROUND_BOLD_GREEN = f"{SEQUENCE_START}1;42{SEQUENCE_END}" # 1 (bold) ; 42 (background green)
|
|
32
|
+
BACKGROUND_BOLD_CYAN = f"{SEQUENCE_START}1;46{SEQUENCE_END}" # 1 (bold) ; 46 (background cyan)
|
|
File without changes
|
|
@@ -6,7 +6,7 @@ from typing import cast
|
|
|
6
6
|
|
|
7
7
|
import regex
|
|
8
8
|
|
|
9
|
-
from dsp_tools.
|
|
9
|
+
from dsp_tools.error.exceptions import BaseError
|
|
10
10
|
|
|
11
11
|
_calendar = r"GREGORIAN|JULIAN|ISLAMIC"
|
|
12
12
|
_era = r"CE|BCE|BC|AD"
|
|
@@ -70,6 +70,18 @@ class Era(Enum):
|
|
|
70
70
|
raise BaseError(f"Invalid era type: {s}")
|
|
71
71
|
|
|
72
72
|
|
|
73
|
+
class DayMonthYearEra(Enum):
|
|
74
|
+
DAY = "Day"
|
|
75
|
+
MONTH = "Month"
|
|
76
|
+
YEAR = "Year"
|
|
77
|
+
ERA = "Era"
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class StartEnd(Enum):
|
|
81
|
+
START = "Start"
|
|
82
|
+
END = "End"
|
|
83
|
+
|
|
84
|
+
|
|
73
85
|
@dataclass(frozen=True)
|
|
74
86
|
class SingleDate:
|
|
75
87
|
"""Information about a single date."""
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import regex
|
|
2
|
+
|
|
3
|
+
_iri_pattern = r"^(http)s?://[\w\.\-~]*(:\d{,6})?(/[\w\-~]+)*(#[\w\-~]*)?"
|
|
4
|
+
_resource_iri_pattern = r"https?://rdfh.ch/[a-fA-F0-9]{4}/[\w-]{22}"
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def is_iri(s: str) -> bool:
|
|
8
|
+
"""Checks whether a string is a valid IRI."""
|
|
9
|
+
return regex.fullmatch(_iri_pattern, s) is not None
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def is_resource_iri(s: str) -> bool:
|
|
13
|
+
"""Checks whether a string is a valid resource IRI."""
|
|
14
|
+
return regex.fullmatch(_resource_iri_pattern, s) is not None
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def from_dsp_iri_to_prefixed_iri(iri: str) -> str:
|
|
18
|
+
dsp_iri_re = r".+\/(.+?)\/v2#(.+)$"
|
|
19
|
+
if not (found := regex.search(dsp_iri_re, iri)):
|
|
20
|
+
return iri
|
|
21
|
+
return f"{found.group(1)}:{found.group(2)}"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def make_dsp_ontology_prefix(api_url: str, shortcode: str, onto_name: str) -> str:
|
|
25
|
+
api_fixed = convert_api_url_for_correct_iri_namespace_construction(api_url)
|
|
26
|
+
return f"{api_fixed}/ontology/{shortcode}/{onto_name}/v2#"
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def convert_api_url_for_correct_iri_namespace_construction(api_url: str) -> str:
|
|
30
|
+
return regex.sub(r"^https", "http", api_url)
|
|
@@ -1,18 +1,14 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
import json
|
|
4
3
|
import unicodedata
|
|
5
|
-
from pathlib import Path
|
|
6
4
|
from typing import Any
|
|
7
5
|
from typing import Optional
|
|
8
6
|
from typing import TypeGuard
|
|
9
|
-
from typing import Union
|
|
10
7
|
|
|
11
8
|
import pandas as pd
|
|
12
9
|
import regex
|
|
13
10
|
|
|
14
11
|
from dsp_tools.commands.excel2xml.propertyelement import PropertyElement
|
|
15
|
-
from dsp_tools.models.exceptions import BaseError
|
|
16
12
|
|
|
17
13
|
|
|
18
14
|
def simplify_name(value: str) -> str:
|
|
@@ -73,7 +69,7 @@ def check_notna(value: Optional[Any]) -> TypeGuard[Any]:
|
|
|
73
69
|
if isinstance(value, PropertyElement):
|
|
74
70
|
value = value.value
|
|
75
71
|
|
|
76
|
-
if isinstance(value,
|
|
72
|
+
if isinstance(value, bool | int) or (
|
|
77
73
|
isinstance(value, float) and pd.notna(value)
|
|
78
74
|
): # necessary because isinstance(np.nan, float)
|
|
79
75
|
return True
|
|
@@ -83,33 +79,3 @@ def check_notna(value: Optional[Any]) -> TypeGuard[Any]:
|
|
|
83
79
|
)
|
|
84
80
|
else:
|
|
85
81
|
return False
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
def parse_json_input(project_file_as_path_or_parsed: Union[str, Path, dict[str, Any]]) -> dict[str, Any]:
|
|
89
|
-
"""
|
|
90
|
-
Check the input for a method that expects a JSON project definition, either as file path or as parsed JSON object:
|
|
91
|
-
If it is parsed already, return it unchanged.
|
|
92
|
-
If the input is a file path, parse it.
|
|
93
|
-
|
|
94
|
-
Args:
|
|
95
|
-
project_file_as_path_or_parsed: path to the JSON project definition, or parsed JSON object
|
|
96
|
-
|
|
97
|
-
Raises:
|
|
98
|
-
BaseError: if the input is invalid
|
|
99
|
-
|
|
100
|
-
Returns:
|
|
101
|
-
the parsed JSON object
|
|
102
|
-
"""
|
|
103
|
-
project_definition: dict[str, Any] = {}
|
|
104
|
-
if isinstance(project_file_as_path_or_parsed, dict):
|
|
105
|
-
project_definition = project_file_as_path_or_parsed
|
|
106
|
-
elif isinstance(project_file_as_path_or_parsed, (str, Path)) and Path(project_file_as_path_or_parsed).exists():
|
|
107
|
-
with open(project_file_as_path_or_parsed, encoding="utf-8") as f:
|
|
108
|
-
try:
|
|
109
|
-
project_definition = json.load(f)
|
|
110
|
-
except json.JSONDecodeError as e:
|
|
111
|
-
msg = f"The input file '{project_file_as_path_or_parsed}' cannot be parsed to a JSON object."
|
|
112
|
-
raise BaseError(msg) from e
|
|
113
|
-
else:
|
|
114
|
-
raise BaseError("Invalid input: The input must be a path to a JSON file or a parsed JSON object.")
|
|
115
|
-
return project_definition
|
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
import regex
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
def is_prod_like_server(server: str) -> bool:
|
|
5
|
+
return server in [
|
|
6
|
+
"https://api.dasch.swiss",
|
|
7
|
+
"https://api.rdu.dasch.swiss",
|
|
8
|
+
"https://api.ls-prod-server.dasch.swiss",
|
|
9
|
+
"https://api.ls-test-server.dasch.swiss",
|
|
10
|
+
"https://api.stage.dasch.swiss",
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
|
|
4
14
|
def is_uri(s: str) -> bool:
|
|
5
15
|
"""Checks if the given string is a valid URI."""
|
|
6
16
|
# URI = scheme ":" ["//" host [":" port]] path ["?" query] ["#" fragment]
|
|
7
|
-
chars_for_path_query_fragment = r"\w_.\-:~%()!@,;/=*&"
|
|
17
|
+
chars_for_path_query_fragment = r"\w_.\-:~%()!@,;/=*&'+"
|
|
8
18
|
scheme = r"(?<scheme>[a-z][a-z0-9+.\-]*)"
|
|
9
19
|
host = r"(?<host>[\w_.\-:~\[\]]+)"
|
|
10
20
|
port = r"(?<port>:\d{0,6})"
|
|
@@ -50,7 +60,7 @@ def is_iiif_uri(uri: str) -> bool:
|
|
|
50
60
|
r"^((\^|%5e)?max|" # max | ^max
|
|
51
61
|
r"(\^|%5e)?full|" # full | ^full
|
|
52
62
|
r"(\^|%5e)?pct:\d+(\.\d+)?|" # pct:n | ^pct:n
|
|
53
|
-
r"(\^|%5e)?(\d+(\.\d+)?)
|
|
63
|
+
r"(\^|%5e)?(\d+(\.\d+)?)+(,|%2c)|" # w, | ^w,
|
|
54
64
|
r"(\^|%5e)?,\d+(\.\d+)?|" # ,h | ^,h
|
|
55
65
|
r"(\^|%5e)?!?\d+(\.\d+)?,\d+(\.\d+)?)$" # w,h | ^w,h | !w,h | ^!w,h
|
|
56
66
|
)
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
from typing import assert_never
|
|
2
|
+
|
|
3
|
+
from loguru import logger
|
|
4
|
+
|
|
5
|
+
from dsp_tools.clients.fuseki_metrics import FusekiBloatingLevel
|
|
6
|
+
from dsp_tools.clients.fuseki_metrics import FusekiMetrics
|
|
7
|
+
from dsp_tools.config.logger_config import LOGGER_SAVEPATH
|
|
8
|
+
from dsp_tools.utils.ansi_colors import BACKGROUND_BOLD_RED
|
|
9
|
+
from dsp_tools.utils.ansi_colors import BOLD_YELLOW
|
|
10
|
+
from dsp_tools.utils.ansi_colors import RESET_TO_DEFAULT
|
|
11
|
+
|
|
12
|
+
_1_GB_IN_BYTES = 1_000_000_000
|
|
13
|
+
WARNING_BLOATING = 10 * _1_GB_IN_BYTES
|
|
14
|
+
CRITICAL_BLOATING = 20 * _1_GB_IN_BYTES
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def communicate_fuseki_bloating(fuseki_metrics: FusekiMetrics) -> None:
|
|
18
|
+
size_diff = _analyse_fuseki_sizes(fuseki_metrics)
|
|
19
|
+
bloating_level = _get_bloating_level(size_diff)
|
|
20
|
+
if size_diff is not None:
|
|
21
|
+
rounded = round(size_diff / _1_GB_IN_BYTES, 2)
|
|
22
|
+
else:
|
|
23
|
+
rounded = None
|
|
24
|
+
msg = (
|
|
25
|
+
f"The xmlupload caused the database to use {rounded} GB disk space. "
|
|
26
|
+
f"Please check that your test server has enough disk space for an upload. "
|
|
27
|
+
f"If you have any questions contact the dsp-tools developers at support@dasch.swiss."
|
|
28
|
+
)
|
|
29
|
+
match bloating_level:
|
|
30
|
+
case FusekiBloatingLevel.OK:
|
|
31
|
+
logger.debug(msg)
|
|
32
|
+
case FusekiBloatingLevel.WARNING:
|
|
33
|
+
logger.warning(msg)
|
|
34
|
+
print(f"{BOLD_YELLOW}WARNING: {msg}{RESET_TO_DEFAULT}")
|
|
35
|
+
case FusekiBloatingLevel.CRITICAL:
|
|
36
|
+
logger.warning(msg)
|
|
37
|
+
print(f"{BACKGROUND_BOLD_RED}WARNING: {msg}{RESET_TO_DEFAULT}")
|
|
38
|
+
case FusekiBloatingLevel.CALCULATION_FAILURE:
|
|
39
|
+
msg = (
|
|
40
|
+
"The database bloating size could not be calculated. "
|
|
41
|
+
f"Please contact the dsp-tools developers (at support@dasch.swiss) "
|
|
42
|
+
f"with your logs saved at {LOGGER_SAVEPATH}."
|
|
43
|
+
)
|
|
44
|
+
print(f"{BACKGROUND_BOLD_RED}{msg}{RESET_TO_DEFAULT}")
|
|
45
|
+
logger.error(msg)
|
|
46
|
+
case _:
|
|
47
|
+
assert_never(bloating_level)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _get_bloating_level(size_diff: int | None) -> FusekiBloatingLevel:
|
|
51
|
+
if size_diff is None:
|
|
52
|
+
return FusekiBloatingLevel.CALCULATION_FAILURE
|
|
53
|
+
if size_diff <= WARNING_BLOATING:
|
|
54
|
+
return FusekiBloatingLevel.OK
|
|
55
|
+
if size_diff <= CRITICAL_BLOATING:
|
|
56
|
+
return FusekiBloatingLevel.WARNING
|
|
57
|
+
return FusekiBloatingLevel.CRITICAL
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _analyse_fuseki_sizes(fuseki_metrics: FusekiMetrics) -> int | None:
|
|
61
|
+
if fuseki_metrics.end_size is not None and fuseki_metrics.start_size is not None:
|
|
62
|
+
return fuseki_metrics.end_size - fuseki_metrics.start_size
|
|
63
|
+
return None
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from typing import Any
|
|
4
|
+
from typing import cast
|
|
5
|
+
|
|
6
|
+
from loguru import logger
|
|
7
|
+
|
|
8
|
+
from dsp_tools.error.exceptions import JSONFileParsingError
|
|
9
|
+
from dsp_tools.error.exceptions import UserFilepathNotFoundError
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def parse_json_file(filepath: Path) -> dict[str, Any]:
|
|
13
|
+
if not filepath.exists():
|
|
14
|
+
raise UserFilepathNotFoundError(filepath)
|
|
15
|
+
with open(filepath, encoding="utf-8") as f:
|
|
16
|
+
try:
|
|
17
|
+
loaded = json.load(f)
|
|
18
|
+
return cast(dict[str, Any], loaded)
|
|
19
|
+
except json.JSONDecodeError as e:
|
|
20
|
+
logger.error(e)
|
|
21
|
+
msg = f"The input file '{filepath}' cannot be parsed to a JSON object."
|
|
22
|
+
raise JSONFileParsingError(msg) from None
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from typing import Union
|
|
2
|
+
|
|
3
|
+
from rdflib import IdentifiedNode
|
|
4
|
+
from rdflib import Literal
|
|
5
|
+
from rdflib import Namespace
|
|
6
|
+
from rdflib import Variable
|
|
7
|
+
from rdflib.term import Node
|
|
8
|
+
|
|
9
|
+
# naming conventions of prefixes and namespaces
|
|
10
|
+
|
|
11
|
+
# a prefix as a string is called [...]_PREFIX
|
|
12
|
+
# a prefix as a rdflib Namespace has no further suffix
|
|
13
|
+
|
|
14
|
+
#####
|
|
15
|
+
# rdflib typing
|
|
16
|
+
type PropertyTypeAlias = Union[IdentifiedNode, Variable]
|
|
17
|
+
type SubjectObjectTypeAlias = Union[IdentifiedNode, Literal, Variable, Node]
|
|
18
|
+
|
|
19
|
+
#####
|
|
20
|
+
# DSP-Namespaces
|
|
21
|
+
KNORA_API_PREFIX = "http://api.knora.org/ontology/knora-api/v2#"
|
|
22
|
+
KNORA_API = Namespace(KNORA_API_PREFIX)
|
|
23
|
+
|
|
24
|
+
KNORA_ADMIN_PREFIX = "http://www.knora.org/ontology/knora-admin#"
|
|
25
|
+
|
|
26
|
+
SALSAH_GUI_PREFIX = "http://api.knora.org/ontology/salsah-gui/v2#"
|
|
27
|
+
SALSAH_GUI = Namespace(SALSAH_GUI_PREFIX)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
#####
|
|
31
|
+
# Mappers
|
|
32
|
+
|
|
33
|
+
DSP_NAME_TO_PREFIX = {"knora-api": KNORA_API_PREFIX, "salsah-gui": SALSAH_GUI_PREFIX}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
#####
|
|
37
|
+
# For validate-data
|
|
38
|
+
API_SHAPES_PREFIX = "http://api.knora.org/ontology/knora-api/shapes/v2#"
|
|
39
|
+
API_SHAPES = Namespace(API_SHAPES_PREFIX)
|
|
40
|
+
DATA = Namespace("http://data/")
|
|
41
|
+
DASH_PREFIX = "http://datashapes.org/dash#"
|
|
42
|
+
DASH = Namespace(DASH_PREFIX)
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
from rdflib import Graph
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def serialise_json(rdf_graph: Graph) -> list[dict[str, Any]]:
|
|
8
|
+
graph_bytes = rdf_graph.serialize(format="json-ld", encoding="utf-8")
|
|
9
|
+
json_graph: list[dict[str, Any]] = json.loads(graph_bytes)
|
|
10
|
+
return json_graph
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
from copy import deepcopy
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
from dsp_tools.commands.xmlupload.iri_resolver import IriResolver
|
|
5
|
+
from dsp_tools.commands.xmlupload.richtext_id2iri import replace_ids_if_found
|
|
6
|
+
from dsp_tools.error.exceptions import DuplicateIdsInXmlAndId2IriMapping
|
|
7
|
+
from dsp_tools.utils.json_parsing import parse_json_file
|
|
8
|
+
from dsp_tools.utils.xml_parsing.models.parsed_resource import KnoraValueType
|
|
9
|
+
from dsp_tools.utils.xml_parsing.models.parsed_resource import ParsedResource
|
|
10
|
+
from dsp_tools.utils.xml_parsing.models.parsed_resource import ParsedValue
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def use_id2iri_mapping_to_replace_ids(resources: list[ParsedResource], id2iri_file: Path) -> list[ParsedResource]:
|
|
14
|
+
lookup = parse_json_file(id2iri_file)
|
|
15
|
+
iri_lookup = IriResolver(lookup)
|
|
16
|
+
return _replace_all_ids_with_iris(resources, iri_lookup)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _replace_all_ids_with_iris(resources: list[ParsedResource], iri_lookup: IriResolver) -> list[ParsedResource]:
|
|
20
|
+
new_ids = {x.res_id for x in resources}
|
|
21
|
+
_raise_error_if_resource_ids_are_reused(new_ids, set(iri_lookup.lookup.keys()))
|
|
22
|
+
return [_process_one_resource(r, iri_lookup) for r in resources]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _raise_error_if_resource_ids_are_reused(
|
|
26
|
+
resources_ids_from_xml: set[str], resource_ids_from_mapping: set[str]
|
|
27
|
+
) -> None:
|
|
28
|
+
overlap = resources_ids_from_xml.intersection(resource_ids_from_mapping)
|
|
29
|
+
if overlap:
|
|
30
|
+
msg = (
|
|
31
|
+
"You provided a id2iri mapping file to replace IDs referenced in links and "
|
|
32
|
+
"richtext with IRIs of previously uploaded resources. "
|
|
33
|
+
"This means that the new XML file must not contain IDs that were previously used.\n"
|
|
34
|
+
f"The following ID(s) are both in the id2iri mapping and the new data: {', '.join(overlap)}"
|
|
35
|
+
)
|
|
36
|
+
raise DuplicateIdsInXmlAndId2IriMapping(msg)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _process_one_resource(res: ParsedResource, iri_lookup: IriResolver) -> ParsedResource:
|
|
40
|
+
new_vals = []
|
|
41
|
+
previous_vals = deepcopy(res.values)
|
|
42
|
+
for v in previous_vals:
|
|
43
|
+
if v.value_type == KnoraValueType.LINK_VALUE:
|
|
44
|
+
new_vals.append(_process_link_value(v, iri_lookup))
|
|
45
|
+
elif v.value_type == KnoraValueType.RICHTEXT_VALUE:
|
|
46
|
+
new_vals.append(_process_richtext_value(v, iri_lookup))
|
|
47
|
+
else:
|
|
48
|
+
new_vals.append(v)
|
|
49
|
+
res.values = new_vals
|
|
50
|
+
return res
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _process_link_value(val: ParsedValue, iri_lookup: IriResolver) -> ParsedValue:
|
|
54
|
+
# later code deals with cases when it is not a string, we can safely ignore this here
|
|
55
|
+
if isinstance(val.value, str):
|
|
56
|
+
if found := iri_lookup.get(val.value):
|
|
57
|
+
val.value = found
|
|
58
|
+
return val
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _process_richtext_value(val: ParsedValue, iri_lookup: IriResolver) -> ParsedValue:
|
|
62
|
+
# later code deals with cases when it is not a string, we can safely ignore this here
|
|
63
|
+
if isinstance(val.value, str):
|
|
64
|
+
replaced, _ = replace_ids_if_found(val.value, iri_lookup)
|
|
65
|
+
val.value = replaced
|
|
66
|
+
return val
|