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,428 @@
|
|
|
1
|
+
import contextlib
|
|
2
|
+
import importlib.resources
|
|
3
|
+
import shutil
|
|
4
|
+
import subprocess
|
|
5
|
+
import time
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import Optional
|
|
9
|
+
|
|
10
|
+
import regex
|
|
11
|
+
import requests
|
|
12
|
+
import yaml
|
|
13
|
+
from jinja2 import Template
|
|
14
|
+
from loguru import logger
|
|
15
|
+
|
|
16
|
+
from dsp_tools.error.exceptions import InputError
|
|
17
|
+
from dsp_tools.error.exceptions import PermanentConnectionError
|
|
18
|
+
from dsp_tools.utils.request_utils import RequestParameters
|
|
19
|
+
from dsp_tools.utils.request_utils import log_request
|
|
20
|
+
from dsp_tools.utils.request_utils import log_response
|
|
21
|
+
|
|
22
|
+
MAX_FILE_SIZE = 100_000
|
|
23
|
+
MINUTE = 60
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@dataclass(frozen=True)
|
|
27
|
+
class StackConfiguration:
|
|
28
|
+
"""
|
|
29
|
+
Groups together configuration information for the StackHandler.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
max_file_size: max. multimedia file size allowed for ingest, in MB (max: 100'000)
|
|
33
|
+
enforce_docker_system_prune: if True, prune Docker without asking the user
|
|
34
|
+
suppress_docker_system_prune: if True, don't prune Docker (and don't ask)
|
|
35
|
+
latest_dev_version: if True, start DSP-API from repo's main branch, instead of the latest deployed version
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
max_file_size: Optional[int] = None
|
|
39
|
+
enforce_docker_system_prune: bool = False
|
|
40
|
+
suppress_docker_system_prune: bool = False
|
|
41
|
+
latest_dev_version: bool = False
|
|
42
|
+
upload_test_data: bool = False
|
|
43
|
+
custom_host: Optional[str] = None
|
|
44
|
+
|
|
45
|
+
def __post_init__(self) -> None:
|
|
46
|
+
"""
|
|
47
|
+
Validate the input parameters passed by the user.
|
|
48
|
+
|
|
49
|
+
Raises:
|
|
50
|
+
InputError: if one of the parameters is invalid
|
|
51
|
+
"""
|
|
52
|
+
if self.max_file_size is not None and not 1 <= self.max_file_size <= MAX_FILE_SIZE:
|
|
53
|
+
raise InputError(f"max_file_size must be between 1 and {MAX_FILE_SIZE}")
|
|
54
|
+
if self.enforce_docker_system_prune and self.suppress_docker_system_prune:
|
|
55
|
+
raise InputError('The arguments "--prune" and "--no-prune" are mutually exclusive')
|
|
56
|
+
if self.custom_host is not None and not regex.match(
|
|
57
|
+
r"^(((\d{1,3}\.){3}\d{1,3})|((([-\w_~]+\.)*([a-z]){2,})))$", self.custom_host
|
|
58
|
+
):
|
|
59
|
+
raise InputError("Invalid format for custom host. Please, enter an IP or a domain name.")
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class StackHandler:
|
|
63
|
+
"""This class contains functions to start and stop the Docker containers of DSP-API and DSP-APP."""
|
|
64
|
+
|
|
65
|
+
__stack_configuration: StackConfiguration
|
|
66
|
+
__url_prefix: str
|
|
67
|
+
__docker_path_of_user: Path
|
|
68
|
+
__localhost_url = "http://0.0.0.0"
|
|
69
|
+
|
|
70
|
+
def __init__(self, stack_configuration: StackConfiguration) -> None:
|
|
71
|
+
"""
|
|
72
|
+
Initialize a StackHandler with a StackConfiguration
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
stack_configuration: configuration information for the StackHandler
|
|
76
|
+
"""
|
|
77
|
+
self.__stack_configuration = stack_configuration
|
|
78
|
+
self.__url_prefix = self._get_url_prefix()
|
|
79
|
+
self.__docker_path_of_user = Path.home() / Path(".dsp-tools/start-stack")
|
|
80
|
+
self.__docker_path_of_user.mkdir(parents=True, exist_ok=True)
|
|
81
|
+
|
|
82
|
+
def _get_url_prefix(self) -> str:
|
|
83
|
+
"""
|
|
84
|
+
The start-stack command needs some files from the DSP-API repository.
|
|
85
|
+
By default, start-stack starts the latest deployed version of DSP-API.
|
|
86
|
+
Since the last deployment, the DSP-API repository may have been updated.
|
|
87
|
+
For this reason, we need to know the commit hash of the DSP-API version that is currently deployed,
|
|
88
|
+
so that the files can be retrieved from the correct commit.
|
|
89
|
+
|
|
90
|
+
This function reads the version tag in the docker-compose.yml file,
|
|
91
|
+
and constructs the URL prefix necessary to retrieve the files from the DSP-API repository.
|
|
92
|
+
|
|
93
|
+
If the latest development version of DSP-API is started,
|
|
94
|
+
the URL prefix points to the main branch of the DSP-API repository.
|
|
95
|
+
|
|
96
|
+
Returns:
|
|
97
|
+
URL prefix used to retrieve files from the DSP-API repository
|
|
98
|
+
"""
|
|
99
|
+
url_prefix_base = "https://raw.githubusercontent.com/dasch-swiss/dsp-api"
|
|
100
|
+
|
|
101
|
+
if self.__stack_configuration.latest_dev_version:
|
|
102
|
+
return f"{url_prefix_base}/main/"
|
|
103
|
+
|
|
104
|
+
docker_compose_pth = importlib.resources.files("dsp_tools").joinpath("resources/start-stack/docker-compose.yml")
|
|
105
|
+
docker_compose = yaml.safe_load(docker_compose_pth.read_bytes())
|
|
106
|
+
tag = docker_compose["services"]["api"]["image"].split(":")[-1]
|
|
107
|
+
|
|
108
|
+
return f"{url_prefix_base}/{tag}/"
|
|
109
|
+
|
|
110
|
+
def _copy_resources_to_home_dir(self) -> None:
|
|
111
|
+
"""
|
|
112
|
+
On most systems, Docker is not allowed to access files outside of the user's home directory.
|
|
113
|
+
For this reason, copy the contents of the distribution (src/dsp_tools/resources/start-stack)
|
|
114
|
+
to the user's home directory (~/.dsp-tools/start-stack).
|
|
115
|
+
|
|
116
|
+
Important: The files of the home directory might have been modified
|
|
117
|
+
by an earlier run of this method.
|
|
118
|
+
So, this method must always be called, at every run of start-stack.
|
|
119
|
+
"""
|
|
120
|
+
logger.debug("Copying resources to home directory ...")
|
|
121
|
+
docker_path_of_distribution = importlib.resources.files("dsp_tools").joinpath("resources/start-stack")
|
|
122
|
+
for file in docker_path_of_distribution.iterdir():
|
|
123
|
+
with importlib.resources.as_file(file) as f:
|
|
124
|
+
file_path = Path(f)
|
|
125
|
+
shutil.copy(file_path, self.__docker_path_of_user / file.name)
|
|
126
|
+
if not self.__stack_configuration.latest_dev_version:
|
|
127
|
+
Path(self.__docker_path_of_user / "docker-compose.override.yml").unlink()
|
|
128
|
+
|
|
129
|
+
def _set_custom_host(self) -> None:
|
|
130
|
+
"""
|
|
131
|
+
To ensure the frontend can communicate with a backend on a different server, the host in the environments
|
|
132
|
+
needs to be changed.
|
|
133
|
+
By design the IRIs match the host of the database.
|
|
134
|
+
|
|
135
|
+
This is done by overriding the environment variables in the docker-compose.yml and by replacing the
|
|
136
|
+
configuration for the frontend.
|
|
137
|
+
"""
|
|
138
|
+
if self.__stack_configuration.custom_host is not None:
|
|
139
|
+
logger.debug("Setting custom host...")
|
|
140
|
+
self.__localhost_url = f"http://{self.__stack_configuration.custom_host}"
|
|
141
|
+
|
|
142
|
+
docker_template_path = importlib.resources.files("dsp_tools").joinpath(
|
|
143
|
+
"resources/start-stack/docker-compose.override-host.j2"
|
|
144
|
+
)
|
|
145
|
+
docker_template = Template(docker_template_path.read_text(encoding="utf-8"))
|
|
146
|
+
docker_template_rendered = docker_template.render(CUSTOM_HOST=self.__stack_configuration.custom_host)
|
|
147
|
+
Path(self.__docker_path_of_user / "docker-compose.override-host.yml").write_text(
|
|
148
|
+
docker_template_rendered, encoding="utf-8"
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
dsp_app_config_template_path = importlib.resources.files("dsp_tools").joinpath(
|
|
152
|
+
"resources/start-stack/dsp-app-config.override-host.j2"
|
|
153
|
+
)
|
|
154
|
+
dsp_app_config_template = Template(dsp_app_config_template_path.read_text(encoding="utf-8"))
|
|
155
|
+
dsp_app_config_rendered = dsp_app_config_template.render(CUSTOM_HOST=self.__stack_configuration.custom_host)
|
|
156
|
+
Path(self.__docker_path_of_user / "dsp-app-config.json").unlink()
|
|
157
|
+
Path(self.__docker_path_of_user / "dsp-app-config.json").write_text(
|
|
158
|
+
dsp_app_config_rendered, encoding="utf-8"
|
|
159
|
+
)
|
|
160
|
+
Path(self.__docker_path_of_user / "docker-compose.override-host.j2").unlink()
|
|
161
|
+
Path(self.__docker_path_of_user / "dsp-app-config.override-host.j2").unlink()
|
|
162
|
+
|
|
163
|
+
def _get_sipi_docker_config_lua(self) -> None:
|
|
164
|
+
"""
|
|
165
|
+
Retrieve the config file sipi.docker-config.lua from the DSP-API repository,
|
|
166
|
+
and set the max_file_size parameter if necessary.
|
|
167
|
+
|
|
168
|
+
Raises:
|
|
169
|
+
InputError: if max_file_size is set but cannot be injected into sipi.docker-config.lua
|
|
170
|
+
"""
|
|
171
|
+
logger.debug("Retrieving sipi.docker-config.lua...")
|
|
172
|
+
docker_config_lua_response = requests.get(f"{self.__url_prefix}sipi/config/sipi.docker-config.lua", timeout=30)
|
|
173
|
+
docker_config_lua_text = docker_config_lua_response.text
|
|
174
|
+
if self.__stack_configuration.max_file_size:
|
|
175
|
+
max_post_size_regex = r"max_post_size ?= ?[\'\"]?\d+[MG][\'\"]?"
|
|
176
|
+
if not regex.search(max_post_size_regex, docker_config_lua_text):
|
|
177
|
+
raise InputError("Unable to set max_file_size. Please try again without this flag.")
|
|
178
|
+
docker_config_lua_text = regex.sub(
|
|
179
|
+
max_post_size_regex,
|
|
180
|
+
f"max_post_size = '{self.__stack_configuration.max_file_size}M'",
|
|
181
|
+
docker_config_lua_text,
|
|
182
|
+
)
|
|
183
|
+
with open(self.__docker_path_of_user / "sipi.docker-config.lua", "w", encoding="utf-8") as f:
|
|
184
|
+
f.write(docker_config_lua_text)
|
|
185
|
+
|
|
186
|
+
def _start_up_fuseki(self) -> None:
|
|
187
|
+
"""
|
|
188
|
+
Start up the Docker container of the fuseki database.
|
|
189
|
+
|
|
190
|
+
Raises:
|
|
191
|
+
InputError: if the database cannot be started
|
|
192
|
+
"""
|
|
193
|
+
logger.debug("Starting up the fuseki container...")
|
|
194
|
+
cmd = "docker compose up -d db".split()
|
|
195
|
+
completed_process = subprocess.run(cmd, cwd=self.__docker_path_of_user, check=False)
|
|
196
|
+
if not completed_process or completed_process.returncode != 0:
|
|
197
|
+
msg = "Cannot start the API: Error while executing 'docker compose up -d db'"
|
|
198
|
+
logger.error(f"{msg}. completed_process = '{vars(completed_process)}'")
|
|
199
|
+
raise InputError(msg)
|
|
200
|
+
|
|
201
|
+
def _wait_for_fuseki(self) -> None:
|
|
202
|
+
"""
|
|
203
|
+
Wait up to 6 minutes, until the fuseki database is up and running.
|
|
204
|
+
This function imitates the behaviour of the script dsp-api/webapi/scripts/wait-for-db.sh.
|
|
205
|
+
"""
|
|
206
|
+
logger.debug("Waiting for the fuseki container to be up and running...")
|
|
207
|
+
for _ in range(6 * 60):
|
|
208
|
+
try:
|
|
209
|
+
response = requests.get(f"{self.__localhost_url}:3030/$/server", auth=("admin", "test"), timeout=10)
|
|
210
|
+
if response.ok:
|
|
211
|
+
logger.debug("Fuseki is now up and running.")
|
|
212
|
+
break
|
|
213
|
+
except Exception: # noqa: BLE001 (blind-except)
|
|
214
|
+
time.sleep(1)
|
|
215
|
+
time.sleep(1)
|
|
216
|
+
|
|
217
|
+
def _load_data_into_repo(self) -> None:
|
|
218
|
+
"""
|
|
219
|
+
Load some basic ontologies and data into the repository.
|
|
220
|
+
This function imitates the behaviour of the script
|
|
221
|
+
dsp-api/webapi/scripts/fuseki-init-knora-test.sh.
|
|
222
|
+
|
|
223
|
+
Raises:
|
|
224
|
+
InputError: if one of the graphs cannot be created
|
|
225
|
+
"""
|
|
226
|
+
logger.debug("Loading data into the 'dsp-repo' repository...")
|
|
227
|
+
graph_prefix = f"{self.__localhost_url}:3030/dsp-repo/data?graph="
|
|
228
|
+
ttl_files = [
|
|
229
|
+
("webapi/src/main/resources/knora-ontologies/knora-admin.ttl", "http://www.knora.org/ontology/knora-admin"),
|
|
230
|
+
("webapi/src/main/resources/knora-ontologies/knora-base.ttl", "http://www.knora.org/ontology/knora-base"),
|
|
231
|
+
("webapi/src/main/resources/knora-ontologies/standoff-onto.ttl", "http://www.knora.org/ontology/standoff"),
|
|
232
|
+
("webapi/src/main/resources/knora-ontologies/standoff-data.ttl", "http://www.knora.org/data/standoff"),
|
|
233
|
+
("webapi/src/main/resources/knora-ontologies/salsah-gui.ttl", "http://www.knora.org/ontology/salsah-gui"),
|
|
234
|
+
("test_data/project_data/admin-data.ttl", "http://www.knora.org/data/admin"),
|
|
235
|
+
("test_data/project_data/permissions-data.ttl", "http://www.knora.org/data/permissions"),
|
|
236
|
+
("test_data/project_ontologies/anything-onto.ttl", "http://www.knora.org/ontology/0001/anything"),
|
|
237
|
+
("test_data/project_data/anything-data.ttl", "http://www.knora.org/data/0001/anything"),
|
|
238
|
+
]
|
|
239
|
+
for ttl_file, graph in ttl_files:
|
|
240
|
+
ttl_response = requests.get(self.__url_prefix + ttl_file, timeout=30)
|
|
241
|
+
if not ttl_response.ok:
|
|
242
|
+
msg = f"Cannot start DSP-API: Error when retrieving '{self.__url_prefix + ttl_file}'"
|
|
243
|
+
logger.error(f"{msg}'. response = {vars(ttl_response)}")
|
|
244
|
+
raise InputError(msg)
|
|
245
|
+
ttl_text = ttl_response.text
|
|
246
|
+
response = requests.post(
|
|
247
|
+
graph_prefix + graph,
|
|
248
|
+
files={"file": ("file.ttl", ttl_text, "text/turtle; charset: utf-8")},
|
|
249
|
+
auth=("admin", "test"),
|
|
250
|
+
timeout=30,
|
|
251
|
+
)
|
|
252
|
+
if not response.ok:
|
|
253
|
+
logger.error(f"Cannot start DSP-API: Error when creating graph '{graph}'. response = {vars(response)}")
|
|
254
|
+
raise InputError(f"Cannot start DSP-API: Error when creating graph '{graph}'")
|
|
255
|
+
|
|
256
|
+
def _create_admin_user(self) -> None:
|
|
257
|
+
"""
|
|
258
|
+
This function adds the default system admin user to the database.
|
|
259
|
+
The password is the hash for "test".
|
|
260
|
+
|
|
261
|
+
Raises:
|
|
262
|
+
InputError: If the user cannot be created.
|
|
263
|
+
"""
|
|
264
|
+
logger.debug("Creating the default admin user...")
|
|
265
|
+
graph_prefix = f"{self.__localhost_url}:3030/dsp-repo/data?graph="
|
|
266
|
+
admin_graph = "http://www.knora.org/data/admin"
|
|
267
|
+
admin_user = """
|
|
268
|
+
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
|
|
269
|
+
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
|
|
270
|
+
@prefix knora-admin: <http://www.knora.org/ontology/knora-admin#> .
|
|
271
|
+
|
|
272
|
+
<http://rdfh.ch/users/root>
|
|
273
|
+
rdf:type knora-admin:User ;
|
|
274
|
+
knora-admin:username "root"^^xsd:string ;
|
|
275
|
+
knora-admin:email "root@example.com"^^xsd:string ;
|
|
276
|
+
knora-admin:givenName "System"^^xsd:string ;
|
|
277
|
+
knora-admin:familyName "Administrator"^^xsd:string ;
|
|
278
|
+
knora-admin:password "$2a$12$7XEBehimXN1rbhmVgQsyve08.vtDmKK7VMin4AdgCEtE4DWgfQbTK"^^xsd:string ;
|
|
279
|
+
knora-admin:phone "123456"^^xsd:string ;
|
|
280
|
+
knora-admin:preferredLanguage "en"^^xsd:string ;
|
|
281
|
+
knora-admin:status "true"^^xsd:boolean ;
|
|
282
|
+
knora-admin:isInSystemAdminGroup "true"^^xsd:boolean .
|
|
283
|
+
"""
|
|
284
|
+
response = requests.post(
|
|
285
|
+
graph_prefix + admin_graph,
|
|
286
|
+
files={"file": ("file.ttl", admin_user, "text/turtle; charset: utf-8")},
|
|
287
|
+
auth=("admin", "test"),
|
|
288
|
+
timeout=30,
|
|
289
|
+
)
|
|
290
|
+
if not response.ok:
|
|
291
|
+
logger.error(f"Cannot start DSP-API: Error when creating the admin user. response = {vars(response)}")
|
|
292
|
+
raise InputError("Cannot start DSP-API: Error when creating the admin user.")
|
|
293
|
+
|
|
294
|
+
def _initialize_fuseki(self) -> None:
|
|
295
|
+
"""
|
|
296
|
+
Load some basic ontologies and data into the 'dsp-repo' repository.
|
|
297
|
+
"""
|
|
298
|
+
if self.__stack_configuration.upload_test_data:
|
|
299
|
+
self._load_data_into_repo()
|
|
300
|
+
else:
|
|
301
|
+
self._create_admin_user()
|
|
302
|
+
|
|
303
|
+
def _start_remaining_docker_containers(self) -> None:
|
|
304
|
+
"""
|
|
305
|
+
Start the other Docker containers that are not running yet.
|
|
306
|
+
(Fuseki is already running at this point.)
|
|
307
|
+
"""
|
|
308
|
+
compose_str = "docker compose -f docker-compose.yml"
|
|
309
|
+
if self.__stack_configuration.latest_dev_version:
|
|
310
|
+
logger.debug("In order to get the latest dev version, run 'docker compose pull' ...")
|
|
311
|
+
subprocess.run("docker compose pull".split(), cwd=self.__docker_path_of_user, check=True)
|
|
312
|
+
compose_str += " -f docker-compose.override.yml"
|
|
313
|
+
if self.__stack_configuration.custom_host is not None:
|
|
314
|
+
compose_str += " -f docker-compose.override-host.yml"
|
|
315
|
+
compose_str += " up -d"
|
|
316
|
+
logger.debug(f"Running '{compose_str}' ...")
|
|
317
|
+
subprocess.run(compose_str.split(), cwd=self.__docker_path_of_user, check=True)
|
|
318
|
+
|
|
319
|
+
def _wait_for_api(self) -> None:
|
|
320
|
+
"""
|
|
321
|
+
Wait until the API is up and running.
|
|
322
|
+
This mimicks the behaviour of the script webapi/scripts/wait-for-api.sh in the DSP-API repository.
|
|
323
|
+
"""
|
|
324
|
+
logger.debug("Waiting for the API to start...")
|
|
325
|
+
for num_secs in range(6 * 60):
|
|
326
|
+
try:
|
|
327
|
+
params = RequestParameters("GET", f"{self.__localhost_url}:3333/health", timeout=1)
|
|
328
|
+
log_request(params)
|
|
329
|
+
response = requests.get(params.url, timeout=params.timeout)
|
|
330
|
+
log_response(response)
|
|
331
|
+
if response.ok:
|
|
332
|
+
break
|
|
333
|
+
except requests.exceptions.RequestException as e:
|
|
334
|
+
logger.debug(f"RequestException while checking API status: {e}")
|
|
335
|
+
if num_secs > MINUTE / 2 and num_secs % 10 == 0:
|
|
336
|
+
# There is probably an issue, so we need more logs
|
|
337
|
+
with contextlib.suppress():
|
|
338
|
+
docker_ps_output = subprocess.run(
|
|
339
|
+
"docker ps -a".split(), cwd=self.__docker_path_of_user, check=True, capture_output=True
|
|
340
|
+
).stdout.decode("utf-8")
|
|
341
|
+
docker_ps_output = "\n\t".join(docker_ps_output.split("\n"))
|
|
342
|
+
logger.debug(f"docker ps -a output:\n\t{docker_ps_output}")
|
|
343
|
+
docker_logs_output = subprocess.run(
|
|
344
|
+
"docker logs start-stack-api-1".split(),
|
|
345
|
+
cwd=self.__docker_path_of_user,
|
|
346
|
+
check=True,
|
|
347
|
+
capture_output=True,
|
|
348
|
+
).stdout.decode("utf-8")
|
|
349
|
+
docker_logs_output = "\n\t".join(docker_logs_output.split("\n"))
|
|
350
|
+
logger.debug(f"Logs of DSP-API container:\n\t{docker_logs_output}")
|
|
351
|
+
time.sleep(1)
|
|
352
|
+
msg = f"DSP-API is now running on {self.__localhost_url}:3333/ and DSP-APP on {self.__localhost_url}:4200/"
|
|
353
|
+
logger.debug(msg)
|
|
354
|
+
print(msg)
|
|
355
|
+
|
|
356
|
+
def _execute_docker_system_prune(self) -> None:
|
|
357
|
+
"""
|
|
358
|
+
Depending on the CLI parameters or the user's input,
|
|
359
|
+
execute "docker system prune" or not.
|
|
360
|
+
"""
|
|
361
|
+
if self.__stack_configuration.enforce_docker_system_prune:
|
|
362
|
+
prune_docker = "y"
|
|
363
|
+
elif self.__stack_configuration.suppress_docker_system_prune:
|
|
364
|
+
prune_docker = "n"
|
|
365
|
+
else:
|
|
366
|
+
prune_docker = None
|
|
367
|
+
while prune_docker not in ["y", "n"]:
|
|
368
|
+
prune_docker = input(
|
|
369
|
+
"Allow dsp-tools to execute 'docker system prune'? \n"
|
|
370
|
+
"If you press 'y', all unused containers, networks, and images (both dangling and unused) "
|
|
371
|
+
"in your docker will be deleted.\n"
|
|
372
|
+
"It is recommended that you do this every once in a while "
|
|
373
|
+
"to keep your docker clean and running smoothly. [y/n]"
|
|
374
|
+
)
|
|
375
|
+
if prune_docker == "y":
|
|
376
|
+
logger.debug("Running 'docker system prune --volumes -f' ...")
|
|
377
|
+
subprocess.run("docker system prune --volumes -f".split(), cwd=self.__docker_path_of_user, check=False)
|
|
378
|
+
|
|
379
|
+
def _start_docker_containers(self) -> None:
|
|
380
|
+
"""
|
|
381
|
+
Start the fuseki Docker container,
|
|
382
|
+
wait until it is up and running,
|
|
383
|
+
load some basic ontologies and data into it,
|
|
384
|
+
start the other Docker containers,
|
|
385
|
+
and execute "docker system prune" if necessary.
|
|
386
|
+
"""
|
|
387
|
+
self._start_up_fuseki()
|
|
388
|
+
self._wait_for_fuseki()
|
|
389
|
+
self._initialize_fuseki()
|
|
390
|
+
self._start_remaining_docker_containers()
|
|
391
|
+
self._wait_for_api()
|
|
392
|
+
self._execute_docker_system_prune()
|
|
393
|
+
|
|
394
|
+
def start_stack(self) -> bool:
|
|
395
|
+
"""
|
|
396
|
+
Start the Docker containers of DSP-API and DSP-APP, and load some basic data models and data.
|
|
397
|
+
After startup, ask user if Docker should be pruned or not.
|
|
398
|
+
|
|
399
|
+
Raises:
|
|
400
|
+
InputError: if the stack cannot be started with the parameters passed by the user
|
|
401
|
+
|
|
402
|
+
Returns:
|
|
403
|
+
True if everything went well, False otherwise
|
|
404
|
+
"""
|
|
405
|
+
self._copy_resources_to_home_dir()
|
|
406
|
+
self._set_custom_host()
|
|
407
|
+
try:
|
|
408
|
+
self._get_sipi_docker_config_lua()
|
|
409
|
+
except (requests.ConnectionError, requests.ReadTimeout):
|
|
410
|
+
raise PermanentConnectionError(
|
|
411
|
+
"This command requires an internet connection. "
|
|
412
|
+
"Please ensure that your computer is connected and try again."
|
|
413
|
+
)
|
|
414
|
+
self._start_docker_containers()
|
|
415
|
+
return True
|
|
416
|
+
|
|
417
|
+
def stop_stack(self) -> bool:
|
|
418
|
+
"""
|
|
419
|
+
Shut down the Docker containers of your local DSP stack and delete all data that is in it.
|
|
420
|
+
|
|
421
|
+
Returns:
|
|
422
|
+
True if everything went well, False otherwise
|
|
423
|
+
"""
|
|
424
|
+
subprocess.run("docker compose down --volumes".split(), cwd=self.__docker_path_of_user, check=True)
|
|
425
|
+
shutil.rmtree(self.__docker_path_of_user / "sipi", ignore_errors=True)
|
|
426
|
+
# ignore all errors, because the dir cannot be found if this function is called multiple times,
|
|
427
|
+
# and because in GitHub CI, python lacks permissions to delete this dir
|
|
428
|
+
return True
|