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
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import json
|
|
2
4
|
from pathlib import Path
|
|
3
5
|
from typing import Any
|
|
@@ -5,14 +7,16 @@ from typing import Any
|
|
|
5
7
|
import regex
|
|
6
8
|
|
|
7
9
|
from dsp_tools.commands.excel2json.json_header import get_json_header
|
|
8
|
-
from dsp_tools.commands.excel2json.lists import excel2lists
|
|
9
|
-
from dsp_tools.commands.excel2json.
|
|
10
|
+
from dsp_tools.commands.excel2json.lists.make_lists import excel2lists
|
|
11
|
+
from dsp_tools.commands.excel2json.models.json_header import PermissionsOverrulesPrefixed
|
|
12
|
+
from dsp_tools.commands.excel2json.old_lists import old_excel2lists
|
|
10
13
|
from dsp_tools.commands.excel2json.properties import excel2properties
|
|
11
14
|
from dsp_tools.commands.excel2json.resources import excel2resources
|
|
12
|
-
from dsp_tools.
|
|
15
|
+
from dsp_tools.error.exceptions import BaseError
|
|
16
|
+
from dsp_tools.error.exceptions import InputError
|
|
13
17
|
|
|
14
18
|
|
|
15
|
-
def
|
|
19
|
+
def old_excel2json(
|
|
16
20
|
data_model_files: str,
|
|
17
21
|
path_to_output_file: str,
|
|
18
22
|
) -> bool:
|
|
@@ -38,16 +42,16 @@ def excel2json(
|
|
|
38
42
|
path_to_output_file: path to the file where the output JSON file will be saved
|
|
39
43
|
|
|
40
44
|
Raises:
|
|
41
|
-
|
|
45
|
+
InputError: if something went wrong
|
|
42
46
|
BaseError: if something went wrong
|
|
43
47
|
|
|
44
48
|
Returns:
|
|
45
49
|
True if everything went well
|
|
46
50
|
"""
|
|
47
51
|
|
|
48
|
-
listfolder, onto_folders =
|
|
52
|
+
listfolder, onto_folders = _old_validate_folder_structure_and_get_filenames(data_model_files)
|
|
49
53
|
|
|
50
|
-
overall_success, project =
|
|
54
|
+
overall_success, project = _old_create_project_json(data_model_files, listfolder, onto_folders)
|
|
51
55
|
|
|
52
56
|
with open(path_to_output_file, "w", encoding="utf-8") as f:
|
|
53
57
|
json.dump(project, f, indent=4, ensure_ascii=False)
|
|
@@ -57,17 +61,17 @@ def excel2json(
|
|
|
57
61
|
return overall_success
|
|
58
62
|
|
|
59
63
|
|
|
60
|
-
def
|
|
64
|
+
def _old_validate_folder_structure_and_get_filenames(data_model_files: str) -> tuple[list[Path], list[Path]]:
|
|
61
65
|
if not Path(data_model_files).is_dir():
|
|
62
|
-
raise
|
|
66
|
+
raise InputError(f"ERROR: {data_model_files} is not a directory.")
|
|
63
67
|
sub_folders = [x for x in Path(data_model_files).glob("*") if _non_hidden(x) and x.is_dir()]
|
|
64
68
|
files_to_process = []
|
|
65
69
|
onto_folders, onto_files_to_process = _get_and_validate_onto_folder(Path(data_model_files), sub_folders)
|
|
66
70
|
files_to_process.extend(onto_files_to_process)
|
|
67
|
-
listfolder, lists_to_process =
|
|
71
|
+
listfolder, lists_to_process = _old_get_and_validate_list_folder(data_model_files, sub_folders)
|
|
68
72
|
files_to_process.extend(lists_to_process)
|
|
69
73
|
if len(onto_folders) + len(listfolder) != len(sub_folders):
|
|
70
|
-
raise
|
|
74
|
+
raise InputError(
|
|
71
75
|
f"The only allowed subfolders in '{data_model_files}' are 'lists' "
|
|
72
76
|
"and folders that match the pattern 'onto_name (onto_label)'"
|
|
73
77
|
)
|
|
@@ -78,20 +82,20 @@ def _validate_folder_structure_get_filenames(data_model_files: str) -> tuple[lis
|
|
|
78
82
|
return listfolder, onto_folders
|
|
79
83
|
|
|
80
84
|
|
|
81
|
-
def
|
|
85
|
+
def _old_get_and_validate_list_folder(data_model_files: str, folder: list[Path]) -> tuple[list[Path], list[str]]:
|
|
82
86
|
processed_files: list[str] = []
|
|
83
87
|
listfolder = [x for x in folder if x.is_dir() and x.name == "lists"]
|
|
84
88
|
if listfolder:
|
|
85
89
|
listfolder_contents = [x for x in Path(listfolder[0]).glob("*") if _non_hidden(x)]
|
|
86
90
|
if not all(regex.search(r"(de|en|fr|it|rm).xlsx", file.name) for file in listfolder_contents):
|
|
87
|
-
raise
|
|
91
|
+
raise InputError(
|
|
88
92
|
f"The only files allowed in '{data_model_files}/lists' are en.xlsx, de.xlsx, fr.xlsx, it.xlsx, rm.xlsx"
|
|
89
93
|
)
|
|
90
94
|
processed_files = [f"{data_model_files}/lists/{file.name}" for file in listfolder_contents]
|
|
91
95
|
return listfolder, processed_files
|
|
92
96
|
|
|
93
97
|
|
|
94
|
-
def
|
|
98
|
+
def excel2json(
|
|
95
99
|
data_model_files: str,
|
|
96
100
|
path_to_output_file: str,
|
|
97
101
|
) -> bool:
|
|
@@ -123,26 +127,27 @@ def new_excel2json(
|
|
|
123
127
|
True if everything went well
|
|
124
128
|
"""
|
|
125
129
|
|
|
126
|
-
listfolder, onto_folders =
|
|
130
|
+
listfolder, onto_folders = _validate_folder_structure_and_get_filenames(Path(data_model_files))
|
|
127
131
|
|
|
128
|
-
overall_success, project =
|
|
132
|
+
overall_success, project = _create_project_json(data_model_files, onto_folders, listfolder)
|
|
129
133
|
|
|
130
134
|
with open(path_to_output_file, "w", encoding="utf-8") as f:
|
|
131
|
-
json.
|
|
135
|
+
dump_str = json.dumps(project, indent=4, ensure_ascii=False)
|
|
136
|
+
f.write(dump_str)
|
|
132
137
|
|
|
133
138
|
print(f"JSON project file successfully saved at {path_to_output_file}")
|
|
134
139
|
|
|
135
140
|
return overall_success
|
|
136
141
|
|
|
137
142
|
|
|
138
|
-
def
|
|
143
|
+
def _validate_folder_structure_and_get_filenames(data_model_files: Path) -> tuple[Path | None, list[Path]]:
|
|
139
144
|
if not data_model_files.is_dir():
|
|
140
|
-
raise
|
|
145
|
+
raise InputError(f"ERROR: {data_model_files} is not a directory.")
|
|
141
146
|
folder = [x for x in data_model_files.glob("*") if _non_hidden(x)]
|
|
142
147
|
processed_files = []
|
|
143
148
|
onto_folders, processed_onto = _get_and_validate_onto_folder(data_model_files, folder)
|
|
144
149
|
processed_files.extend(processed_onto)
|
|
145
|
-
listfolder, processed_lists =
|
|
150
|
+
listfolder, processed_lists = _get_and_validate_list_folder(data_model_files)
|
|
146
151
|
processed_files.extend(processed_lists)
|
|
147
152
|
print("The following files will be processed:")
|
|
148
153
|
print(*(f" - {file}" for file in processed_files), sep="\n")
|
|
@@ -153,13 +158,13 @@ def _get_and_validate_onto_folder(data_model_files: Path, folder: list[Path]) ->
|
|
|
153
158
|
processed_files = []
|
|
154
159
|
onto_folders = [x for x in folder if x.is_dir() and regex.search(r"([\w.-]+) \(([\w.\- ]+)\)", x.name)]
|
|
155
160
|
if not onto_folders:
|
|
156
|
-
raise
|
|
161
|
+
raise InputError(
|
|
157
162
|
f"'{data_model_files}' must contain at least one subfolder named after the pattern 'onto_name (onto_label)'"
|
|
158
163
|
)
|
|
159
164
|
for onto_folder in onto_folders:
|
|
160
165
|
contents = sorted([x.name for x in Path(onto_folder).glob("*") if _non_hidden(x)])
|
|
161
166
|
if contents != ["properties.xlsx", "resources.xlsx"]:
|
|
162
|
-
raise
|
|
167
|
+
raise InputError(
|
|
163
168
|
f"ERROR: '{data_model_files}/{onto_folder.name}' must contain one file 'properties.xlsx' "
|
|
164
169
|
"and one file 'resources.xlsx', but nothing else."
|
|
165
170
|
)
|
|
@@ -167,62 +172,99 @@ def _get_and_validate_onto_folder(data_model_files: Path, folder: list[Path]) ->
|
|
|
167
172
|
return onto_folders, processed_files
|
|
168
173
|
|
|
169
174
|
|
|
170
|
-
def
|
|
175
|
+
def _get_and_validate_list_folder(
|
|
171
176
|
data_model_files: Path,
|
|
172
177
|
) -> tuple[Path | None, list[str]]:
|
|
173
178
|
if not (list_dir := (data_model_files / "lists")).is_dir():
|
|
174
179
|
return None, []
|
|
175
180
|
processed_files = [str(file) for file in list_dir.glob("*list*.xlsx") if _non_hidden(file)]
|
|
176
|
-
return list_dir, processed_files
|
|
181
|
+
return list_dir, sorted(processed_files)
|
|
177
182
|
|
|
178
183
|
|
|
179
184
|
def _non_hidden(path: Path) -> bool:
|
|
180
185
|
return not regex.search(r"^(\.|~\$).+", path.name)
|
|
181
186
|
|
|
182
187
|
|
|
183
|
-
def
|
|
188
|
+
def _old_create_project_json(
|
|
184
189
|
data_model_files: str, listfolder: list[Path], onto_folders: list[Path]
|
|
185
190
|
) -> tuple[bool, dict[str, Any]]:
|
|
186
191
|
overall_success = True
|
|
187
|
-
lists, success =
|
|
192
|
+
lists, success = old_excel2lists(excelfolder=f"{data_model_files}/lists") if listfolder else (None, True)
|
|
188
193
|
if not success:
|
|
189
194
|
overall_success = False
|
|
190
|
-
ontologies, success = _get_ontologies(data_model_files, onto_folders)
|
|
195
|
+
ontologies, default_permissions_overrule, success = _get_ontologies(data_model_files, onto_folders)
|
|
191
196
|
if not success:
|
|
192
197
|
overall_success = False
|
|
193
198
|
project = get_json_header(Path(data_model_files) / "json_header.xlsx").to_dict()
|
|
199
|
+
if default_permissions_overrule.non_empty():
|
|
200
|
+
project["project"]["default_permissions_overrule"] = default_permissions_overrule.serialize()
|
|
194
201
|
if lists:
|
|
195
202
|
project["project"]["lists"] = lists
|
|
196
203
|
project["project"]["ontologies"] = ontologies
|
|
204
|
+
project["project"] = _sort_project_dict(project["project"])
|
|
197
205
|
return overall_success, project
|
|
198
206
|
|
|
199
207
|
|
|
200
|
-
def
|
|
208
|
+
def _create_project_json(
|
|
201
209
|
data_model_files: str, onto_folders: list[Path], list_folder: Path | None
|
|
202
210
|
) -> tuple[bool, dict[str, Any]]:
|
|
203
211
|
overall_success = True
|
|
204
212
|
lists = None
|
|
205
213
|
if list_folder:
|
|
206
|
-
lists, success =
|
|
214
|
+
lists, success = excel2lists(list_folder)
|
|
207
215
|
if not success:
|
|
208
216
|
overall_success = False
|
|
209
|
-
ontologies, success = _get_ontologies(data_model_files, onto_folders)
|
|
217
|
+
ontologies, default_permissions_overrule, success = _get_ontologies(data_model_files, onto_folders)
|
|
210
218
|
if not success:
|
|
211
219
|
overall_success = False
|
|
212
220
|
project = get_json_header(Path(data_model_files) / "json_header.xlsx").to_dict()
|
|
221
|
+
if default_permissions_overrule.non_empty():
|
|
222
|
+
project["project"]["default_permissions_overrule"] = default_permissions_overrule.serialize()
|
|
213
223
|
if lists:
|
|
214
224
|
project["project"]["lists"] = lists
|
|
215
225
|
project["project"]["ontologies"] = ontologies
|
|
226
|
+
project["project"] = _sort_project_dict(project["project"])
|
|
216
227
|
return overall_success, project
|
|
217
228
|
|
|
218
229
|
|
|
219
|
-
def
|
|
230
|
+
def _sort_project_dict(unsorted_project_dict: dict[str, Any]) -> dict[str, Any]:
|
|
231
|
+
# order how the keys should appear in the JSON file
|
|
232
|
+
ordered_keys = [
|
|
233
|
+
"shortcode",
|
|
234
|
+
"shortname",
|
|
235
|
+
"longname",
|
|
236
|
+
"descriptions",
|
|
237
|
+
"keywords",
|
|
238
|
+
"enabled_licenses",
|
|
239
|
+
"default_permissions",
|
|
240
|
+
"default_permissions_overrule",
|
|
241
|
+
"users",
|
|
242
|
+
"groups",
|
|
243
|
+
"lists",
|
|
244
|
+
"ontologies",
|
|
245
|
+
]
|
|
246
|
+
# filter out unused keys, to prevent a KeyError
|
|
247
|
+
ordered_keys = [key for key in ordered_keys if key in unsorted_project_dict]
|
|
248
|
+
# important - if in the future, more keys are added, they must be added to the list above
|
|
249
|
+
if any(forgotten_keys := [key for key in unsorted_project_dict if key not in ordered_keys]):
|
|
250
|
+
raise BaseError(
|
|
251
|
+
"The list of keys is outdated. During sorting, the following keys would be discarded: "
|
|
252
|
+
+ ", ".join(forgotten_keys)
|
|
253
|
+
)
|
|
254
|
+
# do the actual sorting
|
|
255
|
+
return {key: unsorted_project_dict[key] for key in ordered_keys}
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
def _get_ontologies(
|
|
259
|
+
data_model_files: str, onto_folders: list[Path]
|
|
260
|
+
) -> tuple[list[dict[str, Any]], PermissionsOverrulesPrefixed, bool]:
|
|
220
261
|
success = True
|
|
221
262
|
ontologies = []
|
|
263
|
+
permissions_overrules = PermissionsOverrulesPrefixed(private=[], limited_view=[])
|
|
222
264
|
for onto_folder in onto_folders:
|
|
223
265
|
name, label = regex.search(r"([\w.-]+) \(([\w.\- ]+)\)", onto_folder.name).groups() # type: ignore[union-attr]
|
|
224
|
-
resources, success1 = excel2resources(f"{data_model_files}/{onto_folder.name}/resources.xlsx")
|
|
225
|
-
properties, success2 = excel2properties(f"{data_model_files}/{onto_folder.name}/properties.xlsx")
|
|
266
|
+
resources, r_overrules, success1 = excel2resources(f"{data_model_files}/{onto_folder.name}/resources.xlsx")
|
|
267
|
+
properties, p_overrules, success2 = excel2properties(f"{data_model_files}/{onto_folder.name}/properties.xlsx")
|
|
226
268
|
if not success1 or not success2:
|
|
227
269
|
success = False
|
|
228
270
|
ontologies.append(
|
|
@@ -233,4 +275,6 @@ def _get_ontologies(data_model_files: str, onto_folders: list[Path]) -> tuple[li
|
|
|
233
275
|
"resources": resources,
|
|
234
276
|
}
|
|
235
277
|
)
|
|
236
|
-
|
|
278
|
+
permissions_overrules.add_overrules(r_overrules, name)
|
|
279
|
+
permissions_overrules.add_overrules(p_overrules, name)
|
|
280
|
+
return ontologies, permissions_overrules, success
|
|
@@ -19,13 +19,14 @@ from dsp_tools.commands.excel2json.models.input_error import JsonValidationPrope
|
|
|
19
19
|
from dsp_tools.commands.excel2json.models.input_error import MissingValuesProblem
|
|
20
20
|
from dsp_tools.commands.excel2json.models.input_error import MoreThanOneSheetProblem
|
|
21
21
|
from dsp_tools.commands.excel2json.models.input_error import PositionInExcel
|
|
22
|
-
from dsp_tools.commands.excel2json.models.input_error import Problem
|
|
23
22
|
from dsp_tools.commands.excel2json.models.input_error import PropertyProblem
|
|
23
|
+
from dsp_tools.commands.excel2json.models.json_header import PermissionsOverrulesUnprefixed
|
|
24
24
|
from dsp_tools.commands.excel2json.models.ontology import GuiAttributes
|
|
25
25
|
from dsp_tools.commands.excel2json.models.ontology import OntoProperty
|
|
26
26
|
from dsp_tools.commands.excel2json.utils import add_optional_columns
|
|
27
27
|
from dsp_tools.commands.excel2json.utils import check_column_for_duplicate
|
|
28
28
|
from dsp_tools.commands.excel2json.utils import check_contains_required_columns
|
|
29
|
+
from dsp_tools.commands.excel2json.utils import check_permissions
|
|
29
30
|
from dsp_tools.commands.excel2json.utils import check_required_values
|
|
30
31
|
from dsp_tools.commands.excel2json.utils import col_must_or_not_empty_based_on_other_col
|
|
31
32
|
from dsp_tools.commands.excel2json.utils import find_one_full_cell_in_cols
|
|
@@ -33,17 +34,18 @@ from dsp_tools.commands.excel2json.utils import get_comments
|
|
|
33
34
|
from dsp_tools.commands.excel2json.utils import get_labels
|
|
34
35
|
from dsp_tools.commands.excel2json.utils import get_wrong_row_numbers
|
|
35
36
|
from dsp_tools.commands.excel2json.utils import read_and_clean_all_sheets
|
|
36
|
-
from dsp_tools.
|
|
37
|
+
from dsp_tools.error.exceptions import InputError
|
|
38
|
+
from dsp_tools.error.exceptions import InvalidGuiAttributeError
|
|
39
|
+
from dsp_tools.error.problems import Problem
|
|
37
40
|
|
|
38
41
|
languages = ["en", "de", "fr", "it", "rm"]
|
|
39
42
|
language_label_col = ["label_en", "label_de", "label_fr", "label_it", "label_rm"]
|
|
40
|
-
mandatory_properties = ["name", "object", "gui_element"]
|
|
41
43
|
|
|
42
44
|
|
|
43
45
|
def excel2properties(
|
|
44
46
|
excelfile: str,
|
|
45
47
|
path_to_output_file: Optional[str] = None,
|
|
46
|
-
) -> tuple[list[dict[str, Any]], bool]:
|
|
48
|
+
) -> tuple[list[dict[str, Any]], PermissionsOverrulesUnprefixed, bool]:
|
|
47
49
|
"""
|
|
48
50
|
Converts properties described in an Excel file into a "properties" section which can be inserted into a JSON
|
|
49
51
|
project file.
|
|
@@ -56,8 +58,9 @@ def excel2properties(
|
|
|
56
58
|
InputError: if something went wrong
|
|
57
59
|
|
|
58
60
|
Returns:
|
|
59
|
-
|
|
60
|
-
|
|
61
|
+
- the "properties" section as a Python list
|
|
62
|
+
- the unprefixed "default_permissions_overrule"
|
|
63
|
+
- the success status (True if everything went well)
|
|
61
64
|
"""
|
|
62
65
|
|
|
63
66
|
property_df = _read_check_property_df(excelfile)
|
|
@@ -77,6 +80,7 @@ def excel2properties(
|
|
|
77
80
|
"comment_it",
|
|
78
81
|
"comment_rm",
|
|
79
82
|
"subject",
|
|
83
|
+
"default_permissions_overrule",
|
|
80
84
|
}
|
|
81
85
|
property_df = add_optional_columns(property_df, optional_col_set)
|
|
82
86
|
|
|
@@ -101,6 +105,7 @@ def excel2properties(
|
|
|
101
105
|
raise InputError(msg)
|
|
102
106
|
|
|
103
107
|
serialised_prop = [x.serialise() for x in props]
|
|
108
|
+
default_permissions_overrule = _extract_default_permissions_overrule(property_df)
|
|
104
109
|
|
|
105
110
|
# write final JSON file
|
|
106
111
|
_validate_properties_section_in_json(properties_list=serialised_prop)
|
|
@@ -109,7 +114,7 @@ def excel2properties(
|
|
|
109
114
|
json.dump(serialised_prop, file, indent=4, ensure_ascii=False)
|
|
110
115
|
print(f"properties section was created successfully and written to file '{path_to_output_file}'")
|
|
111
116
|
|
|
112
|
-
return serialised_prop, True
|
|
117
|
+
return serialised_prop, default_permissions_overrule, True
|
|
113
118
|
|
|
114
119
|
|
|
115
120
|
def _check_for_deprecated_syntax(df: pd.DataFrame) -> None:
|
|
@@ -176,6 +181,8 @@ def _do_property_excel_compliance(df: pd.DataFrame) -> None:
|
|
|
176
181
|
problems.append(col_prob)
|
|
177
182
|
if missing_vals_check := _check_missing_values_in_row(df=df):
|
|
178
183
|
problems.append(missing_vals_check)
|
|
184
|
+
if permissions_prob := check_permissions(df=df, allowed_vals=["private"]):
|
|
185
|
+
problems.append(permissions_prob)
|
|
179
186
|
if any(problems):
|
|
180
187
|
excel_prob = ExcelFileProblem("properties.xlsx", problems)
|
|
181
188
|
msg = excel_prob.execute_error_protocol()
|
|
@@ -202,7 +209,7 @@ def _check_missing_values_in_row(df: pd.DataFrame) -> None | MissingValuesProble
|
|
|
202
209
|
|
|
203
210
|
|
|
204
211
|
def _check_compliance_gui_attributes(df: pd.DataFrame) -> dict[str, pd.Series[bool]] | None:
|
|
205
|
-
mandatory_attributes = ["
|
|
212
|
+
mandatory_attributes = ["List"]
|
|
206
213
|
mandatory_check = col_must_or_not_empty_based_on_other_col(
|
|
207
214
|
df=df,
|
|
208
215
|
substring_list=mandatory_attributes,
|
|
@@ -210,7 +217,18 @@ def _check_compliance_gui_attributes(df: pd.DataFrame) -> dict[str, pd.Series[bo
|
|
|
210
217
|
check_empty_colname="gui_attributes",
|
|
211
218
|
must_have_value=True,
|
|
212
219
|
)
|
|
213
|
-
no_attributes = [
|
|
220
|
+
no_attributes = [
|
|
221
|
+
"Checkbox",
|
|
222
|
+
"Colorpicker",
|
|
223
|
+
"Date",
|
|
224
|
+
"Spinbox",
|
|
225
|
+
"Geonames",
|
|
226
|
+
"SimpleText",
|
|
227
|
+
"Textarea",
|
|
228
|
+
"Richtext",
|
|
229
|
+
"TimeStamp",
|
|
230
|
+
"Searchbox",
|
|
231
|
+
]
|
|
214
232
|
no_attribute_check = col_must_or_not_empty_based_on_other_col(
|
|
215
233
|
df=df,
|
|
216
234
|
substring_list=no_attributes,
|
|
@@ -230,11 +248,11 @@ def _get_final_series(
|
|
|
230
248
|
case None, None:
|
|
231
249
|
return None
|
|
232
250
|
case pd.Series(), pd.Series():
|
|
233
|
-
final_series = pd.Series(np.logical_or(mandatory_check, no_attribute_check))
|
|
251
|
+
final_series = pd.Series(np.logical_or(mandatory_check, no_attribute_check))
|
|
234
252
|
case pd.Series(), None:
|
|
235
|
-
final_series = mandatory_check
|
|
253
|
+
final_series = mandatory_check
|
|
236
254
|
case None, pd.Series():
|
|
237
|
-
final_series = no_attribute_check
|
|
255
|
+
final_series = no_attribute_check
|
|
238
256
|
return final_series
|
|
239
257
|
|
|
240
258
|
|
|
@@ -263,39 +281,31 @@ def _get_gui_attribute(
|
|
|
263
281
|
) -> GuiAttributes | InvalidExcelContentProblem | None:
|
|
264
282
|
if pd.isnull(df_row["gui_attributes"]):
|
|
265
283
|
return None
|
|
266
|
-
# If the attribute is not in the correct format, a called function may raise an IndexError
|
|
267
284
|
try:
|
|
268
|
-
return
|
|
269
|
-
except
|
|
285
|
+
return _unpack_gui_attributes(attribute_str=df_row["gui_attributes"])
|
|
286
|
+
except InvalidGuiAttributeError:
|
|
270
287
|
return InvalidExcelContentProblem(
|
|
271
|
-
expected_content="
|
|
288
|
+
expected_content="The only valid gui-attribute is 'hlist' for the gui-element 'List'.",
|
|
272
289
|
actual_content=df_row["gui_attributes"],
|
|
273
290
|
excel_position=PositionInExcel(column="gui_attributes", row=row_num),
|
|
274
291
|
)
|
|
275
292
|
|
|
276
293
|
|
|
277
|
-
def
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
)
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
gui_list = [x.strip() for x in attribute_str.split(",") if x.strip() != ""]
|
|
286
|
-
sub_gui_list = [[sub.strip() for sub in x.split(":") if sub.strip() != ""] for x in gui_list]
|
|
287
|
-
if any(len(sub) != 2 for sub in sub_gui_list):
|
|
288
|
-
raise IndexError
|
|
289
|
-
return {sub[0]: sub[1] for sub in sub_gui_list}
|
|
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})
|
|
290
302
|
|
|
291
303
|
|
|
292
|
-
def
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
else:
|
|
298
|
-
return value_str
|
|
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")
|
|
299
309
|
|
|
300
310
|
|
|
301
311
|
def _validate_properties_section_in_json(
|
|
@@ -347,3 +357,14 @@ def _find_validation_problem(
|
|
|
347
357
|
original_msg=validation_error.message,
|
|
348
358
|
message_path=validation_error.json_path,
|
|
349
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
|
|
@@ -18,18 +18,20 @@ from dsp_tools.commands.excel2json.models.input_error import JsonValidationResou
|
|
|
18
18
|
from dsp_tools.commands.excel2json.models.input_error import MandatorySheetsMissingProblem
|
|
19
19
|
from dsp_tools.commands.excel2json.models.input_error import MissingValuesProblem
|
|
20
20
|
from dsp_tools.commands.excel2json.models.input_error import PositionInExcel
|
|
21
|
-
from dsp_tools.commands.excel2json.models.input_error import Problem
|
|
22
21
|
from dsp_tools.commands.excel2json.models.input_error import ResourceSheetNotListedProblem
|
|
22
|
+
from dsp_tools.commands.excel2json.models.json_header import PermissionsOverrulesUnprefixed
|
|
23
23
|
from dsp_tools.commands.excel2json.models.ontology import OntoResource
|
|
24
24
|
from dsp_tools.commands.excel2json.models.ontology import ResourceCardinality
|
|
25
25
|
from dsp_tools.commands.excel2json.utils import add_optional_columns
|
|
26
26
|
from dsp_tools.commands.excel2json.utils import check_column_for_duplicate
|
|
27
27
|
from dsp_tools.commands.excel2json.utils import check_contains_required_columns
|
|
28
|
+
from dsp_tools.commands.excel2json.utils import check_permissions
|
|
28
29
|
from dsp_tools.commands.excel2json.utils import find_missing_required_values
|
|
29
30
|
from dsp_tools.commands.excel2json.utils import get_comments
|
|
30
31
|
from dsp_tools.commands.excel2json.utils import get_labels
|
|
31
32
|
from dsp_tools.commands.excel2json.utils import read_and_clean_all_sheets
|
|
32
|
-
from dsp_tools.
|
|
33
|
+
from dsp_tools.error.exceptions import InputError
|
|
34
|
+
from dsp_tools.error.problems import Problem
|
|
33
35
|
|
|
34
36
|
languages = ["en", "de", "fr", "it", "rm"]
|
|
35
37
|
|
|
@@ -37,7 +39,7 @@ languages = ["en", "de", "fr", "it", "rm"]
|
|
|
37
39
|
def excel2resources(
|
|
38
40
|
excelfile: str,
|
|
39
41
|
path_to_output_file: Optional[str] = None,
|
|
40
|
-
) -> tuple[list[dict[str, Any]], bool]:
|
|
42
|
+
) -> tuple[list[dict[str, Any]], PermissionsOverrulesUnprefixed, bool]:
|
|
41
43
|
"""
|
|
42
44
|
Converts resources described in an Excel file into a "resources" section which can be inserted into a JSON
|
|
43
45
|
project file.
|
|
@@ -48,12 +50,12 @@ def excel2resources(
|
|
|
48
50
|
(otherwise, it's only returned as return value)
|
|
49
51
|
|
|
50
52
|
Raises:
|
|
51
|
-
|
|
52
|
-
InputError: is something went wrong
|
|
53
|
+
InputError: if something went wrong
|
|
53
54
|
|
|
54
55
|
Returns:
|
|
55
|
-
|
|
56
|
-
|
|
56
|
+
- the "resources" section as Python list,
|
|
57
|
+
- the unprefixed "default_permissions_overrule",
|
|
58
|
+
- the success status (True if everything went well)
|
|
57
59
|
"""
|
|
58
60
|
|
|
59
61
|
all_dfs = read_and_clean_all_sheets(excelfile)
|
|
@@ -66,6 +68,7 @@ def excel2resources(
|
|
|
66
68
|
# transform every row into a resource
|
|
67
69
|
res = [_row2resource(row, resource_dfs.get(row["name"])) for i, row in classes_df.iterrows()]
|
|
68
70
|
resources = [x.serialise() for x in res]
|
|
71
|
+
default_permissions_overrule = _extract_default_permissions_overrule(classes_df)
|
|
69
72
|
|
|
70
73
|
# write final "resources" section into a JSON file
|
|
71
74
|
_validate_resources(resources_list=resources)
|
|
@@ -75,7 +78,7 @@ def excel2resources(
|
|
|
75
78
|
json.dump(resources, file, indent=4, ensure_ascii=False)
|
|
76
79
|
print(f"resources section was created successfully and written to file '{path_to_output_file}'")
|
|
77
80
|
|
|
78
|
-
return resources, True
|
|
81
|
+
return resources, default_permissions_overrule, True
|
|
79
82
|
|
|
80
83
|
|
|
81
84
|
def _validate_excel_file(all_dfs: dict[str, pd.DataFrame]) -> ExcelFileProblem | None:
|
|
@@ -91,6 +94,8 @@ def _validate_excel_file(all_dfs: dict[str, pd.DataFrame]) -> ExcelFileProblem |
|
|
|
91
94
|
problems.append(cls_problem)
|
|
92
95
|
if sheet_problems := _validate_individual_class_sheets(df_dict):
|
|
93
96
|
problems.extend(sheet_problems)
|
|
97
|
+
if permissions_prob := check_permissions(df=classes_df, allowed_vals=["private", "limited_view"]):
|
|
98
|
+
problems.append(permissions_prob)
|
|
94
99
|
if problems:
|
|
95
100
|
return ExcelFileProblem("resources.xlsx", problems)
|
|
96
101
|
return None
|
|
@@ -153,6 +158,7 @@ def _prepare_classes_df(resource_dfs: dict[str, pd.DataFrame]) -> tuple[pd.DataF
|
|
|
153
158
|
"comment_fr",
|
|
154
159
|
"comment_it",
|
|
155
160
|
"comment_rm",
|
|
161
|
+
"default_permissions_overrule",
|
|
156
162
|
},
|
|
157
163
|
)
|
|
158
164
|
resource_dfs = {k: add_optional_columns(v, {"gui_order"}) for k, v in resource_dfs.items()}
|
|
@@ -173,7 +179,7 @@ def _row2resource(
|
|
|
173
179
|
class_df_with_cardinalities: Excel sheet of the individual class
|
|
174
180
|
|
|
175
181
|
Raises:
|
|
176
|
-
|
|
182
|
+
InputError: if the row or the details sheet contains invalid data
|
|
177
183
|
|
|
178
184
|
Returns:
|
|
179
185
|
dict object of the resource
|
|
@@ -204,9 +210,10 @@ def _create_all_cardinalities(class_name: str, class_df_with_cardinalities: pd.D
|
|
|
204
210
|
|
|
205
211
|
|
|
206
212
|
def _make_one_cardinality(detail_row: pd.Series[str | int]) -> ResourceCardinality:
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
213
|
+
prop_str = str(detail_row["property"])
|
|
214
|
+
knora_props = ["seqnum", "isPartOf"]
|
|
215
|
+
prop = prop_str if ":" in prop_str or prop_str in knora_props else f":{prop_str}"
|
|
216
|
+
return ResourceCardinality(prop, str(detail_row["cardinality"]).lower(), int(detail_row["gui_order"]))
|
|
210
217
|
|
|
211
218
|
|
|
212
219
|
def _check_complete_gui_order(class_name: str, class_df_with_cardinalities: pd.DataFrame) -> pd.DataFrame:
|
|
@@ -314,3 +321,16 @@ def _find_validation_problem(
|
|
|
314
321
|
original_msg=validation_error.message,
|
|
315
322
|
message_path=validation_error.json_path,
|
|
316
323
|
)
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
def _extract_default_permissions_overrule(classes_df: pd.DataFrame) -> PermissionsOverrulesUnprefixed:
|
|
327
|
+
result = PermissionsOverrulesUnprefixed(private=[], limited_view=[])
|
|
328
|
+
for _, row in classes_df.iterrows():
|
|
329
|
+
perm = row.get("default_permissions_overrule")
|
|
330
|
+
if pd.isna(perm):
|
|
331
|
+
continue
|
|
332
|
+
if perm.strip().lower() == "private":
|
|
333
|
+
result.private.append(row["name"])
|
|
334
|
+
elif perm.strip().lower() == "limited_view":
|
|
335
|
+
result.limited_view.append(row["name"])
|
|
336
|
+
return result
|
|
@@ -11,11 +11,14 @@ import regex
|
|
|
11
11
|
from dsp_tools.commands.excel2json.models.input_error import DuplicateSheetProblem
|
|
12
12
|
from dsp_tools.commands.excel2json.models.input_error import DuplicatesInColumnProblem
|
|
13
13
|
from dsp_tools.commands.excel2json.models.input_error import ExcelFileProblem
|
|
14
|
+
from dsp_tools.commands.excel2json.models.input_error import InvalidPermissionsOverrule
|
|
15
|
+
from dsp_tools.commands.excel2json.models.input_error import InvalidPermissionsOverruleProblem
|
|
14
16
|
from dsp_tools.commands.excel2json.models.input_error import InvalidSheetNameProblem
|
|
15
17
|
from dsp_tools.commands.excel2json.models.input_error import PositionInExcel
|
|
16
18
|
from dsp_tools.commands.excel2json.models.input_error import RequiredColumnMissingProblem
|
|
17
19
|
from dsp_tools.commands.excel2json.models.ontology import LanguageDict
|
|
18
|
-
from dsp_tools.
|
|
20
|
+
from dsp_tools.error.exceptions import InputError
|
|
21
|
+
from dsp_tools.error.exceptions import UserFilepathNotFoundError
|
|
19
22
|
|
|
20
23
|
languages = ["en", "de", "fr", "it", "rm"]
|
|
21
24
|
|
|
@@ -36,6 +39,8 @@ def read_and_clean_all_sheets(excelfile: str | Path) -> dict[str, pd.DataFrame]:
|
|
|
36
39
|
Raises:
|
|
37
40
|
InputError: If the sheets are not correctly named
|
|
38
41
|
"""
|
|
42
|
+
if not Path(excelfile).exists():
|
|
43
|
+
raise UserFilepathNotFoundError(excelfile)
|
|
39
44
|
try:
|
|
40
45
|
df_dict = pd.read_excel(excelfile, sheet_name=None)
|
|
41
46
|
except ValueError:
|
|
@@ -331,3 +336,17 @@ def add_optional_columns(df: pd.DataFrame, optional_col_set: set[str]) -> pd.Dat
|
|
|
331
336
|
additional_df = pd.DataFrame(columns=additional_col, index=df.index)
|
|
332
337
|
df = pd.concat(objs=[df, additional_df], axis=1)
|
|
333
338
|
return df
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
def check_permissions(df: pd.DataFrame, allowed_vals: list[str]) -> None | InvalidPermissionsOverruleProblem:
|
|
342
|
+
problems: list[InvalidPermissionsOverrule] = []
|
|
343
|
+
for _, row in df.iterrows():
|
|
344
|
+
if pd.isna(actual_val := row.get("default_permissions_overrule")):
|
|
345
|
+
continue
|
|
346
|
+
if actual_val.strip().lower() not in allowed_vals:
|
|
347
|
+
prob = InvalidPermissionsOverrule(entity_name=row["name"], actual_val=actual_val, allowed_vals=allowed_vals)
|
|
348
|
+
problems.append(prob)
|
|
349
|
+
if problems:
|
|
350
|
+
return InvalidPermissionsOverruleProblem(problems)
|
|
351
|
+
else:
|
|
352
|
+
return None
|
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
|
|
4
4
|
from dsp_tools.commands.excel2xml.excel2xml_lib import *
|
|
5
5
|
from dsp_tools.commands.excel2xml.propertyelement import PropertyElement as PropertyElement
|
|
6
|
-
from dsp_tools.utils.shared import check_notna as check_notna
|
|
7
|
-
from dsp_tools.utils.shared import simplify_name as simplify_name
|
|
6
|
+
from dsp_tools.utils.data_formats.shared import check_notna as check_notna
|
|
7
|
+
from dsp_tools.utils.data_formats.shared import simplify_name as simplify_name
|