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,416 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
from dsp_tools.error.problems import Problem
|
|
7
|
+
|
|
8
|
+
separator = "\n "
|
|
9
|
+
list_separator = "\n - "
|
|
10
|
+
medium_separator = "\n----------------------------\n"
|
|
11
|
+
|
|
12
|
+
grand_separator = "\n\n---------------------------------------\n\n"
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclass(frozen=True)
|
|
16
|
+
class PositionInExcel:
|
|
17
|
+
"""This class contains the information about the position of a value in the excel."""
|
|
18
|
+
|
|
19
|
+
sheet: str | None = None
|
|
20
|
+
column: str | None = None
|
|
21
|
+
row: int | None = None
|
|
22
|
+
excel_filename: str | None = None
|
|
23
|
+
|
|
24
|
+
def __str__(self) -> str:
|
|
25
|
+
msg = []
|
|
26
|
+
if self.excel_filename:
|
|
27
|
+
msg.append(f"Excel '{self.excel_filename}'")
|
|
28
|
+
if self.sheet:
|
|
29
|
+
msg.append(f"Sheet '{self.sheet}'")
|
|
30
|
+
if self.column:
|
|
31
|
+
msg.append(f"Column '{self.column}'")
|
|
32
|
+
if self.row:
|
|
33
|
+
msg.append(f"Row {self.row}")
|
|
34
|
+
return " | ".join(msg)
|
|
35
|
+
|
|
36
|
+
def execute_error_protocol(self) -> str:
|
|
37
|
+
"""
|
|
38
|
+
This function initiates all the steps for successful problem communication with the user.
|
|
39
|
+
|
|
40
|
+
Returns:
|
|
41
|
+
message for the error
|
|
42
|
+
"""
|
|
43
|
+
return str(self)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@dataclass(frozen=True)
|
|
47
|
+
class ExcelFileProblem:
|
|
48
|
+
"""This class contains information about problems with an excel file."""
|
|
49
|
+
|
|
50
|
+
filename: str
|
|
51
|
+
problems: list[Problem]
|
|
52
|
+
|
|
53
|
+
def execute_error_protocol(self) -> str:
|
|
54
|
+
"""
|
|
55
|
+
This function initiates all the steps for successful problem communication with the user.
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
message for the error
|
|
59
|
+
"""
|
|
60
|
+
msg = f"The Excel file '{self.filename}' contains the following problems:\n\n"
|
|
61
|
+
msg += medium_separator.join([x.execute_error_protocol() for x in self.problems])
|
|
62
|
+
return msg
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
@dataclass(frozen=True)
|
|
66
|
+
class ExcelSheetProblem:
|
|
67
|
+
"""This class contains information about problems in one excel sheet."""
|
|
68
|
+
|
|
69
|
+
sheet_name: str
|
|
70
|
+
problems: list[Problem]
|
|
71
|
+
|
|
72
|
+
def execute_error_protocol(self) -> str:
|
|
73
|
+
"""
|
|
74
|
+
This function initiates all the steps for successful problem communication with the user.
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
message for the error
|
|
78
|
+
"""
|
|
79
|
+
|
|
80
|
+
problem_strings = [x.execute_error_protocol() for x in self.problems]
|
|
81
|
+
return f"The sheet '{self.sheet_name}' has the following problems:\n\n{'\n\n'.join(problem_strings)}"
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
@dataclass(frozen=True)
|
|
85
|
+
class EmptySheetsProblem:
|
|
86
|
+
"""This class contains information if sheets that must contain information are empty."""
|
|
87
|
+
|
|
88
|
+
sheet_names: list[str]
|
|
89
|
+
|
|
90
|
+
def execute_error_protocol(self) -> str:
|
|
91
|
+
"""
|
|
92
|
+
This function initiates all the steps for successful problem communication with the user.
|
|
93
|
+
|
|
94
|
+
Returns:
|
|
95
|
+
message for the error
|
|
96
|
+
"""
|
|
97
|
+
return (
|
|
98
|
+
f"The following sheet(s) are mandatory and may not be empty:{list_separator}"
|
|
99
|
+
f"{list_separator.join(sorted(self.sheet_names))}"
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
@dataclass(frozen=True)
|
|
104
|
+
class MissingValuesProblem:
|
|
105
|
+
"""This class contains information if a value is missing in a location"""
|
|
106
|
+
|
|
107
|
+
locations: list[PositionInExcel]
|
|
108
|
+
|
|
109
|
+
def execute_error_protocol(self) -> str:
|
|
110
|
+
"""
|
|
111
|
+
This function initiates all the steps for successful problem communication with the user.
|
|
112
|
+
|
|
113
|
+
Returns:
|
|
114
|
+
message for the error
|
|
115
|
+
"""
|
|
116
|
+
locs = [str(x) for x in self.locations]
|
|
117
|
+
return f"At the following locations, mandatory values are missing:{list_separator}{list_separator.join(locs)}"
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
@dataclass(frozen=True)
|
|
121
|
+
class RequiredColumnMissingProblem:
|
|
122
|
+
"""This class contains information if a required column is missing."""
|
|
123
|
+
|
|
124
|
+
columns: list[str]
|
|
125
|
+
|
|
126
|
+
def execute_error_protocol(self) -> str:
|
|
127
|
+
"""
|
|
128
|
+
This function initiates all the steps for successful problem communication with the user.
|
|
129
|
+
|
|
130
|
+
Returns:
|
|
131
|
+
message for the error
|
|
132
|
+
"""
|
|
133
|
+
return f"The following required column(s) are missing:{list_separator}{list_separator.join(self.columns)}"
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
@dataclass(frozen=True)
|
|
137
|
+
class DuplicatesInColumnProblem:
|
|
138
|
+
"""This class contains information if a required column is missing."""
|
|
139
|
+
|
|
140
|
+
column: str
|
|
141
|
+
duplicate_values: list[str]
|
|
142
|
+
|
|
143
|
+
def execute_error_protocol(self) -> str:
|
|
144
|
+
"""
|
|
145
|
+
This function initiates all the steps for successful problem communication with the user.
|
|
146
|
+
|
|
147
|
+
Returns:
|
|
148
|
+
message for the error
|
|
149
|
+
"""
|
|
150
|
+
return (
|
|
151
|
+
f"No duplicates are allowed in the column '{self.column}'\n"
|
|
152
|
+
f"The following values appear several times:{list_separator}"
|
|
153
|
+
f"{list_separator.join(self.duplicate_values)}"
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
@dataclass(frozen=True)
|
|
158
|
+
class InvalidExcelContentProblem:
|
|
159
|
+
"""This class contains information if a required column is missing."""
|
|
160
|
+
|
|
161
|
+
expected_content: str
|
|
162
|
+
actual_content: str
|
|
163
|
+
excel_position: PositionInExcel
|
|
164
|
+
|
|
165
|
+
def execute_error_protocol(self) -> str:
|
|
166
|
+
"""
|
|
167
|
+
This function initiates all the steps for successful problem communication with the user.
|
|
168
|
+
|
|
169
|
+
Returns:
|
|
170
|
+
message for the error
|
|
171
|
+
"""
|
|
172
|
+
return (
|
|
173
|
+
f"There is invalid content in the excel.\n"
|
|
174
|
+
f"Located at: {self.excel_position}\n"
|
|
175
|
+
f"Expected Content: {self.expected_content}\n"
|
|
176
|
+
f"Actual Content: {self.actual_content}"
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
@dataclass(frozen=True)
|
|
181
|
+
class InvalidSheetNameProblem:
|
|
182
|
+
"""This class contains information if the excel sheet names are not strings."""
|
|
183
|
+
|
|
184
|
+
excelfile: str
|
|
185
|
+
excel_sheet_names: list[Any]
|
|
186
|
+
|
|
187
|
+
def execute_error_protocol(self) -> str:
|
|
188
|
+
"""
|
|
189
|
+
This function initiates all the steps for successful problem communication with the user.
|
|
190
|
+
|
|
191
|
+
Returns:
|
|
192
|
+
message for the error
|
|
193
|
+
"""
|
|
194
|
+
sheet_types = [f"Name: {x} | Type {type(x)}" for x in self.excel_sheet_names if not isinstance(x, str)]
|
|
195
|
+
return (
|
|
196
|
+
f"The names sheets in the excel '{self.excelfile}' are not all valid.\n"
|
|
197
|
+
f"They must be of type string. The following names are problematic:\n"
|
|
198
|
+
f"{list_separator}{list_separator.join(sheet_types)}\n"
|
|
199
|
+
f"Please rename them."
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
@dataclass(frozen=True)
|
|
204
|
+
class DuplicateSheetProblem:
|
|
205
|
+
duplicate_sheets: list[str]
|
|
206
|
+
|
|
207
|
+
def execute_error_protocol(self) -> str:
|
|
208
|
+
"""
|
|
209
|
+
This function initiates all the steps for successful problem communication with the user.
|
|
210
|
+
|
|
211
|
+
Returns:
|
|
212
|
+
message for the error
|
|
213
|
+
"""
|
|
214
|
+
return (
|
|
215
|
+
f"The sheet names inside the same Excel file must be unique. "
|
|
216
|
+
f"Using capitalisation or spaces to differentiate sheets is not valid.\n"
|
|
217
|
+
f"For example 'sheet' and 'SHEET ' are considered identical.\n"
|
|
218
|
+
f"Under this condition, the following sheet names appear multiple times:"
|
|
219
|
+
f"{list_separator}{list_separator.join(sorted(self.duplicate_sheets))}"
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
@dataclass(frozen=True)
|
|
224
|
+
class MoreThanOneSheetProblem:
|
|
225
|
+
"""This class contains information if the excel containing the property values has more than one sheet."""
|
|
226
|
+
|
|
227
|
+
excelname: str
|
|
228
|
+
sheet_names: list[str]
|
|
229
|
+
|
|
230
|
+
def execute_error_protocol(self) -> str:
|
|
231
|
+
msg = [
|
|
232
|
+
f"\nIn the '{self.excelname}' file only one sheet is allowed.",
|
|
233
|
+
f"The excel used contains the following sheets:{list_separator}{list_separator.join(self.sheet_names)}",
|
|
234
|
+
"Please delete all but one sheet.",
|
|
235
|
+
]
|
|
236
|
+
return separator.join(msg)
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
@dataclass(frozen=True)
|
|
240
|
+
class MandatorySheetsMissingProblem:
|
|
241
|
+
"""This class contains information if the excel is missing a mandatory sheet."""
|
|
242
|
+
|
|
243
|
+
mandatory_sheet: list[str]
|
|
244
|
+
existing_sheets: list[str]
|
|
245
|
+
|
|
246
|
+
def execute_error_protocol(self) -> str:
|
|
247
|
+
return (
|
|
248
|
+
f"The following mandatory sheet(s) are missing in this Excel:{list_separator}"
|
|
249
|
+
f"{list_separator.join(sorted(self.mandatory_sheet))}"
|
|
250
|
+
f"The following sheets are in the file:{list_separator}"
|
|
251
|
+
f"{list_separator.join(sorted(self.existing_sheets))}"
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
@dataclass(frozen=True)
|
|
256
|
+
class ResourceSheetNotListedProblem:
|
|
257
|
+
"""This class contains information if some resource sheets are missing in the 'classes' sheet."""
|
|
258
|
+
|
|
259
|
+
missing_names: set[str]
|
|
260
|
+
|
|
261
|
+
def execute_error_protocol(self) -> str:
|
|
262
|
+
"""
|
|
263
|
+
This function initiates all the steps for successful problem communication with the user.
|
|
264
|
+
|
|
265
|
+
Returns:
|
|
266
|
+
message for the error
|
|
267
|
+
"""
|
|
268
|
+
return (
|
|
269
|
+
f"All the sheets in the Excel must be listed in the 'name' column of the 'classes' sheet.\n"
|
|
270
|
+
f"The following sheet(s) are not listed in the column:{list_separator}"
|
|
271
|
+
f"{list_separator.join(self.missing_names)}"
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
@dataclass(frozen=True)
|
|
276
|
+
class MoreThanOneRowProblem:
|
|
277
|
+
"""This class contains information if a sheet has more than one row."""
|
|
278
|
+
|
|
279
|
+
num_rows: int
|
|
280
|
+
|
|
281
|
+
def execute_error_protocol(self) -> str:
|
|
282
|
+
"""
|
|
283
|
+
This function initiates all the steps for successful problem communication with the user.
|
|
284
|
+
|
|
285
|
+
Returns:
|
|
286
|
+
message for the error
|
|
287
|
+
"""
|
|
288
|
+
return f"This sheet may only have one row. The provided sheet has {self.num_rows} rows."
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
@dataclass(frozen=True)
|
|
292
|
+
class AtLeastOneValueRequiredProblem:
|
|
293
|
+
"""This class contains information if at least one entry in a group of columns must be filled."""
|
|
294
|
+
|
|
295
|
+
columns: list[str]
|
|
296
|
+
row_num: int
|
|
297
|
+
|
|
298
|
+
def execute_error_protocol(self) -> str:
|
|
299
|
+
"""
|
|
300
|
+
This function initiates all the steps for successful problem communication with the user.
|
|
301
|
+
|
|
302
|
+
Returns:
|
|
303
|
+
message for the error
|
|
304
|
+
"""
|
|
305
|
+
return (
|
|
306
|
+
f"At least one value is required in the columns: {', '.join(sorted(self.columns))}\n"
|
|
307
|
+
f"Row {self.row_num} does not contain any values in those columns."
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
@dataclass(frozen=True)
|
|
312
|
+
class JsonValidationPropertyProblem:
|
|
313
|
+
"""This class contains information about a JSON property section that fails its validation against the schema."""
|
|
314
|
+
|
|
315
|
+
problematic_property: str | None = None
|
|
316
|
+
original_msg: str | None = None
|
|
317
|
+
message_path: str | None = None
|
|
318
|
+
excel_position: PositionInExcel | None = None
|
|
319
|
+
|
|
320
|
+
def execute_error_protocol(self) -> str:
|
|
321
|
+
"""
|
|
322
|
+
This function initiates all the steps for successful problem communication with the user.
|
|
323
|
+
|
|
324
|
+
Returns:
|
|
325
|
+
message for the error
|
|
326
|
+
"""
|
|
327
|
+
msg = [
|
|
328
|
+
f"{separator}Section of the problem: 'Properties'",
|
|
329
|
+
]
|
|
330
|
+
if self.problematic_property:
|
|
331
|
+
msg.append(f"Problematic property: '{self.problematic_property}'")
|
|
332
|
+
if self.excel_position:
|
|
333
|
+
msg.append(f"Located at: {self.excel_position}")
|
|
334
|
+
if self.original_msg:
|
|
335
|
+
msg.append(f"Original Error Message: {self.original_msg}")
|
|
336
|
+
if self.message_path:
|
|
337
|
+
msg.append(f"The error occurred at {self.message_path}")
|
|
338
|
+
return separator.join(msg)
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
@dataclass(frozen=True)
|
|
342
|
+
class JsonValidationResourceProblem:
|
|
343
|
+
"""This class contains information about a JSON resource section that fails its validation against the schema."""
|
|
344
|
+
|
|
345
|
+
problematic_resource: str | None = None
|
|
346
|
+
excel_position: PositionInExcel | None = None
|
|
347
|
+
original_msg: str | None = None
|
|
348
|
+
message_path: str | None = None
|
|
349
|
+
|
|
350
|
+
def execute_error_protocol(self) -> str:
|
|
351
|
+
"""
|
|
352
|
+
This function initiates all the steps for successful problem communication with the user.
|
|
353
|
+
|
|
354
|
+
Returns:
|
|
355
|
+
message for the error
|
|
356
|
+
"""
|
|
357
|
+
msg = [
|
|
358
|
+
f"{separator}Section of the problem: 'Resources'",
|
|
359
|
+
]
|
|
360
|
+
if self.problematic_resource:
|
|
361
|
+
msg.append(f"Problematic Resource '{self.problematic_resource}'")
|
|
362
|
+
if self.excel_position:
|
|
363
|
+
msg.append(f"Located at: {self.excel_position}")
|
|
364
|
+
if self.original_msg:
|
|
365
|
+
msg.append(f"Original Error Message: {self.original_msg}")
|
|
366
|
+
if self.message_path:
|
|
367
|
+
msg.append(f"The error occurred at {self.message_path}")
|
|
368
|
+
return separator.join(msg)
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
@dataclass(frozen=True)
|
|
372
|
+
class PropertyProblem:
|
|
373
|
+
"""This class contains information if a property has invalid content."""
|
|
374
|
+
|
|
375
|
+
prop_name: str
|
|
376
|
+
problems: list[Problem]
|
|
377
|
+
|
|
378
|
+
def execute_error_protocol(self) -> str:
|
|
379
|
+
"""
|
|
380
|
+
This function initiates all the steps for successful problem communication with the user.
|
|
381
|
+
|
|
382
|
+
Returns:
|
|
383
|
+
message for the error
|
|
384
|
+
"""
|
|
385
|
+
all_problems = [x.execute_error_protocol() for x in self.problems]
|
|
386
|
+
return f"The property '{self.prop_name}' has the following problem(s):\n{medium_separator.join(all_problems)}"
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
@dataclass(frozen=True)
|
|
390
|
+
class InvalidPermissionsOverrule:
|
|
391
|
+
entity_name: str
|
|
392
|
+
actual_val: str
|
|
393
|
+
allowed_vals: list[str]
|
|
394
|
+
|
|
395
|
+
|
|
396
|
+
@dataclass(frozen=True)
|
|
397
|
+
class InvalidPermissionsOverruleProblem:
|
|
398
|
+
"""This class contains information if a "default_permissions_overrule" is invalid."""
|
|
399
|
+
|
|
400
|
+
wrong_vals: list[InvalidPermissionsOverrule]
|
|
401
|
+
|
|
402
|
+
def execute_error_protocol(self) -> str:
|
|
403
|
+
"""
|
|
404
|
+
This function initiates all the steps for successful problem communication with the user.
|
|
405
|
+
|
|
406
|
+
Returns:
|
|
407
|
+
message for the error
|
|
408
|
+
"""
|
|
409
|
+
report_lines = [
|
|
410
|
+
f"Entity: '{x.entity_name}'. Actual value: '{x.actual_val}'. Allowed values: {', '.join(x.allowed_vals)}."
|
|
411
|
+
for x in self.wrong_vals
|
|
412
|
+
]
|
|
413
|
+
return (
|
|
414
|
+
f"The following entities have an invalid 'default_permissions_overrule': "
|
|
415
|
+
f"{list_separator}{list_separator.join(report_lines)}"
|
|
416
|
+
)
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Any
|
|
5
|
+
from typing import Protocol
|
|
6
|
+
|
|
7
|
+
SCHEMA = "https://raw.githubusercontent.com/dasch-swiss/dsp-tools/main/src/dsp_tools/resources/schema/project.json"
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass
|
|
11
|
+
class JsonHeader(Protocol):
|
|
12
|
+
def to_dict(self) -> dict[str, Any]:
|
|
13
|
+
raise NotImplementedError
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass
|
|
17
|
+
class EmptyJsonHeader(JsonHeader):
|
|
18
|
+
def to_dict(self) -> dict[str, Any]:
|
|
19
|
+
return {
|
|
20
|
+
"prefixes": {"": ""},
|
|
21
|
+
"$schema": SCHEMA,
|
|
22
|
+
"project": {
|
|
23
|
+
"shortcode": "",
|
|
24
|
+
"shortname": "",
|
|
25
|
+
"longname": "",
|
|
26
|
+
"descriptions": {"en": ""},
|
|
27
|
+
"keywords": [""],
|
|
28
|
+
"enabled_licenses": [""],
|
|
29
|
+
},
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@dataclass
|
|
34
|
+
class FilledJsonHeader(JsonHeader):
|
|
35
|
+
project: Project
|
|
36
|
+
prefixes: Prefixes | None
|
|
37
|
+
|
|
38
|
+
def to_dict(self) -> dict[str, Any]:
|
|
39
|
+
header_dict: dict[str, Any] = {}
|
|
40
|
+
if self.prefixes:
|
|
41
|
+
header_dict["prefixes"] = self.prefixes.to_dict()
|
|
42
|
+
header_dict.update({"$schema": SCHEMA, "project": self.project.to_dict()})
|
|
43
|
+
return header_dict
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@dataclass
|
|
47
|
+
class Prefixes:
|
|
48
|
+
prefixes: dict[str, str]
|
|
49
|
+
|
|
50
|
+
def to_dict(self) -> dict[str, Any]:
|
|
51
|
+
return self.prefixes
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
@dataclass
|
|
55
|
+
class Project:
|
|
56
|
+
shortcode: str
|
|
57
|
+
shortname: str
|
|
58
|
+
longname: str
|
|
59
|
+
descriptions: Descriptions
|
|
60
|
+
keywords: Keywords
|
|
61
|
+
licenses: Licenses
|
|
62
|
+
users: Users | None
|
|
63
|
+
default_permissions: str
|
|
64
|
+
|
|
65
|
+
def to_dict(self) -> dict[str, Any]:
|
|
66
|
+
proj_dict: dict[str, Any] = {
|
|
67
|
+
"shortcode": self.shortcode,
|
|
68
|
+
"shortname": self.shortname,
|
|
69
|
+
"longname": self.longname,
|
|
70
|
+
"descriptions": self.descriptions.to_dict(),
|
|
71
|
+
"keywords": self.keywords.to_dict(),
|
|
72
|
+
"enabled_licenses": self.licenses.to_dict(),
|
|
73
|
+
"default_permissions": self.default_permissions,
|
|
74
|
+
}
|
|
75
|
+
if self.users:
|
|
76
|
+
proj_dict["users"] = self.users.to_dict()
|
|
77
|
+
return proj_dict
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
@dataclass
|
|
81
|
+
class Descriptions:
|
|
82
|
+
descriptions: dict[str, str]
|
|
83
|
+
|
|
84
|
+
def __post_init__(self) -> None:
|
|
85
|
+
for k, v in self.descriptions.items():
|
|
86
|
+
self.descriptions[k] = v.replace("\n", "<br/>")
|
|
87
|
+
|
|
88
|
+
def to_dict(self) -> dict[str, str]:
|
|
89
|
+
return self.descriptions
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
@dataclass
|
|
93
|
+
class Keywords:
|
|
94
|
+
keywords: list[str]
|
|
95
|
+
|
|
96
|
+
def to_dict(self) -> list[str]:
|
|
97
|
+
return sorted(self.keywords)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
@dataclass
|
|
101
|
+
class Licenses:
|
|
102
|
+
licenses: list[str]
|
|
103
|
+
|
|
104
|
+
def to_dict(self) -> list[str]:
|
|
105
|
+
return sorted(self.licenses)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
@dataclass
|
|
109
|
+
class Users:
|
|
110
|
+
users: list[User]
|
|
111
|
+
|
|
112
|
+
def to_dict(self) -> list[dict[str, Any]]:
|
|
113
|
+
return [x.to_dict() for x in self.users]
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
@dataclass
|
|
117
|
+
class User:
|
|
118
|
+
username: str
|
|
119
|
+
email: str
|
|
120
|
+
givenName: str
|
|
121
|
+
familyName: str
|
|
122
|
+
password: str | None
|
|
123
|
+
lang: str
|
|
124
|
+
isProjectAdmin: bool
|
|
125
|
+
|
|
126
|
+
def to_dict(self) -> dict[str, Any]:
|
|
127
|
+
usr_dict: dict[str, Any] = {
|
|
128
|
+
"username": self.username,
|
|
129
|
+
"email": self.email,
|
|
130
|
+
"givenName": self.givenName,
|
|
131
|
+
"familyName": self.familyName,
|
|
132
|
+
"password": self.password,
|
|
133
|
+
"lang": self.lang,
|
|
134
|
+
"status": True,
|
|
135
|
+
}
|
|
136
|
+
if self.isProjectAdmin:
|
|
137
|
+
usr_dict["projects"] = [":admin", ":member"]
|
|
138
|
+
else:
|
|
139
|
+
usr_dict["projects"] = [":member"]
|
|
140
|
+
return usr_dict
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
@dataclass
|
|
144
|
+
class PermissionsOverrulesUnprefixed:
|
|
145
|
+
"""
|
|
146
|
+
Data gathered from the column 'default_permissions_overrule' from 1 resources.xlsx / 1 properties.xlsx,
|
|
147
|
+
not yet enriched with ontology prefixes
|
|
148
|
+
"""
|
|
149
|
+
|
|
150
|
+
private: list[str]
|
|
151
|
+
limited_view: list[str]
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
@dataclass
|
|
155
|
+
class PermissionsOverrulesPrefixed:
|
|
156
|
+
"""
|
|
157
|
+
Object to gather 'default_permissions_overrule' infos from several resources.xlsx/properties.xlsx,
|
|
158
|
+
with ontology prefixes.
|
|
159
|
+
"""
|
|
160
|
+
|
|
161
|
+
private: list[str]
|
|
162
|
+
limited_view: list[str]
|
|
163
|
+
|
|
164
|
+
def add_overrules(self, new_overrules: PermissionsOverrulesUnprefixed, onto_prefix: str) -> None:
|
|
165
|
+
self.private.extend([f"{onto_prefix}:{p}" for p in new_overrules.private])
|
|
166
|
+
self.limited_view.extend([f"{onto_prefix}:{p}" for p in new_overrules.limited_view])
|
|
167
|
+
|
|
168
|
+
def non_empty(self) -> bool:
|
|
169
|
+
return bool(self.private or self.limited_view)
|
|
170
|
+
|
|
171
|
+
def serialize(self) -> dict[str, list[str]]:
|
|
172
|
+
return {
|
|
173
|
+
"private": self.private,
|
|
174
|
+
"limited_view": self.limited_view,
|
|
175
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from dataclasses import field
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@dataclass
|
|
6
|
+
class ListNodeNames:
|
|
7
|
+
"""
|
|
8
|
+
Contains the information to construct a list
|
|
9
|
+
|
|
10
|
+
Args:
|
|
11
|
+
lists_with_previous_cell_values: used to ensure that there are no duplicate node names
|
|
12
|
+
previous_node_names: used to ensure that there are no duplicate node names
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
lists_with_previous_cell_values: list[list[str]] = field(default_factory=list)
|
|
16
|
+
previous_node_names: list[str] = field(default_factory=list)
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclass
|
|
8
|
+
class OntoResource:
|
|
9
|
+
name: str
|
|
10
|
+
super: list[str]
|
|
11
|
+
labels: LanguageDict
|
|
12
|
+
comments: LanguageDict | None
|
|
13
|
+
cardinalities: list[ResourceCardinality] | None
|
|
14
|
+
|
|
15
|
+
def serialise(self) -> dict[str, Any]:
|
|
16
|
+
res: dict[str, Any] = {
|
|
17
|
+
"name": self.name,
|
|
18
|
+
"super": self.super,
|
|
19
|
+
"labels": self.labels.serialise(),
|
|
20
|
+
}
|
|
21
|
+
if self.comments:
|
|
22
|
+
res["comments"] = self.comments.serialise()
|
|
23
|
+
if self.cardinalities:
|
|
24
|
+
res["cardinalities"] = [x.serialise() for x in self.cardinalities]
|
|
25
|
+
return res
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@dataclass
|
|
29
|
+
class ResourceCardinality:
|
|
30
|
+
propname: str
|
|
31
|
+
cardinality: str
|
|
32
|
+
gui_order: int
|
|
33
|
+
|
|
34
|
+
def serialise(self) -> dict[str, str | int]:
|
|
35
|
+
return {"propname": self.propname, "cardinality": self.cardinality, "gui_order": self.gui_order}
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@dataclass
|
|
39
|
+
class OntoProperty:
|
|
40
|
+
name: str
|
|
41
|
+
super: list[str]
|
|
42
|
+
object: str
|
|
43
|
+
subject: str | None
|
|
44
|
+
labels: LanguageDict
|
|
45
|
+
comments: LanguageDict | None
|
|
46
|
+
gui_element: str
|
|
47
|
+
gui_attributes: GuiAttributes | None
|
|
48
|
+
|
|
49
|
+
def serialise(self) -> dict[str, Any]:
|
|
50
|
+
prop_dict: dict[str, Any] = {"name": self.name, "super": self.super, "object": self.object}
|
|
51
|
+
if self.subject:
|
|
52
|
+
prop_dict["subject"] = self.subject
|
|
53
|
+
prop_dict["labels"] = self.labels.serialise()
|
|
54
|
+
if self.comments:
|
|
55
|
+
prop_dict["comments"] = self.comments.serialise()
|
|
56
|
+
prop_dict["gui_element"] = self.gui_element
|
|
57
|
+
if self.gui_attributes:
|
|
58
|
+
prop_dict["gui_attributes"] = self.gui_attributes.serialise()
|
|
59
|
+
return prop_dict
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@dataclass
|
|
63
|
+
class LanguageDict:
|
|
64
|
+
lang_dict: dict[str, str]
|
|
65
|
+
|
|
66
|
+
def serialise(self) -> dict[str, str]:
|
|
67
|
+
sorted_dict = {k: self.lang_dict[k] for k in sorted(self.lang_dict.keys())}
|
|
68
|
+
return sorted_dict
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@dataclass
|
|
72
|
+
class GuiAttributes:
|
|
73
|
+
gui_attributes: dict[str, str]
|
|
74
|
+
|
|
75
|
+
def serialise(self) -> dict[str, str]:
|
|
76
|
+
return self.gui_attributes
|