dsp-tools 0.9.13__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 +5 -0
- dsp_tools/cli/args.py +47 -0
- dsp_tools/cli/call_action.py +85 -0
- 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 +479 -0
- dsp_tools/cli/entry_point.py +322 -0
- 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/clients/connection.py +35 -0
- 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 +321 -0
- dsp_tools/commands/excel2json/lists/__init__.py +0 -0
- dsp_tools/commands/excel2json/lists/compliance_checks.py +292 -0
- dsp_tools/commands/excel2json/lists/make_lists.py +247 -0
- dsp_tools/commands/excel2json/lists/models/__init__.py +0 -0
- dsp_tools/commands/excel2json/lists/models/deserialise.py +30 -0
- dsp_tools/commands/excel2json/lists/models/input_error.py +216 -0
- dsp_tools/commands/excel2json/lists/models/serialise.py +57 -0
- dsp_tools/commands/excel2json/lists/utils.py +81 -0
- dsp_tools/commands/excel2json/models/__init__.py +0 -0
- dsp_tools/commands/excel2json/models/input_error.py +416 -0
- dsp_tools/commands/excel2json/models/json_header.py +175 -0
- dsp_tools/commands/excel2json/models/list_node_name.py +16 -0
- dsp_tools/commands/excel2json/models/ontology.py +76 -0
- dsp_tools/commands/excel2json/old_lists.py +328 -0
- dsp_tools/commands/excel2json/project.py +280 -0
- dsp_tools/commands/excel2json/properties.py +370 -0
- dsp_tools/commands/excel2json/resources.py +336 -0
- dsp_tools/commands/excel2json/utils.py +352 -0
- dsp_tools/commands/excel2xml/__init__.py +7 -0
- dsp_tools/commands/excel2xml/excel2xml_cli.py +523 -0
- dsp_tools/commands/excel2xml/excel2xml_lib.py +1953 -0
- dsp_tools/commands/excel2xml/propertyelement.py +47 -0
- dsp_tools/commands/get/__init__.py +0 -0
- dsp_tools/commands/get/get.py +166 -0
- dsp_tools/commands/get/get_permissions.py +257 -0
- dsp_tools/commands/get/get_permissions_legacy.py +89 -0
- dsp_tools/commands/get/legacy_models/__init__.py +0 -0
- dsp_tools/commands/get/legacy_models/context.py +318 -0
- dsp_tools/commands/get/legacy_models/group.py +241 -0
- dsp_tools/commands/get/legacy_models/helpers.py +47 -0
- dsp_tools/commands/get/legacy_models/listnode.py +390 -0
- dsp_tools/commands/get/legacy_models/model.py +12 -0
- dsp_tools/commands/get/legacy_models/ontology.py +324 -0
- dsp_tools/commands/get/legacy_models/project.py +366 -0
- dsp_tools/commands/get/legacy_models/propertyclass.py +417 -0
- dsp_tools/commands/get/legacy_models/resourceclass.py +676 -0
- dsp_tools/commands/get/legacy_models/user.py +438 -0
- dsp_tools/commands/get/models/__init__.py +0 -0
- dsp_tools/commands/get/models/permissions_models.py +10 -0
- dsp_tools/commands/id2iri.py +258 -0
- dsp_tools/commands/ingest_xmlupload/__init__.py +0 -0
- dsp_tools/commands/ingest_xmlupload/bulk_ingest_client.py +178 -0
- dsp_tools/commands/ingest_xmlupload/create_resources/__init__.py +0 -0
- dsp_tools/commands/ingest_xmlupload/create_resources/apply_ingest_id.py +69 -0
- dsp_tools/commands/ingest_xmlupload/create_resources/upload_xml.py +166 -0
- dsp_tools/commands/ingest_xmlupload/create_resources/user_information.py +121 -0
- dsp_tools/commands/ingest_xmlupload/ingest_files/__init__.py +0 -0
- dsp_tools/commands/ingest_xmlupload/ingest_files/ingest_files.py +64 -0
- dsp_tools/commands/ingest_xmlupload/upload_files/__init__.py +0 -0
- dsp_tools/commands/ingest_xmlupload/upload_files/filechecker.py +20 -0
- dsp_tools/commands/ingest_xmlupload/upload_files/input_error.py +57 -0
- dsp_tools/commands/ingest_xmlupload/upload_files/upload_failures.py +66 -0
- dsp_tools/commands/ingest_xmlupload/upload_files/upload_files.py +67 -0
- dsp_tools/commands/resume_xmlupload/__init__.py +0 -0
- dsp_tools/commands/resume_xmlupload/resume_xmlupload.py +96 -0
- dsp_tools/commands/start_stack.py +428 -0
- 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/validate_data/sparql/cardinality_shacl.py +209 -0
- 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/__init__.py +0 -0
- dsp_tools/commands/xmlupload/iri_resolver.py +21 -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/__init__.py +0 -0
- dsp_tools/commands/xmlupload/models/bitstream_info.py +18 -0
- dsp_tools/commands/xmlupload/models/formatted_text_value.py +10 -0
- dsp_tools/commands/xmlupload/models/ingest.py +143 -0
- dsp_tools/commands/xmlupload/models/input_problems.py +58 -0
- dsp_tools/commands/xmlupload/models/lookup_models.py +21 -0
- dsp_tools/commands/xmlupload/models/permission.py +45 -0
- dsp_tools/commands/xmlupload/models/permissions_parsed.py +93 -0
- 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 +14 -0
- dsp_tools/commands/xmlupload/models/upload_state.py +20 -0
- dsp_tools/commands/xmlupload/prepare_xml_input/__init__.py +0 -0
- dsp_tools/commands/xmlupload/prepare_xml_input/ark2iri.py +55 -0
- dsp_tools/commands/xmlupload/prepare_xml_input/get_processed_resources.py +252 -0
- dsp_tools/commands/xmlupload/prepare_xml_input/iiif_uri_validator.py +50 -0
- dsp_tools/commands/xmlupload/prepare_xml_input/list_client.py +120 -0
- 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 +25 -0
- dsp_tools/commands/xmlupload/richtext_id2iri.py +37 -0
- dsp_tools/commands/xmlupload/stash/__init__.py +0 -0
- dsp_tools/commands/xmlupload/stash/analyse_circular_reference_graph.py +236 -0
- dsp_tools/commands/xmlupload/stash/create_info_for_graph.py +53 -0
- dsp_tools/commands/xmlupload/stash/graph_models.py +87 -0
- dsp_tools/commands/xmlupload/stash/stash_circular_references.py +68 -0
- dsp_tools/commands/xmlupload/stash/stash_models.py +109 -0
- dsp_tools/commands/xmlupload/stash/upload_stashed_resptr_props.py +106 -0
- dsp_tools/commands/xmlupload/stash/upload_stashed_xml_texts.py +196 -0
- dsp_tools/commands/xmlupload/upload_config.py +76 -0
- dsp_tools/commands/xmlupload/write_diagnostic_info.py +27 -0
- dsp_tools/commands/xmlupload/xmlupload.py +516 -0
- dsp_tools/config/__init__.py +0 -0
- dsp_tools/config/logger_config.py +69 -0
- dsp_tools/config/warnings_config.py +32 -0
- 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/legacy_models/datetimestamp.py +81 -0
- dsp_tools/legacy_models/langstring.py +253 -0
- dsp_tools/legacy_models/projectContext.py +49 -0
- dsp_tools/py.typed +0 -0
- dsp_tools/resources/schema/data.xsd +648 -0
- dsp_tools/resources/schema/lists-only.json +72 -0
- dsp_tools/resources/schema/project.json +1258 -0
- dsp_tools/resources/schema/properties-only.json +874 -0
- dsp_tools/resources/schema/resources-only.json +140 -0
- dsp_tools/resources/start-stack/docker-compose.override-host.j2 +11 -0
- dsp_tools/resources/start-stack/docker-compose.override.yml +11 -0
- dsp_tools/resources/start-stack/docker-compose.yml +88 -0
- 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/__init__.py +0 -0
- dsp_tools/utils/ansi_colors.py +32 -0
- dsp_tools/utils/data_formats/__init__.py +0 -0
- dsp_tools/utils/data_formats/date_util.py +166 -0
- dsp_tools/utils/data_formats/iri_util.py +30 -0
- dsp_tools/utils/data_formats/shared.py +81 -0
- dsp_tools/utils/data_formats/uri_util.py +76 -0
- 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/__init__.py +0 -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 +1542 -0
- 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/internal/migration_metadata.py +55 -0
- 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 +348 -0
- dsp_tools/xmllib/value_checkers.py +434 -0
- dsp_tools/xmllib/value_converters.py +777 -0
- 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-18.3.0.post13.dist-info/entry_points.txt +3 -0
- dsp_tools-0.9.13.dist-info/LICENSE +0 -674
- dsp_tools-0.9.13.dist-info/METADATA +0 -144
- dsp_tools-0.9.13.dist-info/RECORD +0 -71
- dsp_tools-0.9.13.dist-info/WHEEL +0 -5
- dsp_tools-0.9.13.dist-info/entry_points.txt +0 -3
- dsp_tools-0.9.13.dist-info/top_level.txt +0 -1
- dsplib/models/connection.py +0 -272
- dsplib/models/group.py +0 -296
- dsplib/models/helpers.py +0 -505
- dsplib/models/langstring.py +0 -277
- dsplib/models/listnode.py +0 -578
- dsplib/models/model.py +0 -20
- dsplib/models/ontology.py +0 -448
- dsplib/models/permission.py +0 -112
- dsplib/models/project.py +0 -547
- dsplib/models/propertyclass.py +0 -505
- dsplib/models/resource.py +0 -366
- dsplib/models/resourceclass.py +0 -810
- dsplib/models/sipi.py +0 -30
- dsplib/models/user.py +0 -731
- dsplib/models/value.py +0 -1000
- dsplib/utils/knora-data-schema.xsd +0 -454
- dsplib/utils/knora-schema-lists.json +0 -83
- dsplib/utils/knora-schema.json +0 -434
- dsplib/utils/onto_commons.py +0 -24
- dsplib/utils/onto_create_lists.py +0 -73
- dsplib/utils/onto_create_ontology.py +0 -442
- dsplib/utils/onto_get.py +0 -58
- dsplib/utils/onto_validate.py +0 -33
- dsplib/utils/xml_upload.py +0 -539
- dsplib/widgets/doublepassword.py +0 -80
- knora/MLS-import-libraries.py +0 -84
- knora/dsp_tools.py +0 -96
- knora/dsplib/models/connection.py +0 -272
- knora/dsplib/models/group.py +0 -296
- knora/dsplib/models/helpers.py +0 -506
- knora/dsplib/models/langstring.py +0 -277
- knora/dsplib/models/listnode.py +0 -578
- knora/dsplib/models/model.py +0 -20
- knora/dsplib/models/ontology.py +0 -448
- knora/dsplib/models/permission.py +0 -112
- knora/dsplib/models/project.py +0 -583
- knora/dsplib/models/propertyclass.py +0 -505
- knora/dsplib/models/resource.py +0 -416
- knora/dsplib/models/resourceclass.py +0 -811
- knora/dsplib/models/sipi.py +0 -35
- knora/dsplib/models/user.py +0 -731
- knora/dsplib/models/value.py +0 -1000
- knora/dsplib/utils/knora-data-schema.xsd +0 -464
- knora/dsplib/utils/knora-schema-lists.json +0 -83
- knora/dsplib/utils/knora-schema.json +0 -444
- knora/dsplib/utils/onto_commons.py +0 -24
- knora/dsplib/utils/onto_create_lists.py +0 -73
- knora/dsplib/utils/onto_create_ontology.py +0 -451
- knora/dsplib/utils/onto_get.py +0 -58
- knora/dsplib/utils/onto_validate.py +0 -33
- knora/dsplib/utils/xml_upload.py +0 -540
- knora/dsplib/widgets/doublepassword.py +0 -80
- knora/knora.py +0 -2108
- knora/test.py +0 -99
- knora/testit.py +0 -76
- knora/xml2knora.py +0 -633
- {dsplib → dsp_tools/cli}/__init__.py +0 -0
- {dsplib/models → dsp_tools/clients}/__init__.py +0 -0
- {dsplib/utils → dsp_tools/commands}/__init__.py +0 -0
- {dsplib/widgets → dsp_tools/commands/create}/__init__.py +0 -0
- {knora → dsp_tools/commands/create/create_on_server}/__init__.py +0 -0
- {knora/dsplib → dsp_tools/commands/create/models}/__init__.py +0 -0
- {knora/dsplib/models → dsp_tools/commands/create/parsing}/__init__.py +0 -0
- {knora/dsplib/utils → dsp_tools/commands/create/serialisation}/__init__.py +0 -0
- {knora/dsplib/widgets → dsp_tools/commands/excel2json}/__init__.py +0 -0
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import importlib.resources
|
|
4
|
+
import json
|
|
5
|
+
import warnings
|
|
6
|
+
from typing import Any
|
|
7
|
+
from typing import Optional
|
|
8
|
+
from typing import cast
|
|
9
|
+
|
|
10
|
+
import jsonpath_ng.ext
|
|
11
|
+
import jsonschema
|
|
12
|
+
import numpy as np
|
|
13
|
+
import pandas as pd
|
|
14
|
+
import regex
|
|
15
|
+
|
|
16
|
+
from dsp_tools.commands.excel2json.models.input_error import ExcelFileProblem
|
|
17
|
+
from dsp_tools.commands.excel2json.models.input_error import InvalidExcelContentProblem
|
|
18
|
+
from dsp_tools.commands.excel2json.models.input_error import JsonValidationPropertyProblem
|
|
19
|
+
from dsp_tools.commands.excel2json.models.input_error import MissingValuesProblem
|
|
20
|
+
from dsp_tools.commands.excel2json.models.input_error import MoreThanOneSheetProblem
|
|
21
|
+
from dsp_tools.commands.excel2json.models.input_error import PositionInExcel
|
|
22
|
+
from dsp_tools.commands.excel2json.models.input_error import PropertyProblem
|
|
23
|
+
from dsp_tools.commands.excel2json.models.json_header import PermissionsOverrulesUnprefixed
|
|
24
|
+
from dsp_tools.commands.excel2json.models.ontology import GuiAttributes
|
|
25
|
+
from dsp_tools.commands.excel2json.models.ontology import OntoProperty
|
|
26
|
+
from dsp_tools.commands.excel2json.utils import add_optional_columns
|
|
27
|
+
from dsp_tools.commands.excel2json.utils import check_column_for_duplicate
|
|
28
|
+
from dsp_tools.commands.excel2json.utils import check_contains_required_columns
|
|
29
|
+
from dsp_tools.commands.excel2json.utils import check_permissions
|
|
30
|
+
from dsp_tools.commands.excel2json.utils import check_required_values
|
|
31
|
+
from dsp_tools.commands.excel2json.utils import col_must_or_not_empty_based_on_other_col
|
|
32
|
+
from dsp_tools.commands.excel2json.utils import find_one_full_cell_in_cols
|
|
33
|
+
from dsp_tools.commands.excel2json.utils import get_comments
|
|
34
|
+
from dsp_tools.commands.excel2json.utils import get_labels
|
|
35
|
+
from dsp_tools.commands.excel2json.utils import get_wrong_row_numbers
|
|
36
|
+
from dsp_tools.commands.excel2json.utils import read_and_clean_all_sheets
|
|
37
|
+
from dsp_tools.error.exceptions import InputError
|
|
38
|
+
from dsp_tools.error.exceptions import InvalidGuiAttributeError
|
|
39
|
+
from dsp_tools.error.problems import Problem
|
|
40
|
+
|
|
41
|
+
languages = ["en", "de", "fr", "it", "rm"]
|
|
42
|
+
language_label_col = ["label_en", "label_de", "label_fr", "label_it", "label_rm"]
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def excel2properties(
|
|
46
|
+
excelfile: str,
|
|
47
|
+
path_to_output_file: Optional[str] = None,
|
|
48
|
+
) -> tuple[list[dict[str, Any]], PermissionsOverrulesUnprefixed, bool]:
|
|
49
|
+
"""
|
|
50
|
+
Converts properties described in an Excel file into a "properties" section which can be inserted into a JSON
|
|
51
|
+
project file.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
excelfile: path to the Excel file containing the properties
|
|
55
|
+
path_to_output_file: if provided, the output is written into this JSON file
|
|
56
|
+
|
|
57
|
+
Raises:
|
|
58
|
+
InputError: if something went wrong
|
|
59
|
+
|
|
60
|
+
Returns:
|
|
61
|
+
- the "properties" section as a Python list
|
|
62
|
+
- the unprefixed "default_permissions_overrule"
|
|
63
|
+
- the success status (True if everything went well)
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
property_df = _read_check_property_df(excelfile)
|
|
67
|
+
|
|
68
|
+
property_df = _rename_deprecated_columnnames(df=property_df)
|
|
69
|
+
|
|
70
|
+
# Not all columns have to be filled, users may delete some for ease of use, but it would generate an error later
|
|
71
|
+
optional_col_set = {
|
|
72
|
+
"label_en",
|
|
73
|
+
"label_de",
|
|
74
|
+
"label_fr",
|
|
75
|
+
"label_it",
|
|
76
|
+
"label_rm",
|
|
77
|
+
"comment_en",
|
|
78
|
+
"comment_de",
|
|
79
|
+
"comment_fr",
|
|
80
|
+
"comment_it",
|
|
81
|
+
"comment_rm",
|
|
82
|
+
"subject",
|
|
83
|
+
"default_permissions_overrule",
|
|
84
|
+
}
|
|
85
|
+
property_df = add_optional_columns(property_df, optional_col_set)
|
|
86
|
+
|
|
87
|
+
_do_property_excel_compliance(df=property_df)
|
|
88
|
+
|
|
89
|
+
_check_for_deprecated_syntax(property_df)
|
|
90
|
+
|
|
91
|
+
# transform every row into a property
|
|
92
|
+
props: list[OntoProperty] = []
|
|
93
|
+
problems: list[Problem] = []
|
|
94
|
+
for index, row in property_df.iterrows():
|
|
95
|
+
result = _row2prop(
|
|
96
|
+
df_row=row,
|
|
97
|
+
row_num=int(str(index)) + 2, # index is a label/index/hashable, but we need an int
|
|
98
|
+
)
|
|
99
|
+
if isinstance(result, PropertyProblem):
|
|
100
|
+
problems.append(result)
|
|
101
|
+
else:
|
|
102
|
+
props.append(result)
|
|
103
|
+
if problems:
|
|
104
|
+
msg = ExcelFileProblem("properties.xlsx", problems).execute_error_protocol()
|
|
105
|
+
raise InputError(msg)
|
|
106
|
+
|
|
107
|
+
serialised_prop = [x.serialise() for x in props]
|
|
108
|
+
default_permissions_overrule = _extract_default_permissions_overrule(property_df)
|
|
109
|
+
|
|
110
|
+
# write final JSON file
|
|
111
|
+
_validate_properties_section_in_json(properties_list=serialised_prop)
|
|
112
|
+
if path_to_output_file:
|
|
113
|
+
with open(file=path_to_output_file, mode="w", encoding="utf-8") as file:
|
|
114
|
+
json.dump(serialised_prop, file, indent=4, ensure_ascii=False)
|
|
115
|
+
print(f"properties section was created successfully and written to file '{path_to_output_file}'")
|
|
116
|
+
|
|
117
|
+
return serialised_prop, default_permissions_overrule, True
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def _check_for_deprecated_syntax(df: pd.DataFrame) -> None:
|
|
121
|
+
pass
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def _read_check_property_df(excelfile: str) -> pd.DataFrame:
|
|
125
|
+
sheets_df_dict = read_and_clean_all_sheets(excelfile)
|
|
126
|
+
if len(sheets_df_dict) != 1:
|
|
127
|
+
msg = MoreThanOneSheetProblem("properties.xlsx", list(sheets_df_dict.keys())).execute_error_protocol()
|
|
128
|
+
raise InputError(msg)
|
|
129
|
+
return next(iter(sheets_df_dict.values()))
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def _rename_deprecated_columnnames(df: pd.DataFrame) -> pd.DataFrame:
|
|
133
|
+
df = _rename_deprecated_lang_cols(df=df)
|
|
134
|
+
df = _rename_deprecated_hlist(df=df)
|
|
135
|
+
return df
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def _rename_deprecated_lang_cols(df: pd.DataFrame) -> pd.DataFrame:
|
|
139
|
+
if set(language_label_col).issubset(set(df.columns)):
|
|
140
|
+
return df
|
|
141
|
+
if set(languages).issubset(set(df.columns)):
|
|
142
|
+
warnings.warn(
|
|
143
|
+
f"The file 'properties.xlsx' uses {languages} as column titles, which is deprecated. "
|
|
144
|
+
f"Please use {[f'label_{lang}' for lang in languages]}"
|
|
145
|
+
)
|
|
146
|
+
rename_dict = dict(zip(languages, language_label_col))
|
|
147
|
+
df = df.rename(columns=rename_dict)
|
|
148
|
+
return df
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def _rename_deprecated_hlist(df: pd.DataFrame) -> pd.DataFrame:
|
|
152
|
+
# This function deals with Excel files that do conform to a previous format.
|
|
153
|
+
if "hlist" not in df.columns:
|
|
154
|
+
return df
|
|
155
|
+
warnings.warn(
|
|
156
|
+
"The file 'properties.xlsx' has a column 'hlist', which is deprecated. "
|
|
157
|
+
"Please use the column 'gui_attributes' for the attribute 'hlist'."
|
|
158
|
+
)
|
|
159
|
+
df["hlist"] = df["hlist"].apply(lambda x: f"hlist:{x}" if isinstance(x, str) else x)
|
|
160
|
+
# If gui_attributes already exists we have to merge the columns
|
|
161
|
+
if "gui_attributes" in df.columns:
|
|
162
|
+
# In case there is a hlist, it is the only valid value in gui_attributes and has precedence
|
|
163
|
+
df["hlist"] = df["hlist"].fillna(df["gui_attributes"])
|
|
164
|
+
df.pop("gui_attributes")
|
|
165
|
+
df = df.rename(columns={"hlist": "gui_attributes"})
|
|
166
|
+
return df
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def _do_property_excel_compliance(df: pd.DataFrame) -> None:
|
|
170
|
+
required_columns = {
|
|
171
|
+
"name",
|
|
172
|
+
"super",
|
|
173
|
+
"object",
|
|
174
|
+
"gui_element",
|
|
175
|
+
"gui_attributes",
|
|
176
|
+
}
|
|
177
|
+
problems: list[Problem] = []
|
|
178
|
+
if req_prob := check_contains_required_columns(df=df, required_columns=required_columns):
|
|
179
|
+
problems.append(req_prob)
|
|
180
|
+
if col_prob := check_column_for_duplicate(df=df, to_check_column="name"):
|
|
181
|
+
problems.append(col_prob)
|
|
182
|
+
if missing_vals_check := _check_missing_values_in_row(df=df):
|
|
183
|
+
problems.append(missing_vals_check)
|
|
184
|
+
if permissions_prob := check_permissions(df=df, allowed_vals=["private"]):
|
|
185
|
+
problems.append(permissions_prob)
|
|
186
|
+
if any(problems):
|
|
187
|
+
excel_prob = ExcelFileProblem("properties.xlsx", problems)
|
|
188
|
+
msg = excel_prob.execute_error_protocol()
|
|
189
|
+
raise InputError(msg)
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def _check_missing_values_in_row(df: pd.DataFrame) -> None | MissingValuesProblem:
|
|
193
|
+
required_values = ["name", "super", "object", "gui_element"]
|
|
194
|
+
missing_dict = check_required_values(df=df, required_values_columns=required_values)
|
|
195
|
+
missing_labels = find_one_full_cell_in_cols(df=df, required_columns=language_label_col)
|
|
196
|
+
if missing_labels is not None:
|
|
197
|
+
missing_dict.update({"label": missing_labels})
|
|
198
|
+
missing_gui_attributes = _check_compliance_gui_attributes(df=df)
|
|
199
|
+
if missing_gui_attributes is not None:
|
|
200
|
+
missing_dict.update(missing_gui_attributes)
|
|
201
|
+
if missing_dict:
|
|
202
|
+
missing_int_dict = get_wrong_row_numbers(wrong_row_dict=missing_dict, true_remains=True)
|
|
203
|
+
locs = []
|
|
204
|
+
for col, row_nums in missing_int_dict.items():
|
|
205
|
+
locs.extend([PositionInExcel(column=col, row=x) for x in row_nums])
|
|
206
|
+
return MissingValuesProblem(locs)
|
|
207
|
+
else:
|
|
208
|
+
return None
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def _check_compliance_gui_attributes(df: pd.DataFrame) -> dict[str, pd.Series[bool]] | None:
|
|
212
|
+
mandatory_attributes = ["List"]
|
|
213
|
+
mandatory_check = col_must_or_not_empty_based_on_other_col(
|
|
214
|
+
df=df,
|
|
215
|
+
substring_list=mandatory_attributes,
|
|
216
|
+
substring_colname="gui_element",
|
|
217
|
+
check_empty_colname="gui_attributes",
|
|
218
|
+
must_have_value=True,
|
|
219
|
+
)
|
|
220
|
+
no_attributes = [
|
|
221
|
+
"Checkbox",
|
|
222
|
+
"Colorpicker",
|
|
223
|
+
"Date",
|
|
224
|
+
"Spinbox",
|
|
225
|
+
"Geonames",
|
|
226
|
+
"SimpleText",
|
|
227
|
+
"Textarea",
|
|
228
|
+
"Richtext",
|
|
229
|
+
"TimeStamp",
|
|
230
|
+
"Searchbox",
|
|
231
|
+
]
|
|
232
|
+
no_attribute_check = col_must_or_not_empty_based_on_other_col(
|
|
233
|
+
df=df,
|
|
234
|
+
substring_list=no_attributes,
|
|
235
|
+
substring_colname="gui_element",
|
|
236
|
+
check_empty_colname="gui_attributes",
|
|
237
|
+
must_have_value=False,
|
|
238
|
+
)
|
|
239
|
+
final_series = _get_final_series(mandatory_check, no_attribute_check)
|
|
240
|
+
return {"gui_attributes": final_series} if final_series is not None else None
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
def _get_final_series(
|
|
244
|
+
mandatory_check: pd.Series[bool] | None, no_attribute_check: pd.Series[bool] | None
|
|
245
|
+
) -> pd.Series[bool] | None:
|
|
246
|
+
final_series: pd.Series[bool] = pd.Series()
|
|
247
|
+
match mandatory_check, no_attribute_check:
|
|
248
|
+
case None, None:
|
|
249
|
+
return None
|
|
250
|
+
case pd.Series(), pd.Series():
|
|
251
|
+
final_series = pd.Series(np.logical_or(mandatory_check, no_attribute_check))
|
|
252
|
+
case pd.Series(), None:
|
|
253
|
+
final_series = mandatory_check
|
|
254
|
+
case None, pd.Series():
|
|
255
|
+
final_series = no_attribute_check
|
|
256
|
+
return final_series
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
def _row2prop(df_row: pd.Series[Any], row_num: int) -> OntoProperty | PropertyProblem:
|
|
260
|
+
subj = df_row["subject"] if not pd.isna(df_row["subject"]) else None
|
|
261
|
+
comment = get_comments(df_row=df_row)
|
|
262
|
+
gui_attrib = _get_gui_attribute(df_row=df_row, row_num=row_num)
|
|
263
|
+
if isinstance(gui_attrib, InvalidExcelContentProblem):
|
|
264
|
+
return PropertyProblem(df_row["name"], cast(list[Problem], [gui_attrib]))
|
|
265
|
+
prop = OntoProperty(
|
|
266
|
+
name=df_row["name"],
|
|
267
|
+
super=[s.strip() for s in df_row["super"].split(",")],
|
|
268
|
+
object=df_row["object"],
|
|
269
|
+
subject=subj,
|
|
270
|
+
labels=get_labels(df_row=df_row),
|
|
271
|
+
comments=comment,
|
|
272
|
+
gui_element=df_row["gui_element"],
|
|
273
|
+
gui_attributes=gui_attrib,
|
|
274
|
+
)
|
|
275
|
+
return prop
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
def _get_gui_attribute(
|
|
279
|
+
df_row: pd.Series[Any],
|
|
280
|
+
row_num: int,
|
|
281
|
+
) -> GuiAttributes | InvalidExcelContentProblem | None:
|
|
282
|
+
if pd.isnull(df_row["gui_attributes"]):
|
|
283
|
+
return None
|
|
284
|
+
try:
|
|
285
|
+
return _unpack_gui_attributes(attribute_str=df_row["gui_attributes"])
|
|
286
|
+
except InvalidGuiAttributeError:
|
|
287
|
+
return InvalidExcelContentProblem(
|
|
288
|
+
expected_content="The only valid gui-attribute is 'hlist' for the gui-element 'List'.",
|
|
289
|
+
actual_content=df_row["gui_attributes"],
|
|
290
|
+
excel_position=PositionInExcel(column="gui_attributes", row=row_num),
|
|
291
|
+
)
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
def _unpack_gui_attributes(attribute_str: str) -> GuiAttributes:
|
|
295
|
+
attribute_str = attribute_str.strip()
|
|
296
|
+
if not attribute_str:
|
|
297
|
+
return GuiAttributes({})
|
|
298
|
+
attrib_key, attrib_val = _extract_information_from_single_gui_attribute(attribute_str)
|
|
299
|
+
if attrib_key != "hlist":
|
|
300
|
+
raise InvalidGuiAttributeError("The only valid gui-attribute is 'hlist' for the gui-element 'List'.")
|
|
301
|
+
return GuiAttributes({attrib_key: attrib_val})
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
def _extract_information_from_single_gui_attribute(attribute_str: str) -> tuple[str, str]:
|
|
305
|
+
attrib_format = r"(\S+)\s*:\s*(.+)"
|
|
306
|
+
if found := regex.search(attrib_format, attribute_str):
|
|
307
|
+
return found.group(1), found.group(2)
|
|
308
|
+
raise InvalidGuiAttributeError("Invalid gui attribute")
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
def _validate_properties_section_in_json(
|
|
312
|
+
properties_list: list[dict[str, Any]],
|
|
313
|
+
) -> None:
|
|
314
|
+
with (
|
|
315
|
+
importlib.resources.files("dsp_tools")
|
|
316
|
+
.joinpath("resources/schema/properties-only.json")
|
|
317
|
+
.open(encoding="utf-8") as schema_file
|
|
318
|
+
):
|
|
319
|
+
properties_schema = json.load(schema_file)
|
|
320
|
+
try:
|
|
321
|
+
jsonschema.validate(instance=properties_list, schema=properties_schema)
|
|
322
|
+
except jsonschema.ValidationError as err:
|
|
323
|
+
validation_problem = _find_validation_problem(properties_list=properties_list, validation_error=err)
|
|
324
|
+
msg = ExcelFileProblem("properties.xlsx", [validation_problem]).execute_error_protocol()
|
|
325
|
+
raise InputError(msg) from None
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
def _find_validation_problem(
|
|
329
|
+
properties_list: list[dict[str, Any]],
|
|
330
|
+
validation_error: jsonschema.ValidationError,
|
|
331
|
+
) -> JsonValidationPropertyProblem:
|
|
332
|
+
if json_path_to_property := regex.search(r"^\$\[(\d+)\]", validation_error.json_path):
|
|
333
|
+
# fmt: off
|
|
334
|
+
wrong_property_name = (
|
|
335
|
+
jsonpath_ng.ext.parse(json_path_to_property.group(0))
|
|
336
|
+
.find(properties_list)[0]
|
|
337
|
+
.value["name"]
|
|
338
|
+
)
|
|
339
|
+
# fmt: on
|
|
340
|
+
excel_row = int(json_path_to_property.group(1)) + 2
|
|
341
|
+
|
|
342
|
+
column = None
|
|
343
|
+
val_msg = None
|
|
344
|
+
if affected_field := regex.search(
|
|
345
|
+
r"name|labels|comments|super|subject|object|gui_element|gui_attributes",
|
|
346
|
+
validation_error.json_path,
|
|
347
|
+
):
|
|
348
|
+
column = affected_field.group(0)
|
|
349
|
+
val_msg = validation_error.message
|
|
350
|
+
|
|
351
|
+
return JsonValidationPropertyProblem(
|
|
352
|
+
problematic_property=wrong_property_name,
|
|
353
|
+
excel_position=PositionInExcel(column=column, row=excel_row),
|
|
354
|
+
original_msg=val_msg,
|
|
355
|
+
)
|
|
356
|
+
return JsonValidationPropertyProblem(
|
|
357
|
+
original_msg=validation_error.message,
|
|
358
|
+
message_path=validation_error.json_path,
|
|
359
|
+
)
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
def _extract_default_permissions_overrule(property_df: pd.DataFrame) -> PermissionsOverrulesUnprefixed:
|
|
363
|
+
result = PermissionsOverrulesUnprefixed(private=[], limited_view=[])
|
|
364
|
+
for _, row in property_df.iterrows():
|
|
365
|
+
perm = row.get("default_permissions_overrule")
|
|
366
|
+
if pd.isna(perm):
|
|
367
|
+
continue
|
|
368
|
+
if perm.strip().lower() == "private":
|
|
369
|
+
result.private.append(row["name"])
|
|
370
|
+
return result
|