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,322 @@
|
|
|
1
|
+
"""
|
|
2
|
+
The code in this file handles the arguments passed by the user from the command line and calls the requested actions.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
import subprocess
|
|
7
|
+
import sys
|
|
8
|
+
from collections.abc import Sequence
|
|
9
|
+
from importlib.metadata import version
|
|
10
|
+
|
|
11
|
+
import regex
|
|
12
|
+
import requests
|
|
13
|
+
from loguru import logger
|
|
14
|
+
from packaging.version import Version
|
|
15
|
+
from packaging.version import parse
|
|
16
|
+
|
|
17
|
+
from dsp_tools.cli.call_action import call_requested_action
|
|
18
|
+
from dsp_tools.cli.create_parsers import make_parser
|
|
19
|
+
from dsp_tools.config.logger_config import logger_config
|
|
20
|
+
from dsp_tools.config.warnings_config import initialize_warnings
|
|
21
|
+
from dsp_tools.error.exceptions import BaseError
|
|
22
|
+
from dsp_tools.error.exceptions import InputError
|
|
23
|
+
from dsp_tools.error.exceptions import InternalError
|
|
24
|
+
from dsp_tools.utils.ansi_colors import BOLD_RED
|
|
25
|
+
from dsp_tools.utils.ansi_colors import RESET_TO_DEFAULT
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def main() -> None:
|
|
29
|
+
"""
|
|
30
|
+
Main entry point of the program as referenced in pyproject.toml
|
|
31
|
+
"""
|
|
32
|
+
logger_config()
|
|
33
|
+
run(sys.argv[1:])
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def run(args: Sequence[str]) -> None:
|
|
37
|
+
"""
|
|
38
|
+
Main function of the CLI.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
args: a list of arguments passed by the user from the command line,
|
|
42
|
+
excluding the leading "dsp-tools" command.
|
|
43
|
+
|
|
44
|
+
Raises:
|
|
45
|
+
InputError: if user input was wrong
|
|
46
|
+
InternalError: if the user cannot fix it
|
|
47
|
+
"""
|
|
48
|
+
default_dsp_api_url = "http://0.0.0.0:3333"
|
|
49
|
+
default_dsp_ingest_url = "http://0.0.0.0:3340"
|
|
50
|
+
root_user_email = "root@example.com"
|
|
51
|
+
root_user_pw = "test"
|
|
52
|
+
|
|
53
|
+
parser = make_parser(
|
|
54
|
+
default_dsp_api_url=default_dsp_api_url,
|
|
55
|
+
root_user_email=root_user_email,
|
|
56
|
+
root_user_pw=root_user_pw,
|
|
57
|
+
)
|
|
58
|
+
parsed_arguments = _parse_arguments(
|
|
59
|
+
user_args=args,
|
|
60
|
+
parser=parser,
|
|
61
|
+
)
|
|
62
|
+
if not parsed_arguments.suppress_update_prompt:
|
|
63
|
+
_check_version()
|
|
64
|
+
_log_cli_arguments(parsed_arguments)
|
|
65
|
+
initialize_warnings()
|
|
66
|
+
|
|
67
|
+
try:
|
|
68
|
+
parsed_arguments = _derive_dsp_ingest_url(
|
|
69
|
+
parsed_arguments=parsed_arguments,
|
|
70
|
+
default_dsp_api_url=default_dsp_api_url,
|
|
71
|
+
default_dsp_ingest_url=default_dsp_ingest_url,
|
|
72
|
+
)
|
|
73
|
+
success = call_requested_action(parsed_arguments)
|
|
74
|
+
except BaseError as err:
|
|
75
|
+
logger.exception(f"The process was terminated because of an Error: {err.message}")
|
|
76
|
+
print(f"\n{BOLD_RED}The process was terminated because of an Error: {err.message}{RESET_TO_DEFAULT}")
|
|
77
|
+
success = False
|
|
78
|
+
except Exception as err: # noqa: BLE001 (blind-except)
|
|
79
|
+
logger.exception(err)
|
|
80
|
+
print(InternalError())
|
|
81
|
+
success = False
|
|
82
|
+
|
|
83
|
+
if not success:
|
|
84
|
+
logger.error("Terminate without success")
|
|
85
|
+
sys.exit(1)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def _check_version() -> None:
|
|
89
|
+
"""
|
|
90
|
+
Check if the installed version of dsp-tools is up-to-date.
|
|
91
|
+
If pypi.org cannot be reached, or if the latest version cannot be determined, do nothing.
|
|
92
|
+
If a new post-release version is available, print a message to the user, and return None.
|
|
93
|
+
If the base version (i.e. the major.minor.micro part of the version) is outdated,
|
|
94
|
+
ask the user if they want to exit or continue anyway.
|
|
95
|
+
"""
|
|
96
|
+
versioning_result = _get_dsp_tools_versions()
|
|
97
|
+
if not versioning_result:
|
|
98
|
+
return
|
|
99
|
+
installed, latest = versioning_result
|
|
100
|
+
if latest <= installed: # in the release-please PR, the installed version is always greater than the latest
|
|
101
|
+
return
|
|
102
|
+
|
|
103
|
+
msg = (
|
|
104
|
+
f"You are using DSP-TOOLS version {installed}, but version {latest} is available. "
|
|
105
|
+
"Consider upgrading via 'pip3 install --upgrade dsp-tools'.\n"
|
|
106
|
+
)
|
|
107
|
+
if latest.base_version == installed.base_version:
|
|
108
|
+
print(BOLD_RED + msg + RESET_TO_DEFAULT)
|
|
109
|
+
return
|
|
110
|
+
|
|
111
|
+
msg += "Continue anyway? [y/n]"
|
|
112
|
+
resp = None
|
|
113
|
+
while resp not in ["y", "n"]:
|
|
114
|
+
resp = input(BOLD_RED + msg + RESET_TO_DEFAULT)
|
|
115
|
+
if resp == "y":
|
|
116
|
+
return
|
|
117
|
+
sys.exit(1)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def _get_dsp_tools_versions() -> tuple[Version, Version] | None:
|
|
121
|
+
try:
|
|
122
|
+
response = requests.get("https://pypi.org/pypi/dsp-tools/json", timeout=5)
|
|
123
|
+
except (requests.ConnectionError, requests.ReadTimeout):
|
|
124
|
+
return None
|
|
125
|
+
if not response.ok:
|
|
126
|
+
return None
|
|
127
|
+
latest = parse(response.json()["info"]["version"])
|
|
128
|
+
installed = parse(version("dsp-tools"))
|
|
129
|
+
return installed, latest
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def _print_version_info() -> None:
|
|
133
|
+
"""
|
|
134
|
+
Print version information including installed version and latest available version from PyPI.
|
|
135
|
+
If PyPI cannot be reached, only print the installed version.
|
|
136
|
+
"""
|
|
137
|
+
installed_version = version("dsp-tools")
|
|
138
|
+
print(f"DSP-TOOLS version {installed_version}")
|
|
139
|
+
|
|
140
|
+
versioning_result = _get_dsp_tools_versions()
|
|
141
|
+
if versioning_result:
|
|
142
|
+
installed, latest = versioning_result
|
|
143
|
+
if latest > installed:
|
|
144
|
+
print(f"Latest version available: {latest}")
|
|
145
|
+
elif latest == installed:
|
|
146
|
+
print("You are using the latest version")
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def _parse_arguments(
|
|
150
|
+
user_args: Sequence[str],
|
|
151
|
+
parser: argparse.ArgumentParser,
|
|
152
|
+
) -> argparse.Namespace:
|
|
153
|
+
"""
|
|
154
|
+
Parse the user-provided CLI arguments.
|
|
155
|
+
If --version flag is provided, print version information and exit.
|
|
156
|
+
If no action is provided,
|
|
157
|
+
print the help text and exit with error code 1.
|
|
158
|
+
|
|
159
|
+
Args:
|
|
160
|
+
user_args: user-provided CLI arguments
|
|
161
|
+
parser: parser used to parse the arguments
|
|
162
|
+
|
|
163
|
+
Returns:
|
|
164
|
+
parsed arguments
|
|
165
|
+
"""
|
|
166
|
+
args = parser.parse_args(user_args)
|
|
167
|
+
if hasattr(args, "version") and args.version:
|
|
168
|
+
_print_version_info()
|
|
169
|
+
sys.exit(0)
|
|
170
|
+
if not hasattr(args, "action"):
|
|
171
|
+
parser.print_help(sys.stderr)
|
|
172
|
+
sys.exit(1)
|
|
173
|
+
return args
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def _get_version() -> str:
|
|
177
|
+
try:
|
|
178
|
+
pip_output = subprocess.run("pip freeze".split(), check=False, capture_output=True).stdout.decode("utf-8")
|
|
179
|
+
dsp_tools_lines = [x for x in pip_output.split("\n") if "dsp-tools" in x]
|
|
180
|
+
except FileNotFoundError:
|
|
181
|
+
dsp_tools_lines = []
|
|
182
|
+
if not dsp_tools_lines:
|
|
183
|
+
# if the virtual environment was activated with env variables instead of executing activation commands,
|
|
184
|
+
# dsp-tools will run correctly, but "pip freeze" won't show dsp-tools
|
|
185
|
+
return version("dsp-tools")
|
|
186
|
+
_detail_version = dsp_tools_lines[0]
|
|
187
|
+
# _detail_version has one of the following formats:
|
|
188
|
+
# - 'dsp-tools==5.0.3\n'
|
|
189
|
+
# - 'dsp-tools==5.6.0.post9\n'
|
|
190
|
+
# - 'dsp-tools @ git+https://github.com/dasch-swiss/dsp-tools.git@1f95f8d1b79bd5170a652c0d04e7ada417d76734\n'
|
|
191
|
+
# - '-e git+ssh://git@github.com/dasch-swiss/dsp-tools.git@af9a35692b542676f2aa0a802ca7fc3b35f5713d#egg=dsp_tools\n'
|
|
192
|
+
# - ''
|
|
193
|
+
if version_number := regex.search(r"\d+\.\d+\.\d+(\.(post|dev|pre)\d+)?", _detail_version):
|
|
194
|
+
return version_number.group(0)
|
|
195
|
+
if regex.search(r"github.com", _detail_version):
|
|
196
|
+
return _detail_version.replace("\n", "")
|
|
197
|
+
return version("dsp-tools")
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def _log_cli_arguments(parsed_args: argparse.Namespace) -> None:
|
|
201
|
+
"""
|
|
202
|
+
Log the CLI arguments passed by the user from the command line.
|
|
203
|
+
|
|
204
|
+
Args:
|
|
205
|
+
parsed_args: parsed arguments
|
|
206
|
+
"""
|
|
207
|
+
metadata_lines = [
|
|
208
|
+
f"DSP-TOOLS: Called the action '{parsed_args.action}' from the command line",
|
|
209
|
+
f"DSP-TOOLS version: {_get_version()}",
|
|
210
|
+
f"Location of this installation: {__file__}",
|
|
211
|
+
"CLI arguments:",
|
|
212
|
+
]
|
|
213
|
+
metadata_lines = [f"*** {line}" for line in metadata_lines]
|
|
214
|
+
|
|
215
|
+
parameter_lines = []
|
|
216
|
+
parameters_to_log = {key: value for key, value in vars(parsed_args).items() if key != "action"}
|
|
217
|
+
longest_key_length = max((len(key) for key in parameters_to_log), default=0)
|
|
218
|
+
for key, value in parameters_to_log.items():
|
|
219
|
+
if key == "password":
|
|
220
|
+
parameter_lines.append(f"{key:<{longest_key_length}} = {'*' * len(value)}")
|
|
221
|
+
else:
|
|
222
|
+
parameter_lines.append(f"{key:<{longest_key_length}} = {value}")
|
|
223
|
+
parameter_lines = parameter_lines or ["(no parameters)"]
|
|
224
|
+
parameter_lines = [f"*** {line}" for line in parameter_lines]
|
|
225
|
+
|
|
226
|
+
asterisk_count = max(len(line) for line in metadata_lines + parameter_lines)
|
|
227
|
+
logger.info("*" * asterisk_count)
|
|
228
|
+
for line in metadata_lines:
|
|
229
|
+
logger.info(line)
|
|
230
|
+
for line in parameter_lines:
|
|
231
|
+
logger.info(line)
|
|
232
|
+
logger.info("*" * asterisk_count)
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
def _get_canonical_server_and_dsp_ingest_url(
|
|
236
|
+
server: str,
|
|
237
|
+
default_dsp_api_url: str,
|
|
238
|
+
default_dsp_ingest_url: str,
|
|
239
|
+
) -> tuple[str, str]:
|
|
240
|
+
"""
|
|
241
|
+
Based on the DSP server URL passed by the user,
|
|
242
|
+
transform it to its canonical form,
|
|
243
|
+
and derive the ingest server URL from it.
|
|
244
|
+
|
|
245
|
+
If the DSP server URL points to port 3333 on localhost,
|
|
246
|
+
the ingest server will point to port 3340 on localhost.
|
|
247
|
+
|
|
248
|
+
If the DSP server URL points to a remote server ending in "dasch.swiss",
|
|
249
|
+
modify it (if necessary) to point to the "api" subdomain of that server,
|
|
250
|
+
and add a new "dsp_ingest_url" argument pointing to the "ingest" subdomain of that server.
|
|
251
|
+
|
|
252
|
+
Args:
|
|
253
|
+
server: DSP server URL passed by the user
|
|
254
|
+
default_dsp_api_url: default DSP server on localhost
|
|
255
|
+
default_dsp_ingest_url: default ingest server on localhost
|
|
256
|
+
|
|
257
|
+
Raises:
|
|
258
|
+
InputError: if the DSP server URL passed by the user is invalid
|
|
259
|
+
|
|
260
|
+
Returns:
|
|
261
|
+
canonical DSP URL and ingest server URL
|
|
262
|
+
"""
|
|
263
|
+
localhost_match = regex.search(r"(0\.0\.0\.0|localhost):3333", server)
|
|
264
|
+
remote_url_match = regex.search(
|
|
265
|
+
r"^(?:https?:\/\/)?(?:admin\.|api\.|ingest\.|app\.)?((?:.+\.)?dasch)\.swiss", server
|
|
266
|
+
)
|
|
267
|
+
|
|
268
|
+
if localhost_match:
|
|
269
|
+
server = default_dsp_api_url
|
|
270
|
+
dsp_ingest_url = default_dsp_ingest_url
|
|
271
|
+
elif remote_url_match:
|
|
272
|
+
server = f"https://api.{remote_url_match.group(1)}.swiss"
|
|
273
|
+
dsp_ingest_url = f"https://ingest.{remote_url_match.group(1)}.swiss"
|
|
274
|
+
else:
|
|
275
|
+
logger.error(f"Invalid DSP server URL '{server}'")
|
|
276
|
+
raise InputError(f"ERROR: Invalid DSP server URL '{server}'")
|
|
277
|
+
|
|
278
|
+
logger.info(f"Using DSP server '{server}' and ingest server '{dsp_ingest_url}'")
|
|
279
|
+
print(f"Using DSP server '{server}' and ingest server '{dsp_ingest_url}'")
|
|
280
|
+
|
|
281
|
+
return server, dsp_ingest_url
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
def _derive_dsp_ingest_url(
|
|
285
|
+
parsed_arguments: argparse.Namespace,
|
|
286
|
+
default_dsp_api_url: str,
|
|
287
|
+
default_dsp_ingest_url: str,
|
|
288
|
+
) -> argparse.Namespace:
|
|
289
|
+
"""
|
|
290
|
+
Modify the parsed arguments so that the DSP and ingest server URLs are correct.
|
|
291
|
+
Based on the DSP server URL passed by the user,
|
|
292
|
+
transform it to its canonical form,
|
|
293
|
+
and derive the ingest server URL from it.
|
|
294
|
+
|
|
295
|
+
Args:
|
|
296
|
+
parsed_arguments: CLI arguments passed by the user, parsed by argparse
|
|
297
|
+
default_dsp_api_url: default DSP server on localhost
|
|
298
|
+
default_dsp_ingest_url: default ingest server on localhost
|
|
299
|
+
|
|
300
|
+
Raises:
|
|
301
|
+
InputError: if the DSP server URL passed by the user is invalid
|
|
302
|
+
|
|
303
|
+
Returns:
|
|
304
|
+
the modified arguments
|
|
305
|
+
"""
|
|
306
|
+
if not hasattr(parsed_arguments, "server"):
|
|
307
|
+
# some CLI actions (like excel2json, excel2xml, start-stack, ...) don't have a server at all
|
|
308
|
+
return parsed_arguments
|
|
309
|
+
|
|
310
|
+
server, dsp_ingest_url = _get_canonical_server_and_dsp_ingest_url(
|
|
311
|
+
server=parsed_arguments.server,
|
|
312
|
+
default_dsp_api_url=default_dsp_api_url,
|
|
313
|
+
default_dsp_ingest_url=default_dsp_ingest_url,
|
|
314
|
+
)
|
|
315
|
+
parsed_arguments.server = server
|
|
316
|
+
parsed_arguments.dsp_ingest_url = dsp_ingest_url
|
|
317
|
+
|
|
318
|
+
return parsed_arguments
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
if __name__ == "__main__":
|
|
322
|
+
main()
|
dsp_tools/cli/utils.py
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import subprocess
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
import requests
|
|
6
|
+
from loguru import logger
|
|
7
|
+
|
|
8
|
+
from dsp_tools.cli.args import NetworkRequirements
|
|
9
|
+
from dsp_tools.cli.args import PathDependencies
|
|
10
|
+
from dsp_tools.cli.args import ServerCredentials
|
|
11
|
+
from dsp_tools.error.exceptions import DockerNotReachableError
|
|
12
|
+
from dsp_tools.error.exceptions import DspApiNotReachableError
|
|
13
|
+
from dsp_tools.error.exceptions import UserDirectoryNotFoundError
|
|
14
|
+
from dsp_tools.error.exceptions import UserFilepathNotFoundError
|
|
15
|
+
|
|
16
|
+
LOCALHOST_API = "http://0.0.0.0:3333"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def get_creds(args: argparse.Namespace) -> ServerCredentials:
|
|
20
|
+
return ServerCredentials(
|
|
21
|
+
server=args.server,
|
|
22
|
+
user=args.user,
|
|
23
|
+
password=args.password,
|
|
24
|
+
dsp_ingest_url=args.dsp_ingest_url,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def check_input_dependencies(
|
|
29
|
+
paths: PathDependencies | None = None, network_dependencies: NetworkRequirements | None = None
|
|
30
|
+
) -> None:
|
|
31
|
+
if paths:
|
|
32
|
+
check_path_dependencies(paths)
|
|
33
|
+
if network_dependencies:
|
|
34
|
+
_check_network_health(network_dependencies)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def check_path_dependencies(paths: PathDependencies) -> None:
|
|
38
|
+
for f_path in paths.required_files:
|
|
39
|
+
_check_filepath_exists(f_path)
|
|
40
|
+
for dir_path in paths.required_directories:
|
|
41
|
+
_check_directory_exists(dir_path)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _check_filepath_exists(file_path: Path) -> None:
|
|
45
|
+
if not file_path.exists():
|
|
46
|
+
raise UserFilepathNotFoundError(file_path)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _check_directory_exists(dir_path: Path) -> None:
|
|
50
|
+
if not dir_path.is_dir():
|
|
51
|
+
raise UserDirectoryNotFoundError(dir_path)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _check_network_health(network_requirements: NetworkRequirements) -> None:
|
|
55
|
+
if network_requirements.api_url == LOCALHOST_API or network_requirements.always_requires_docker:
|
|
56
|
+
check_docker_health()
|
|
57
|
+
_check_api_health(network_requirements.api_url)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def check_docker_health() -> None:
|
|
61
|
+
if subprocess.run("docker stats --no-stream".split(), check=False, capture_output=True, timeout=3).returncode != 0:
|
|
62
|
+
raise DockerNotReachableError()
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def _check_api_health(api_url: str) -> None:
|
|
66
|
+
health_url = f"{api_url}/health"
|
|
67
|
+
msg = (
|
|
68
|
+
"The DSP-API could not be reached. Please check if your stack is healthy "
|
|
69
|
+
"or start a stack with 'dsp-tools start-stack' if none is running."
|
|
70
|
+
)
|
|
71
|
+
try:
|
|
72
|
+
response = requests.get(health_url, timeout=2)
|
|
73
|
+
if not response.ok:
|
|
74
|
+
if api_url != LOCALHOST_API:
|
|
75
|
+
msg = (
|
|
76
|
+
f"The DSP-API could not be reached (returned status {response.status_code}). "
|
|
77
|
+
f"Please contact the DaSCH engineering team for help."
|
|
78
|
+
)
|
|
79
|
+
logger.error(msg)
|
|
80
|
+
raise DspApiNotReachableError(msg)
|
|
81
|
+
logger.debug(f"DSP API health check passed: {health_url}")
|
|
82
|
+
except requests.exceptions.RequestException as e:
|
|
83
|
+
logger.error(e)
|
|
84
|
+
if api_url != LOCALHOST_API:
|
|
85
|
+
msg = "The DSP-API responded with a request exception. Please contact the DaSCH engineering team for help."
|
|
86
|
+
logger.error(msg)
|
|
87
|
+
raise DspApiNotReachableError(msg) from None
|