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,1542 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Collection
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from dsp_tools.error.xmllib_warnings import MessageInfo
|
|
8
|
+
from dsp_tools.error.xmllib_warnings_util import emit_xmllib_input_warning
|
|
9
|
+
from dsp_tools.xmllib.internal.input_converters import check_and_fix_collection_input
|
|
10
|
+
from dsp_tools.xmllib.internal.input_converters import check_and_fix_is_non_empty_string
|
|
11
|
+
from dsp_tools.xmllib.models.config_options import NewlineReplacement
|
|
12
|
+
from dsp_tools.xmllib.models.internal.geometry import Circle
|
|
13
|
+
from dsp_tools.xmllib.models.internal.geometry import GeometryPoint
|
|
14
|
+
from dsp_tools.xmllib.models.internal.geometry import GeometryShape
|
|
15
|
+
from dsp_tools.xmllib.models.internal.geometry import Polygon
|
|
16
|
+
from dsp_tools.xmllib.models.internal.geometry import Rectangle
|
|
17
|
+
from dsp_tools.xmllib.models.internal.geometry import Vector
|
|
18
|
+
from dsp_tools.xmllib.models.internal.migration_metadata import MigrationMetadata
|
|
19
|
+
from dsp_tools.xmllib.models.internal.values import LinkValue
|
|
20
|
+
from dsp_tools.xmllib.models.internal.values import Richtext
|
|
21
|
+
from dsp_tools.xmllib.models.internal.values import SimpleText
|
|
22
|
+
from dsp_tools.xmllib.models.internal.values import Value
|
|
23
|
+
from dsp_tools.xmllib.models.permissions import Permissions
|
|
24
|
+
from dsp_tools.xmllib.value_checkers import is_decimal
|
|
25
|
+
from dsp_tools.xmllib.value_checkers import is_nonempty_value
|
|
26
|
+
|
|
27
|
+
LIST_SEPARATOR = "\n - "
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@dataclass
|
|
31
|
+
class RegionResource:
|
|
32
|
+
res_id: str
|
|
33
|
+
label: str
|
|
34
|
+
values: list[Value]
|
|
35
|
+
geometry: GeometryShape | None
|
|
36
|
+
permissions: Permissions = Permissions.PROJECT_SPECIFIC_PERMISSIONS
|
|
37
|
+
migration_metadata: MigrationMetadata | None = None
|
|
38
|
+
|
|
39
|
+
@staticmethod
|
|
40
|
+
def create_new(
|
|
41
|
+
res_id: str,
|
|
42
|
+
label: str,
|
|
43
|
+
region_of: str,
|
|
44
|
+
permissions: Permissions = Permissions.PROJECT_SPECIFIC_PERMISSIONS,
|
|
45
|
+
) -> RegionResource:
|
|
46
|
+
"""
|
|
47
|
+
Creates a new region resource.
|
|
48
|
+
A region is a region of interest (ROI) in a StillImageRepresentation.
|
|
49
|
+
|
|
50
|
+
Exactly one geometry shape has to be added to the resource with one of the following methods:
|
|
51
|
+
`add_rectangle`, `add_polygon`, `add_circle` (see documentation below for more information).
|
|
52
|
+
|
|
53
|
+
[See XML documentation for details](https://docs.dasch.swiss/latest/DSP-TOOLS/file-formats/xml-data-file/#region)
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
res_id: ID of this region resource
|
|
57
|
+
label: label of this region resource
|
|
58
|
+
region_of: ID of the image resource that this region refers to (cardinality 1)
|
|
59
|
+
permissions: permissions of this region resource
|
|
60
|
+
|
|
61
|
+
Returns:
|
|
62
|
+
A region resource
|
|
63
|
+
|
|
64
|
+
Examples:
|
|
65
|
+
```python
|
|
66
|
+
region = xmllib.RegionResource.create_new(
|
|
67
|
+
res_id="ID",
|
|
68
|
+
label="label",
|
|
69
|
+
region_of="image_id",
|
|
70
|
+
)
|
|
71
|
+
```
|
|
72
|
+
"""
|
|
73
|
+
_check_strings(string_to_check=res_id, res_id=res_id, field_name="Resource ID")
|
|
74
|
+
res_id = str(res_id)
|
|
75
|
+
lbl = check_and_fix_is_non_empty_string(value=label, res_id=res_id, value_field="label")
|
|
76
|
+
return RegionResource(
|
|
77
|
+
res_id=res_id,
|
|
78
|
+
label=lbl,
|
|
79
|
+
values=[
|
|
80
|
+
LinkValue.new(
|
|
81
|
+
value=region_of, prop_name="isRegionOf", resource_id=res_id, comment=None, permissions=permissions
|
|
82
|
+
)
|
|
83
|
+
],
|
|
84
|
+
geometry=None,
|
|
85
|
+
permissions=permissions,
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
def add_rectangle(
|
|
89
|
+
self,
|
|
90
|
+
point1: tuple[float, float],
|
|
91
|
+
point2: tuple[float, float],
|
|
92
|
+
line_width: float = 2,
|
|
93
|
+
color: str = "#5b24bf",
|
|
94
|
+
active: bool = True,
|
|
95
|
+
) -> RegionResource:
|
|
96
|
+
"""
|
|
97
|
+
Add a rectangle shape to the region.
|
|
98
|
+
|
|
99
|
+
[For a visual example see the XML documentation](https://docs.dasch.swiss/latest/DSP-TOOLS/file-formats/xml-data-file/#geometry)
|
|
100
|
+
|
|
101
|
+
Args:
|
|
102
|
+
point1: first point of the rectangle represented as two numbers between 0 and 1 in the format (x, y)
|
|
103
|
+
point2: second point of the rectangle represented as two numbers between 0 and 1 in the format (x, y)
|
|
104
|
+
line_width: A number in pixels between 1 - 5
|
|
105
|
+
color: A hexadecimal color value which starts with a `#` followed by 3 or 6 numerals.
|
|
106
|
+
The default value was chosen as it is distinguishable for most color-blind people.
|
|
107
|
+
active: If set to `False`, the region is marked as 'deleted'
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
Region with added rectangle
|
|
111
|
+
|
|
112
|
+
Examples:
|
|
113
|
+
```python
|
|
114
|
+
region = region.add_rectangle(
|
|
115
|
+
point1=(0.1, 0.1),
|
|
116
|
+
point2=(0.2, 0.2),
|
|
117
|
+
)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
# with custom display values
|
|
122
|
+
region = region.add_rectangle(
|
|
123
|
+
point1=(0.1, 0.1),
|
|
124
|
+
point2=(0.2, 0.2),
|
|
125
|
+
line_width=3,
|
|
126
|
+
color="#32a873",
|
|
127
|
+
)
|
|
128
|
+
```
|
|
129
|
+
"""
|
|
130
|
+
self.geometry = Rectangle(
|
|
131
|
+
point1=GeometryPoint(point1[0], point1[1], self.res_id),
|
|
132
|
+
point2=GeometryPoint(point2[0], point2[1], self.res_id),
|
|
133
|
+
line_width=line_width,
|
|
134
|
+
color=color,
|
|
135
|
+
active=active,
|
|
136
|
+
resource_id=self.res_id,
|
|
137
|
+
)
|
|
138
|
+
return self
|
|
139
|
+
|
|
140
|
+
def add_polygon(
|
|
141
|
+
self,
|
|
142
|
+
points: list[tuple[float, float]],
|
|
143
|
+
line_width: float = 2,
|
|
144
|
+
color: str = "#5b24bf",
|
|
145
|
+
active: bool = True,
|
|
146
|
+
) -> RegionResource:
|
|
147
|
+
"""
|
|
148
|
+
Add a polygon shape to the region.
|
|
149
|
+
A polygon should have at least three points.
|
|
150
|
+
If you wish to create a rectangle, please use the designated `add_rectangle` method.
|
|
151
|
+
|
|
152
|
+
[For a visual example see the XML documentation](https://docs.dasch.swiss/latest/DSP-TOOLS/file-formats/xml-data-file/#geometry)
|
|
153
|
+
|
|
154
|
+
**Please note that this cannot currently be displayed in the dsp-app.**
|
|
155
|
+
|
|
156
|
+
Args:
|
|
157
|
+
points: list of tuples containing two numbers between 0 and 1 in the format (x, y)
|
|
158
|
+
line_width: A number in pixels between 1 - 5
|
|
159
|
+
color: A hexadecimal color value which starts with a `#` followed by 3 or 6 numerals.
|
|
160
|
+
The default value was chosen as it is distinguishable for most color-blind people.
|
|
161
|
+
active: If set to `False` the region is marked as 'deleted'
|
|
162
|
+
|
|
163
|
+
Returns:
|
|
164
|
+
Region with added polygon
|
|
165
|
+
|
|
166
|
+
Examples:
|
|
167
|
+
```python
|
|
168
|
+
region = region.add_polygon(
|
|
169
|
+
points=[(0.1, 0.1), (0.2, 0.2), (0.3, 0.3)],
|
|
170
|
+
)
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
```python
|
|
174
|
+
# with custom display values
|
|
175
|
+
region = region.add_polygon(
|
|
176
|
+
points=[(0.1, 0.1), (0.2, 0.2), (0.3, 0.3)],
|
|
177
|
+
line_width=3,
|
|
178
|
+
color="#32a873",
|
|
179
|
+
)
|
|
180
|
+
```
|
|
181
|
+
"""
|
|
182
|
+
geom_points = [GeometryPoint(val[0], val[1], self.res_id) for val in points]
|
|
183
|
+
self.geometry = Polygon(
|
|
184
|
+
points=geom_points, line_width=line_width, color=color, active=active, resource_id=self.res_id
|
|
185
|
+
)
|
|
186
|
+
return self
|
|
187
|
+
|
|
188
|
+
def add_circle(
|
|
189
|
+
self,
|
|
190
|
+
center: tuple[float, float],
|
|
191
|
+
radius: tuple[float, float],
|
|
192
|
+
line_width: float = 2,
|
|
193
|
+
color: str = "#5b24bf",
|
|
194
|
+
active: bool = True,
|
|
195
|
+
) -> RegionResource:
|
|
196
|
+
"""
|
|
197
|
+
Add a circle shape to the region.
|
|
198
|
+
|
|
199
|
+
[For a visual example see the XML documentation](https://docs.dasch.swiss/latest/DSP-TOOLS/file-formats/xml-data-file/#geometry)
|
|
200
|
+
|
|
201
|
+
**Please note that this cannot currently be displayed in the dsp-app.**
|
|
202
|
+
|
|
203
|
+
Args:
|
|
204
|
+
center: center of the circle, represented as two numbers between 0 and 1 in the format (x, y)
|
|
205
|
+
radius: radius of the circle, represented as a 2-dimensional vector,
|
|
206
|
+
i.e. two numbers between 0 and 1 in the format (x, y)
|
|
207
|
+
line_width: A number in pixels between 1 - 5
|
|
208
|
+
color: A hexadecimal color value which starts with a `#` followed by 3 or 6 numerals.
|
|
209
|
+
The default value was chosen as it is distinguishable for most color-blind people.
|
|
210
|
+
active: If set to `False` the region is marked as 'deleted'
|
|
211
|
+
|
|
212
|
+
Returns:
|
|
213
|
+
Region with added circle
|
|
214
|
+
|
|
215
|
+
Examples:
|
|
216
|
+
```python
|
|
217
|
+
region = region.add_circle(
|
|
218
|
+
center=(0.1, 0.1),
|
|
219
|
+
radius=(0.2, 0.2),
|
|
220
|
+
)
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
```python
|
|
224
|
+
# with custom display values
|
|
225
|
+
region = region.add_circle(
|
|
226
|
+
center=(0.1, 0.1),
|
|
227
|
+
radius=(0.2, 0.2),
|
|
228
|
+
line_width=3,
|
|
229
|
+
color="#32a873",
|
|
230
|
+
)
|
|
231
|
+
```
|
|
232
|
+
"""
|
|
233
|
+
self.geometry = Circle(
|
|
234
|
+
center=GeometryPoint(center[0], center[1], self.res_id),
|
|
235
|
+
radius=Vector(radius[0], radius[1], self.res_id),
|
|
236
|
+
line_width=line_width,
|
|
237
|
+
color=color,
|
|
238
|
+
active=active,
|
|
239
|
+
resource_id=self.res_id,
|
|
240
|
+
)
|
|
241
|
+
return self
|
|
242
|
+
|
|
243
|
+
def add_comment(
|
|
244
|
+
self,
|
|
245
|
+
text: str,
|
|
246
|
+
permissions: Permissions = Permissions.PROJECT_SPECIFIC_PERMISSIONS,
|
|
247
|
+
comment: str | None = None,
|
|
248
|
+
newline_replacement: NewlineReplacement = NewlineReplacement.LINEBREAK,
|
|
249
|
+
) -> RegionResource:
|
|
250
|
+
"""
|
|
251
|
+
Add a comment to the region
|
|
252
|
+
|
|
253
|
+
Args:
|
|
254
|
+
text: text of the comment
|
|
255
|
+
permissions: optional permissions of this value
|
|
256
|
+
comment: optional comment about this comment
|
|
257
|
+
newline_replacement: options how to deal with `\\n` inside the text value. Default: replace with `<br/>`
|
|
258
|
+
|
|
259
|
+
Returns:
|
|
260
|
+
The original region, with the added comment
|
|
261
|
+
|
|
262
|
+
Examples:
|
|
263
|
+
```python
|
|
264
|
+
region = region.add_comment("comment text")
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
```python
|
|
268
|
+
region = region.add_comment(text="comment text", comment="Comment about the comment.")
|
|
269
|
+
```
|
|
270
|
+
"""
|
|
271
|
+
self.values.append(
|
|
272
|
+
Richtext.new(
|
|
273
|
+
value=text,
|
|
274
|
+
prop_name="hasComment",
|
|
275
|
+
permissions=permissions,
|
|
276
|
+
comment=comment,
|
|
277
|
+
resource_id=self.res_id,
|
|
278
|
+
newline_replacement=newline_replacement,
|
|
279
|
+
)
|
|
280
|
+
)
|
|
281
|
+
return self
|
|
282
|
+
|
|
283
|
+
def add_comment_multiple(
|
|
284
|
+
self,
|
|
285
|
+
texts: Collection[str],
|
|
286
|
+
permissions: Permissions = Permissions.PROJECT_SPECIFIC_PERMISSIONS,
|
|
287
|
+
comment: str | None = None,
|
|
288
|
+
newline_replacement: NewlineReplacement = NewlineReplacement.LINEBREAK,
|
|
289
|
+
) -> RegionResource:
|
|
290
|
+
"""
|
|
291
|
+
Add several comments to the region
|
|
292
|
+
|
|
293
|
+
Args:
|
|
294
|
+
texts: list of texts
|
|
295
|
+
permissions: optional permissions of these values
|
|
296
|
+
comment: optional comment about these comments
|
|
297
|
+
newline_replacement: options how to deal with `\\n` inside the text value. Default: replace with `<br/>`
|
|
298
|
+
|
|
299
|
+
Returns:
|
|
300
|
+
The original region, with the added comments
|
|
301
|
+
|
|
302
|
+
Examples:
|
|
303
|
+
```python
|
|
304
|
+
region = region.add_comment_multiple(["comment 1", "comment 2"])
|
|
305
|
+
```
|
|
306
|
+
"""
|
|
307
|
+
vals = check_and_fix_collection_input(texts, "hasComment", self.res_id)
|
|
308
|
+
comnts = [
|
|
309
|
+
Richtext.new(
|
|
310
|
+
value=x,
|
|
311
|
+
prop_name="hasComment",
|
|
312
|
+
permissions=permissions,
|
|
313
|
+
comment=comment,
|
|
314
|
+
resource_id=self.res_id,
|
|
315
|
+
newline_replacement=newline_replacement,
|
|
316
|
+
)
|
|
317
|
+
for x in vals
|
|
318
|
+
]
|
|
319
|
+
self.values.extend(comnts)
|
|
320
|
+
return self
|
|
321
|
+
|
|
322
|
+
def add_comment_optional(
|
|
323
|
+
self,
|
|
324
|
+
text: Any,
|
|
325
|
+
permissions: Permissions = Permissions.PROJECT_SPECIFIC_PERMISSIONS,
|
|
326
|
+
comment: str | None = None,
|
|
327
|
+
newline_replacement: NewlineReplacement = NewlineReplacement.LINEBREAK,
|
|
328
|
+
) -> RegionResource:
|
|
329
|
+
"""
|
|
330
|
+
If the value is not empty, add it as comment, otherwise return the region unchanged.
|
|
331
|
+
|
|
332
|
+
Args:
|
|
333
|
+
text: text of the comment (or empty value)
|
|
334
|
+
permissions: optional permissions of this value
|
|
335
|
+
comment: optional comment about this comment
|
|
336
|
+
newline_replacement: options how to deal with `\\n` inside the text value. Default: replace with `<br/>`
|
|
337
|
+
|
|
338
|
+
Returns:
|
|
339
|
+
The original region, with the added comment
|
|
340
|
+
|
|
341
|
+
Examples:
|
|
342
|
+
```python
|
|
343
|
+
region = region.add_comment_optional("comment text")
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
```python
|
|
347
|
+
region = region.add_comment_optional(None)
|
|
348
|
+
```
|
|
349
|
+
"""
|
|
350
|
+
if is_nonempty_value(text):
|
|
351
|
+
return self.add_comment(text, permissions, comment, newline_replacement)
|
|
352
|
+
return self
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
@dataclass
|
|
356
|
+
class LinkResource:
|
|
357
|
+
res_id: str
|
|
358
|
+
label: str
|
|
359
|
+
values: list[Value]
|
|
360
|
+
permissions: Permissions = Permissions.PROJECT_SPECIFIC_PERMISSIONS
|
|
361
|
+
migration_metadata: MigrationMetadata | None = None
|
|
362
|
+
|
|
363
|
+
@staticmethod
|
|
364
|
+
def create_new(
|
|
365
|
+
res_id: str,
|
|
366
|
+
label: str,
|
|
367
|
+
link_to: Collection[str],
|
|
368
|
+
permissions: Permissions = Permissions.PROJECT_SPECIFIC_PERMISSIONS,
|
|
369
|
+
) -> LinkResource:
|
|
370
|
+
"""
|
|
371
|
+
Creates a new link resource.
|
|
372
|
+
A link resource is like a container that groups together several other resources of different classes.
|
|
373
|
+
|
|
374
|
+
[See XML documentation for details](https://docs.dasch.swiss/latest/DSP-TOOLS/file-formats/xml-data-file/#link)
|
|
375
|
+
|
|
376
|
+
Args:
|
|
377
|
+
res_id: ID of this link resource
|
|
378
|
+
label: label of this link resource
|
|
379
|
+
link_to: IDs of the resources that should be linked together (cardinality 1-n)
|
|
380
|
+
permissions: permissions of this link resource
|
|
381
|
+
|
|
382
|
+
Returns:
|
|
383
|
+
A link resource
|
|
384
|
+
|
|
385
|
+
Examples:
|
|
386
|
+
```python
|
|
387
|
+
link_resource = xmllib.LinkResource.create_new(
|
|
388
|
+
res_id="ID",
|
|
389
|
+
label="label",
|
|
390
|
+
link_to=["target_resource_id_1", "target_resource_id_2"],
|
|
391
|
+
)
|
|
392
|
+
```
|
|
393
|
+
"""
|
|
394
|
+
_check_strings(string_to_check=res_id, res_id=res_id, field_name="Resource ID")
|
|
395
|
+
res_id = str(res_id)
|
|
396
|
+
lbl = check_and_fix_is_non_empty_string(value=label, res_id=res_id, value_field="label")
|
|
397
|
+
links_to = check_and_fix_collection_input(link_to, "hasLinkTo", res_id)
|
|
398
|
+
link_vals: list[Value] = [
|
|
399
|
+
LinkValue.new(value=x, prop_name="hasLinkTo", resource_id=res_id, comment=None, permissions=permissions)
|
|
400
|
+
for x in links_to
|
|
401
|
+
]
|
|
402
|
+
return LinkResource(
|
|
403
|
+
res_id=res_id,
|
|
404
|
+
label=lbl,
|
|
405
|
+
values=link_vals,
|
|
406
|
+
permissions=permissions,
|
|
407
|
+
)
|
|
408
|
+
|
|
409
|
+
def add_comment(
|
|
410
|
+
self,
|
|
411
|
+
text: str,
|
|
412
|
+
permissions: Permissions = Permissions.PROJECT_SPECIFIC_PERMISSIONS,
|
|
413
|
+
comment: str | None = None,
|
|
414
|
+
newline_replacement: NewlineReplacement = NewlineReplacement.LINEBREAK,
|
|
415
|
+
) -> LinkResource:
|
|
416
|
+
"""
|
|
417
|
+
Add a comment to the resource
|
|
418
|
+
|
|
419
|
+
Args:
|
|
420
|
+
text: text of the comment
|
|
421
|
+
permissions: optional permissions of this value
|
|
422
|
+
comment: optional comment about this comment
|
|
423
|
+
newline_replacement: options how to deal with `\\n` inside the text value. Default: replace with `<br/>`
|
|
424
|
+
|
|
425
|
+
Returns:
|
|
426
|
+
The original resource, with the added comment
|
|
427
|
+
|
|
428
|
+
Examples:
|
|
429
|
+
```python
|
|
430
|
+
link_resource = link_resource.add_comment("comment text")
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
```python
|
|
434
|
+
link_resource = link_resource.add_comment(text="comment text", comment="Comment about the comment.")
|
|
435
|
+
```
|
|
436
|
+
"""
|
|
437
|
+
self.values.append(
|
|
438
|
+
Richtext.new(
|
|
439
|
+
value=text,
|
|
440
|
+
prop_name="hasComment",
|
|
441
|
+
permissions=permissions,
|
|
442
|
+
comment=comment,
|
|
443
|
+
resource_id=self.res_id,
|
|
444
|
+
newline_replacement=newline_replacement,
|
|
445
|
+
)
|
|
446
|
+
)
|
|
447
|
+
return self
|
|
448
|
+
|
|
449
|
+
def add_comment_multiple(
|
|
450
|
+
self,
|
|
451
|
+
texts: Collection[str],
|
|
452
|
+
permissions: Permissions = Permissions.PROJECT_SPECIFIC_PERMISSIONS,
|
|
453
|
+
comment: str | None = None,
|
|
454
|
+
newline_replacement: NewlineReplacement = NewlineReplacement.LINEBREAK,
|
|
455
|
+
) -> LinkResource:
|
|
456
|
+
"""
|
|
457
|
+
Add several comments to the resource
|
|
458
|
+
|
|
459
|
+
Args:
|
|
460
|
+
texts: list of texts
|
|
461
|
+
permissions: optional permissions of these values
|
|
462
|
+
comment: optional comment about this comment
|
|
463
|
+
newline_replacement: options how to deal with `\\n` inside the text value. Default: replace with `<br/>`
|
|
464
|
+
|
|
465
|
+
Returns:
|
|
466
|
+
The original resource, with the added comments
|
|
467
|
+
|
|
468
|
+
Examples:
|
|
469
|
+
```python
|
|
470
|
+
link_resource = link_resource.add_comment_multiple(["comment 1", "comment 2"])
|
|
471
|
+
```
|
|
472
|
+
"""
|
|
473
|
+
vals = check_and_fix_collection_input(texts, "hasComment", self.res_id)
|
|
474
|
+
for v in vals:
|
|
475
|
+
self.add_comment(v, permissions, comment, newline_replacement)
|
|
476
|
+
return self
|
|
477
|
+
|
|
478
|
+
def add_comment_optional(
|
|
479
|
+
self,
|
|
480
|
+
text: Any,
|
|
481
|
+
permissions: Permissions = Permissions.PROJECT_SPECIFIC_PERMISSIONS,
|
|
482
|
+
comment: str | None = None,
|
|
483
|
+
newline_replacement: NewlineReplacement = NewlineReplacement.LINEBREAK,
|
|
484
|
+
) -> LinkResource:
|
|
485
|
+
"""
|
|
486
|
+
If the value is not empty, add it as comment, otherwise return the resource unchanged.
|
|
487
|
+
|
|
488
|
+
Args:
|
|
489
|
+
text: text of the comment (or empty value)
|
|
490
|
+
permissions: optional permissions of this value
|
|
491
|
+
comment: optional comment about this comment
|
|
492
|
+
newline_replacement: options how to deal with `\\n` inside the text value. Default: replace with `<br/>`
|
|
493
|
+
|
|
494
|
+
Returns:
|
|
495
|
+
The original resource, with the added comment
|
|
496
|
+
|
|
497
|
+
Examples:
|
|
498
|
+
```python
|
|
499
|
+
link_resource = link_resource.add_comment_optional("comment text")
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
```python
|
|
503
|
+
link_resource = link_resource.add_comment_optional(None)
|
|
504
|
+
```
|
|
505
|
+
"""
|
|
506
|
+
if is_nonempty_value(text):
|
|
507
|
+
return self.add_comment(text, permissions, comment, newline_replacement)
|
|
508
|
+
return self
|
|
509
|
+
|
|
510
|
+
|
|
511
|
+
@dataclass
|
|
512
|
+
class SegmentBounds:
|
|
513
|
+
segment_start: float | int | str
|
|
514
|
+
segment_end: float | int | str
|
|
515
|
+
permissions: Permissions
|
|
516
|
+
res_id: str
|
|
517
|
+
|
|
518
|
+
def __post_init__(self) -> None:
|
|
519
|
+
msg: list[str] = []
|
|
520
|
+
if not is_decimal(self.segment_start):
|
|
521
|
+
msg.append(f"Segment Start Value: {self.segment_start} | Type: {type(self.segment_start)}")
|
|
522
|
+
if not is_decimal(self.segment_end):
|
|
523
|
+
msg.append(f"Segment End Value: {self.segment_end} | Type: {type(self.segment_start)}")
|
|
524
|
+
if msg:
|
|
525
|
+
wrng = f"{LIST_SEPARATOR}{LIST_SEPARATOR.join(msg)}"
|
|
526
|
+
msg_info = MessageInfo(
|
|
527
|
+
f"Segment bounds must be a float or integer. The following places have an unexpected type: {wrng}",
|
|
528
|
+
self.res_id,
|
|
529
|
+
)
|
|
530
|
+
emit_xmllib_input_warning(msg_info)
|
|
531
|
+
self.segment_start = str(self.segment_start)
|
|
532
|
+
self.segment_end = str(self.segment_end)
|
|
533
|
+
|
|
534
|
+
|
|
535
|
+
@dataclass
|
|
536
|
+
class VideoSegmentResource:
|
|
537
|
+
res_id: str
|
|
538
|
+
label: str
|
|
539
|
+
segment_bounds: SegmentBounds
|
|
540
|
+
values: list[Value]
|
|
541
|
+
permissions: Permissions = Permissions.PROJECT_SPECIFIC_PERMISSIONS
|
|
542
|
+
migration_metadata: MigrationMetadata | None = None
|
|
543
|
+
|
|
544
|
+
@staticmethod
|
|
545
|
+
def create_new(
|
|
546
|
+
res_id: str,
|
|
547
|
+
label: str,
|
|
548
|
+
segment_of: str,
|
|
549
|
+
segment_start: float | int | str,
|
|
550
|
+
segment_end: float | int | str,
|
|
551
|
+
permissions: Permissions = Permissions.PROJECT_SPECIFIC_PERMISSIONS,
|
|
552
|
+
) -> VideoSegmentResource:
|
|
553
|
+
"""
|
|
554
|
+
Creates a new video segment resource, i.e. a time span of a MovingImageRepresentation.
|
|
555
|
+
|
|
556
|
+
[See XML documentation for details](https://docs.dasch.swiss/latest/DSP-TOOLS/file-formats/xml-data-file/#video-segment-and-audio-segment)
|
|
557
|
+
|
|
558
|
+
Args:
|
|
559
|
+
res_id: ID of this video segment resource
|
|
560
|
+
label: label of this video segment resource
|
|
561
|
+
segment_of: ID of the video resource that this segment refers to (cardinality 1)
|
|
562
|
+
segment_start: start of the segment in seconds (cardinality 1)
|
|
563
|
+
segment_end: end of the segment in seconds (cardinality 1)
|
|
564
|
+
permissions: permissions of this resource
|
|
565
|
+
|
|
566
|
+
Returns:
|
|
567
|
+
A video segment resource
|
|
568
|
+
|
|
569
|
+
Examples:
|
|
570
|
+
```python
|
|
571
|
+
video_segment = xmllib.VideoSegmentResource.create_new(
|
|
572
|
+
res_id="ID",
|
|
573
|
+
label="label",
|
|
574
|
+
segment_of="video_resource_id",
|
|
575
|
+
segment_start=1.2,
|
|
576
|
+
segment_end=3.4,
|
|
577
|
+
)
|
|
578
|
+
```
|
|
579
|
+
"""
|
|
580
|
+
_check_strings(string_to_check=res_id, res_id=res_id, field_name="Resource ID")
|
|
581
|
+
res_id = str(res_id)
|
|
582
|
+
lbl = check_and_fix_is_non_empty_string(value=label, res_id=res_id, value_field="label")
|
|
583
|
+
segment_of_val = LinkValue.new(
|
|
584
|
+
value=segment_of, prop_name="isSegmentOf", permissions=permissions, comment=None, resource_id=res_id
|
|
585
|
+
)
|
|
586
|
+
return VideoSegmentResource(
|
|
587
|
+
res_id=res_id,
|
|
588
|
+
label=lbl,
|
|
589
|
+
values=[segment_of_val],
|
|
590
|
+
segment_bounds=SegmentBounds(segment_start, segment_end, permissions, res_id),
|
|
591
|
+
permissions=permissions,
|
|
592
|
+
)
|
|
593
|
+
|
|
594
|
+
def add_title(
|
|
595
|
+
self,
|
|
596
|
+
title: str,
|
|
597
|
+
permissions: Permissions = Permissions.PROJECT_SPECIFIC_PERMISSIONS,
|
|
598
|
+
comment: str | None = None,
|
|
599
|
+
) -> VideoSegmentResource:
|
|
600
|
+
"""
|
|
601
|
+
Add a title to the resource.
|
|
602
|
+
|
|
603
|
+
Args:
|
|
604
|
+
title: text
|
|
605
|
+
permissions: permissions of the value
|
|
606
|
+
comment: comments on the value
|
|
607
|
+
|
|
608
|
+
Returns:
|
|
609
|
+
The original resource, with the added title
|
|
610
|
+
|
|
611
|
+
Examples:
|
|
612
|
+
```python
|
|
613
|
+
video_segment = video_segment.add_title("segment title")
|
|
614
|
+
```
|
|
615
|
+
"""
|
|
616
|
+
existing_titles = [x for x in self.values if x.prop_name == "hasTitle"]
|
|
617
|
+
if any(existing_titles):
|
|
618
|
+
_warn_value_exists(
|
|
619
|
+
old_value=existing_titles.pop(0).value, new_value=title, value_field="title", res_id=self.res_id
|
|
620
|
+
)
|
|
621
|
+
self.values.append(
|
|
622
|
+
SimpleText.new(
|
|
623
|
+
value=title,
|
|
624
|
+
prop_name="hasTitle",
|
|
625
|
+
permissions=permissions,
|
|
626
|
+
comment=comment,
|
|
627
|
+
resource_id=self.res_id,
|
|
628
|
+
)
|
|
629
|
+
)
|
|
630
|
+
return self
|
|
631
|
+
|
|
632
|
+
def add_title_optional(
|
|
633
|
+
self,
|
|
634
|
+
title: Any,
|
|
635
|
+
permissions: Permissions = Permissions.PROJECT_SPECIFIC_PERMISSIONS,
|
|
636
|
+
comment: str | None = None,
|
|
637
|
+
) -> VideoSegmentResource:
|
|
638
|
+
"""
|
|
639
|
+
If the value is not empty, add it as title, otherwise return the resource unchanged.
|
|
640
|
+
|
|
641
|
+
Args:
|
|
642
|
+
title: text or empty value
|
|
643
|
+
permissions: permissions of the value
|
|
644
|
+
comment: comments on the value
|
|
645
|
+
|
|
646
|
+
Returns:
|
|
647
|
+
The original resource, with the added title
|
|
648
|
+
|
|
649
|
+
Examples:
|
|
650
|
+
```python
|
|
651
|
+
video_segment = video_segment.add_title("segment title")
|
|
652
|
+
```
|
|
653
|
+
|
|
654
|
+
```python
|
|
655
|
+
video_segment = video_segment.add_title(None)
|
|
656
|
+
```
|
|
657
|
+
"""
|
|
658
|
+
if is_nonempty_value(title):
|
|
659
|
+
self.add_title(title, permissions, comment)
|
|
660
|
+
return self
|
|
661
|
+
|
|
662
|
+
def add_comment(
|
|
663
|
+
self,
|
|
664
|
+
text: str,
|
|
665
|
+
permissions: Permissions = Permissions.PROJECT_SPECIFIC_PERMISSIONS,
|
|
666
|
+
comment: str | None = None,
|
|
667
|
+
newline_replacement: NewlineReplacement = NewlineReplacement.LINEBREAK,
|
|
668
|
+
) -> VideoSegmentResource:
|
|
669
|
+
"""
|
|
670
|
+
Add a comment to the resource
|
|
671
|
+
|
|
672
|
+
Args:
|
|
673
|
+
text: text
|
|
674
|
+
permissions: optional permissions of this value
|
|
675
|
+
comment: optional comment about this comment
|
|
676
|
+
newline_replacement: options how to deal with `\\n` inside the text value. Default: replace with `<br/>`
|
|
677
|
+
|
|
678
|
+
Returns:
|
|
679
|
+
The original resource, with the added comment
|
|
680
|
+
|
|
681
|
+
Examples:
|
|
682
|
+
```python
|
|
683
|
+
video_segment = video_segment.add_comment("comment text")
|
|
684
|
+
```
|
|
685
|
+
"""
|
|
686
|
+
self.values.append(
|
|
687
|
+
Richtext.new(
|
|
688
|
+
value=text,
|
|
689
|
+
prop_name="hasComment",
|
|
690
|
+
permissions=permissions,
|
|
691
|
+
comment=comment,
|
|
692
|
+
resource_id=self.res_id,
|
|
693
|
+
newline_replacement=newline_replacement,
|
|
694
|
+
)
|
|
695
|
+
)
|
|
696
|
+
return self
|
|
697
|
+
|
|
698
|
+
def add_comment_multiple(
|
|
699
|
+
self,
|
|
700
|
+
texts: Collection[str],
|
|
701
|
+
permissions: Permissions = Permissions.PROJECT_SPECIFIC_PERMISSIONS,
|
|
702
|
+
comment: str | None = None,
|
|
703
|
+
newline_replacement: NewlineReplacement = NewlineReplacement.LINEBREAK,
|
|
704
|
+
) -> VideoSegmentResource:
|
|
705
|
+
"""
|
|
706
|
+
Add several comments to the resource
|
|
707
|
+
|
|
708
|
+
Args:
|
|
709
|
+
texts: list of texts
|
|
710
|
+
permissions: optional permissions of these values
|
|
711
|
+
comment: optional comment about these comments
|
|
712
|
+
newline_replacement: options how to deal with `\\n` inside the text value. Default: replace with `<br/>`
|
|
713
|
+
|
|
714
|
+
Returns:
|
|
715
|
+
The original resource, with the added comments
|
|
716
|
+
|
|
717
|
+
Examples:
|
|
718
|
+
```python
|
|
719
|
+
video_segment = video_segment.add_comment_multiple(["comment 1", "comment 2"])
|
|
720
|
+
```
|
|
721
|
+
"""
|
|
722
|
+
vals = check_and_fix_collection_input(texts, "hasComment", self.res_id)
|
|
723
|
+
for v in vals:
|
|
724
|
+
self.add_comment(v, permissions, comment, newline_replacement)
|
|
725
|
+
return self
|
|
726
|
+
|
|
727
|
+
def add_comment_optional(
|
|
728
|
+
self,
|
|
729
|
+
text: Any,
|
|
730
|
+
permissions: Permissions = Permissions.PROJECT_SPECIFIC_PERMISSIONS,
|
|
731
|
+
comment: str | None = None,
|
|
732
|
+
newline_replacement: NewlineReplacement = NewlineReplacement.LINEBREAK,
|
|
733
|
+
) -> VideoSegmentResource:
|
|
734
|
+
"""
|
|
735
|
+
If the value is not empty, add it as comment, otherwise return the resource unchanged.
|
|
736
|
+
|
|
737
|
+
Args:
|
|
738
|
+
text: text of the comment (or empty value)
|
|
739
|
+
permissions: optional permissions of this value
|
|
740
|
+
comment: optional comment about this comment
|
|
741
|
+
newline_replacement: options how to deal with `\\n` inside the text value. Default: replace with `<br/>`
|
|
742
|
+
|
|
743
|
+
Returns:
|
|
744
|
+
The original resource, with the added comment
|
|
745
|
+
|
|
746
|
+
Examples:
|
|
747
|
+
```python
|
|
748
|
+
video_segment = video_segment.add_comment_optional("comment text")
|
|
749
|
+
```
|
|
750
|
+
|
|
751
|
+
```python
|
|
752
|
+
video_segment = video_segment.add_comment_optional(None)
|
|
753
|
+
```
|
|
754
|
+
"""
|
|
755
|
+
if is_nonempty_value(text):
|
|
756
|
+
self.add_comment(text, permissions, comment, newline_replacement)
|
|
757
|
+
return self
|
|
758
|
+
|
|
759
|
+
def add_description(
|
|
760
|
+
self,
|
|
761
|
+
description: str,
|
|
762
|
+
permissions: Permissions = Permissions.PROJECT_SPECIFIC_PERMISSIONS,
|
|
763
|
+
comment: str | None = None,
|
|
764
|
+
newline_replacement: NewlineReplacement = NewlineReplacement.LINEBREAK,
|
|
765
|
+
) -> VideoSegmentResource:
|
|
766
|
+
"""
|
|
767
|
+
Add a description to the resource
|
|
768
|
+
|
|
769
|
+
Args:
|
|
770
|
+
description: text
|
|
771
|
+
permissions: optional permissions of this value
|
|
772
|
+
comment: optional comment
|
|
773
|
+
newline_replacement: options how to deal with `\\n` inside the text value. Default: replace with `<br/>`
|
|
774
|
+
|
|
775
|
+
Returns:
|
|
776
|
+
The original resource, with the added description
|
|
777
|
+
|
|
778
|
+
Examples:
|
|
779
|
+
```python
|
|
780
|
+
video_segment = video_segment.add_description("description text")
|
|
781
|
+
```
|
|
782
|
+
"""
|
|
783
|
+
self.values.append(
|
|
784
|
+
Richtext.new(
|
|
785
|
+
value=description,
|
|
786
|
+
prop_name="hasDescription",
|
|
787
|
+
permissions=permissions,
|
|
788
|
+
comment=comment,
|
|
789
|
+
resource_id=self.res_id,
|
|
790
|
+
newline_replacement=newline_replacement,
|
|
791
|
+
)
|
|
792
|
+
)
|
|
793
|
+
return self
|
|
794
|
+
|
|
795
|
+
def add_description_multiple(
|
|
796
|
+
self,
|
|
797
|
+
descriptions: Collection[str],
|
|
798
|
+
permissions: Permissions = Permissions.PROJECT_SPECIFIC_PERMISSIONS,
|
|
799
|
+
comment: str | None = None,
|
|
800
|
+
newline_replacement: NewlineReplacement = NewlineReplacement.LINEBREAK,
|
|
801
|
+
) -> VideoSegmentResource:
|
|
802
|
+
"""
|
|
803
|
+
Add several descriptions to the resource
|
|
804
|
+
|
|
805
|
+
Args:
|
|
806
|
+
descriptions: list of texts
|
|
807
|
+
permissions: optional permissions of these value
|
|
808
|
+
comment: optional comment
|
|
809
|
+
newline_replacement: options how to deal with `\\n` inside the text value. Default: replace with `<br/>`
|
|
810
|
+
|
|
811
|
+
Returns:
|
|
812
|
+
The original resource, with the added descriptions
|
|
813
|
+
|
|
814
|
+
Examples:
|
|
815
|
+
```python
|
|
816
|
+
video_segment = video_segment.add_description_multiple(["description 1", "description 2"])
|
|
817
|
+
```
|
|
818
|
+
"""
|
|
819
|
+
vals = check_and_fix_collection_input(descriptions, "description", self.res_id)
|
|
820
|
+
for v in vals:
|
|
821
|
+
self.add_description(v, permissions, comment, newline_replacement)
|
|
822
|
+
return self
|
|
823
|
+
|
|
824
|
+
def add_description_optional(
|
|
825
|
+
self,
|
|
826
|
+
description: Any,
|
|
827
|
+
permissions: Permissions = Permissions.PROJECT_SPECIFIC_PERMISSIONS,
|
|
828
|
+
comment: str | None = None,
|
|
829
|
+
newline_replacement: NewlineReplacement = NewlineReplacement.LINEBREAK,
|
|
830
|
+
) -> VideoSegmentResource:
|
|
831
|
+
"""
|
|
832
|
+
If the value is not empty, add it as description, otherwise return the resource unchanged.
|
|
833
|
+
|
|
834
|
+
Args:
|
|
835
|
+
description: text or empty value
|
|
836
|
+
permissions: optional permissions of this value
|
|
837
|
+
comment: optional comment
|
|
838
|
+
newline_replacement: options how to deal with `\\n` inside the text value. Default: replace with `<br/>`
|
|
839
|
+
|
|
840
|
+
Returns:
|
|
841
|
+
The original resource, with the added description
|
|
842
|
+
|
|
843
|
+
Examples:
|
|
844
|
+
```python
|
|
845
|
+
video_segment = video_segment.add_description_optional("description text")
|
|
846
|
+
```
|
|
847
|
+
|
|
848
|
+
```python
|
|
849
|
+
video_segment = video_segment.add_description_optional(None)
|
|
850
|
+
```
|
|
851
|
+
"""
|
|
852
|
+
if is_nonempty_value(description):
|
|
853
|
+
self.add_description(description, permissions, comment, newline_replacement)
|
|
854
|
+
return self
|
|
855
|
+
|
|
856
|
+
def add_keyword(
|
|
857
|
+
self,
|
|
858
|
+
keyword: str,
|
|
859
|
+
permissions: Permissions = Permissions.PROJECT_SPECIFIC_PERMISSIONS,
|
|
860
|
+
comment: str | None = None,
|
|
861
|
+
) -> VideoSegmentResource:
|
|
862
|
+
"""
|
|
863
|
+
Add a keyword to the resource
|
|
864
|
+
|
|
865
|
+
Args:
|
|
866
|
+
keyword: text
|
|
867
|
+
permissions: optional permissions of this value
|
|
868
|
+
comment: optional comment
|
|
869
|
+
|
|
870
|
+
Returns:
|
|
871
|
+
The original resource, with the added keyword
|
|
872
|
+
|
|
873
|
+
Examples:
|
|
874
|
+
```python
|
|
875
|
+
video_segment = video_segment.add_keyword("keyword")
|
|
876
|
+
```
|
|
877
|
+
"""
|
|
878
|
+
self.values.append(
|
|
879
|
+
SimpleText.new(
|
|
880
|
+
value=keyword,
|
|
881
|
+
prop_name="hasKeyword",
|
|
882
|
+
permissions=permissions,
|
|
883
|
+
comment=comment,
|
|
884
|
+
resource_id=self.res_id,
|
|
885
|
+
)
|
|
886
|
+
)
|
|
887
|
+
return self
|
|
888
|
+
|
|
889
|
+
def add_keyword_multiple(
|
|
890
|
+
self,
|
|
891
|
+
keywords: Collection[str],
|
|
892
|
+
permissions: Permissions = Permissions.PROJECT_SPECIFIC_PERMISSIONS,
|
|
893
|
+
comment: str | None = None,
|
|
894
|
+
) -> VideoSegmentResource:
|
|
895
|
+
"""
|
|
896
|
+
Add several keywords to the resource
|
|
897
|
+
|
|
898
|
+
Args:
|
|
899
|
+
keywords: list of texts
|
|
900
|
+
permissions: optional permissions of these values
|
|
901
|
+
comment: optional comment
|
|
902
|
+
|
|
903
|
+
Returns:
|
|
904
|
+
The original resource, with the added keywords
|
|
905
|
+
|
|
906
|
+
Examples:
|
|
907
|
+
```python
|
|
908
|
+
video_segment = video_segment.add_keyword_multiple(["keyword 1", "keyword 2"])
|
|
909
|
+
```
|
|
910
|
+
"""
|
|
911
|
+
vals = check_and_fix_collection_input(keywords, "keywords", self.res_id)
|
|
912
|
+
for v in vals:
|
|
913
|
+
self.add_keyword(v, permissions, comment)
|
|
914
|
+
return self
|
|
915
|
+
|
|
916
|
+
def add_keyword_optional(
|
|
917
|
+
self,
|
|
918
|
+
keyword: Any,
|
|
919
|
+
permissions: Permissions = Permissions.PROJECT_SPECIFIC_PERMISSIONS,
|
|
920
|
+
comment: str | None = None,
|
|
921
|
+
) -> VideoSegmentResource:
|
|
922
|
+
"""
|
|
923
|
+
If the value is not empty, add it as keyword, otherwise return the resource unchanged.
|
|
924
|
+
|
|
925
|
+
Args:
|
|
926
|
+
keyword: text or empty value
|
|
927
|
+
permissions: optional permissions of this value
|
|
928
|
+
comment: optional comment
|
|
929
|
+
|
|
930
|
+
Returns:
|
|
931
|
+
The original resource, with the added keyword
|
|
932
|
+
|
|
933
|
+
Examples:
|
|
934
|
+
```python
|
|
935
|
+
video_segment = video_segment.add_keyword_optional("keyword")
|
|
936
|
+
```
|
|
937
|
+
|
|
938
|
+
```python
|
|
939
|
+
video_segment = video_segment.add_keyword_optional(None)
|
|
940
|
+
```
|
|
941
|
+
"""
|
|
942
|
+
if is_nonempty_value(keyword):
|
|
943
|
+
self.add_keyword(keyword, permissions, comment)
|
|
944
|
+
return self
|
|
945
|
+
|
|
946
|
+
def add_relates_to(
|
|
947
|
+
self,
|
|
948
|
+
relates_to: str,
|
|
949
|
+
permissions: Permissions = Permissions.PROJECT_SPECIFIC_PERMISSIONS,
|
|
950
|
+
comment: str | None = None,
|
|
951
|
+
) -> VideoSegmentResource:
|
|
952
|
+
"""
|
|
953
|
+
Add a link to a related resource
|
|
954
|
+
|
|
955
|
+
Args:
|
|
956
|
+
relates_to: ID of the related resource
|
|
957
|
+
permissions: optional permissions of this value
|
|
958
|
+
comment: optional comment
|
|
959
|
+
|
|
960
|
+
Returns:
|
|
961
|
+
The original resource, with the added related resource
|
|
962
|
+
|
|
963
|
+
Examples:
|
|
964
|
+
```python
|
|
965
|
+
video_segment = video_segment.add_relates_to("target_resource_id")
|
|
966
|
+
```
|
|
967
|
+
"""
|
|
968
|
+
self.values.append(
|
|
969
|
+
LinkValue.new(
|
|
970
|
+
value=relates_to,
|
|
971
|
+
prop_name="relatesTo",
|
|
972
|
+
permissions=permissions,
|
|
973
|
+
comment=comment,
|
|
974
|
+
resource_id=self.res_id,
|
|
975
|
+
)
|
|
976
|
+
)
|
|
977
|
+
return self
|
|
978
|
+
|
|
979
|
+
def add_relates_to_multiple(
|
|
980
|
+
self,
|
|
981
|
+
relates_to: Collection[str],
|
|
982
|
+
permissions: Permissions = Permissions.PROJECT_SPECIFIC_PERMISSIONS,
|
|
983
|
+
comment: str | None = None,
|
|
984
|
+
) -> VideoSegmentResource:
|
|
985
|
+
"""
|
|
986
|
+
Add several links to related resources
|
|
987
|
+
|
|
988
|
+
Args:
|
|
989
|
+
relates_to: list of IDs of the related resources
|
|
990
|
+
permissions: optional permissions of these values
|
|
991
|
+
comment: optional comment
|
|
992
|
+
|
|
993
|
+
Returns:
|
|
994
|
+
The original resource, with the added related resources
|
|
995
|
+
|
|
996
|
+
Examples:
|
|
997
|
+
```python
|
|
998
|
+
video_segment = video_segment.add_relates_to_multiple(["target_resource_id_1", "target_resource_id_2"])
|
|
999
|
+
```
|
|
1000
|
+
"""
|
|
1001
|
+
vals = check_and_fix_collection_input(relates_to, "relatesTo", self.res_id)
|
|
1002
|
+
for v in vals:
|
|
1003
|
+
self.add_relates_to(v, permissions, comment)
|
|
1004
|
+
return self
|
|
1005
|
+
|
|
1006
|
+
def add_relates_to_optional(
|
|
1007
|
+
self,
|
|
1008
|
+
relates_to: Any,
|
|
1009
|
+
permissions: Permissions = Permissions.PROJECT_SPECIFIC_PERMISSIONS,
|
|
1010
|
+
comment: str | None = None,
|
|
1011
|
+
) -> VideoSegmentResource:
|
|
1012
|
+
"""
|
|
1013
|
+
If the value is not empty, add it as related resource, otherwise return the resource unchanged.
|
|
1014
|
+
|
|
1015
|
+
Args:
|
|
1016
|
+
relates_to: ID or the related resource or empty value
|
|
1017
|
+
permissions: optional permissions of this value
|
|
1018
|
+
comment: optional comment
|
|
1019
|
+
|
|
1020
|
+
Returns:
|
|
1021
|
+
The original resource, with the added related resources
|
|
1022
|
+
|
|
1023
|
+
Examples:
|
|
1024
|
+
```python
|
|
1025
|
+
video_segment = video_segment.add_relates_to_optional("target_resource_id")
|
|
1026
|
+
```
|
|
1027
|
+
|
|
1028
|
+
```python
|
|
1029
|
+
video_segment = video_segment.add_relates_to_optional(None)
|
|
1030
|
+
```
|
|
1031
|
+
"""
|
|
1032
|
+
if is_nonempty_value(relates_to):
|
|
1033
|
+
self.add_relates_to(relates_to, permissions, comment)
|
|
1034
|
+
return self
|
|
1035
|
+
|
|
1036
|
+
|
|
1037
|
+
@dataclass
|
|
1038
|
+
class AudioSegmentResource:
|
|
1039
|
+
res_id: str
|
|
1040
|
+
label: str
|
|
1041
|
+
segment_bounds: SegmentBounds
|
|
1042
|
+
values: list[Value]
|
|
1043
|
+
permissions: Permissions = Permissions.PROJECT_SPECIFIC_PERMISSIONS
|
|
1044
|
+
migration_metadata: MigrationMetadata | None = None
|
|
1045
|
+
|
|
1046
|
+
@staticmethod
|
|
1047
|
+
def create_new(
|
|
1048
|
+
res_id: str,
|
|
1049
|
+
label: str,
|
|
1050
|
+
segment_of: str,
|
|
1051
|
+
segment_start: float | int | str,
|
|
1052
|
+
segment_end: float | int | str,
|
|
1053
|
+
permissions: Permissions = Permissions.PROJECT_SPECIFIC_PERMISSIONS,
|
|
1054
|
+
) -> AudioSegmentResource:
|
|
1055
|
+
"""
|
|
1056
|
+
Creates a new audio segment resource, i.e. a time span of an AudioRepresentation.
|
|
1057
|
+
|
|
1058
|
+
[See XML documentation for details](https://docs.dasch.swiss/latest/DSP-TOOLS/file-formats/xml-data-file/#video-segment-and-audio-segment)
|
|
1059
|
+
|
|
1060
|
+
Args:
|
|
1061
|
+
res_id: ID of this audio segment resource
|
|
1062
|
+
label: label of this audio segment resource
|
|
1063
|
+
segment_of: ID of the audio resource that this segment refers to (cardinality 1)
|
|
1064
|
+
segment_start: start of the segment in seconds (cardinality 1)
|
|
1065
|
+
segment_end: end of the segment in seconds (cardinality 1)
|
|
1066
|
+
permissions: permissions of this resource
|
|
1067
|
+
|
|
1068
|
+
Returns:
|
|
1069
|
+
An audio segment resource
|
|
1070
|
+
"""
|
|
1071
|
+
_check_strings(string_to_check=res_id, res_id=res_id, field_name="Resource ID")
|
|
1072
|
+
res_id = str(res_id)
|
|
1073
|
+
lbl = check_and_fix_is_non_empty_string(value=label, res_id=res_id, value_field="label")
|
|
1074
|
+
segment_of_val = LinkValue.new(
|
|
1075
|
+
value=segment_of, prop_name="isSegmentOf", permissions=permissions, comment=None, resource_id=res_id
|
|
1076
|
+
)
|
|
1077
|
+
return AudioSegmentResource(
|
|
1078
|
+
res_id=res_id,
|
|
1079
|
+
label=lbl,
|
|
1080
|
+
segment_bounds=SegmentBounds(segment_start, segment_end, permissions, res_id),
|
|
1081
|
+
values=[segment_of_val],
|
|
1082
|
+
permissions=permissions,
|
|
1083
|
+
)
|
|
1084
|
+
|
|
1085
|
+
def add_title(
|
|
1086
|
+
self,
|
|
1087
|
+
title: str,
|
|
1088
|
+
permissions: Permissions = Permissions.PROJECT_SPECIFIC_PERMISSIONS,
|
|
1089
|
+
comment: str | None = None,
|
|
1090
|
+
) -> AudioSegmentResource:
|
|
1091
|
+
"""
|
|
1092
|
+
Add a title to the resource.
|
|
1093
|
+
|
|
1094
|
+
Args:
|
|
1095
|
+
title: text
|
|
1096
|
+
permissions: permissions of the value
|
|
1097
|
+
comment: comments on the value
|
|
1098
|
+
|
|
1099
|
+
Returns:
|
|
1100
|
+
The original resource, with the added title
|
|
1101
|
+
|
|
1102
|
+
Examples:
|
|
1103
|
+
```python
|
|
1104
|
+
audio_segment = audio_segment.add_title("segment title")
|
|
1105
|
+
```
|
|
1106
|
+
"""
|
|
1107
|
+
existing_title = [x for x in self.values if x.prop_name == "hasTitle"]
|
|
1108
|
+
if any(existing_title):
|
|
1109
|
+
_warn_value_exists(
|
|
1110
|
+
old_value=existing_title.pop(0).value, new_value=title, value_field="title", res_id=self.res_id
|
|
1111
|
+
)
|
|
1112
|
+
self.values.append(
|
|
1113
|
+
SimpleText.new(
|
|
1114
|
+
value=title,
|
|
1115
|
+
prop_name="hasTitle",
|
|
1116
|
+
permissions=permissions,
|
|
1117
|
+
comment=comment,
|
|
1118
|
+
resource_id=self.res_id,
|
|
1119
|
+
)
|
|
1120
|
+
)
|
|
1121
|
+
return self
|
|
1122
|
+
|
|
1123
|
+
def add_title_optional(
|
|
1124
|
+
self,
|
|
1125
|
+
title: Any,
|
|
1126
|
+
permissions: Permissions = Permissions.PROJECT_SPECIFIC_PERMISSIONS,
|
|
1127
|
+
comment: str | None = None,
|
|
1128
|
+
) -> AudioSegmentResource:
|
|
1129
|
+
"""
|
|
1130
|
+
If the value is not empty, add it as title, otherwise return the resource unchanged.
|
|
1131
|
+
|
|
1132
|
+
Args:
|
|
1133
|
+
title: text or empty value
|
|
1134
|
+
permissions: permissions of the value
|
|
1135
|
+
comment: comments on the value
|
|
1136
|
+
|
|
1137
|
+
Returns:
|
|
1138
|
+
The original resource, with the added title
|
|
1139
|
+
|
|
1140
|
+
Examples:
|
|
1141
|
+
```python
|
|
1142
|
+
audio_segment = audio_segment.add_title("segment title")
|
|
1143
|
+
```
|
|
1144
|
+
|
|
1145
|
+
```python
|
|
1146
|
+
audio_segment = audio_segment.add_title(None)
|
|
1147
|
+
```
|
|
1148
|
+
"""
|
|
1149
|
+
if is_nonempty_value(title):
|
|
1150
|
+
self.add_title(title, permissions, comment)
|
|
1151
|
+
return self
|
|
1152
|
+
|
|
1153
|
+
def add_comment(
|
|
1154
|
+
self,
|
|
1155
|
+
text: str,
|
|
1156
|
+
permissions: Permissions = Permissions.PROJECT_SPECIFIC_PERMISSIONS,
|
|
1157
|
+
comment: str | None = None,
|
|
1158
|
+
newline_replacement: NewlineReplacement = NewlineReplacement.LINEBREAK,
|
|
1159
|
+
) -> AudioSegmentResource:
|
|
1160
|
+
"""
|
|
1161
|
+
Add a comment to the resource
|
|
1162
|
+
|
|
1163
|
+
Args:
|
|
1164
|
+
text: text of the comment
|
|
1165
|
+
permissions: optional permissions of this value
|
|
1166
|
+
comment: optional comment about this comment
|
|
1167
|
+
newline_replacement: options how to deal with `\\n` inside the text value. Default: replace with `<br/>`
|
|
1168
|
+
|
|
1169
|
+
Returns:
|
|
1170
|
+
The original resource, with the added comment
|
|
1171
|
+
|
|
1172
|
+
Examples:
|
|
1173
|
+
```python
|
|
1174
|
+
audio_segment = audio_segment.add_comment("comment text")
|
|
1175
|
+
```
|
|
1176
|
+
"""
|
|
1177
|
+
self.values.append(
|
|
1178
|
+
Richtext.new(
|
|
1179
|
+
value=text,
|
|
1180
|
+
prop_name="hasComment",
|
|
1181
|
+
permissions=permissions,
|
|
1182
|
+
comment=comment,
|
|
1183
|
+
resource_id=self.res_id,
|
|
1184
|
+
newline_replacement=newline_replacement,
|
|
1185
|
+
)
|
|
1186
|
+
)
|
|
1187
|
+
return self
|
|
1188
|
+
|
|
1189
|
+
def add_comment_multiple(
|
|
1190
|
+
self,
|
|
1191
|
+
texts: Collection[str],
|
|
1192
|
+
permissions: Permissions = Permissions.PROJECT_SPECIFIC_PERMISSIONS,
|
|
1193
|
+
comment: str | None = None,
|
|
1194
|
+
newline_replacement: NewlineReplacement = NewlineReplacement.LINEBREAK,
|
|
1195
|
+
) -> AudioSegmentResource:
|
|
1196
|
+
"""
|
|
1197
|
+
Add several comments to the resource
|
|
1198
|
+
|
|
1199
|
+
Args:
|
|
1200
|
+
texts: list of texts
|
|
1201
|
+
permissions: optional permissions of these values
|
|
1202
|
+
comment: optional comment about these comments
|
|
1203
|
+
newline_replacement: options how to deal with `\\n` inside the text value. Default: replace with `<br/>`
|
|
1204
|
+
|
|
1205
|
+
Returns:
|
|
1206
|
+
The original resource, with the added comments
|
|
1207
|
+
|
|
1208
|
+
Examples:
|
|
1209
|
+
```python
|
|
1210
|
+
audio_segment = audio_segment.add_comment_multiple(["comment 1", "comment 2"])
|
|
1211
|
+
```
|
|
1212
|
+
"""
|
|
1213
|
+
vals = check_and_fix_collection_input(texts, "hasComment", self.res_id)
|
|
1214
|
+
for v in vals:
|
|
1215
|
+
self.add_comment(v, permissions, comment, newline_replacement)
|
|
1216
|
+
return self
|
|
1217
|
+
|
|
1218
|
+
def add_comment_optional(
|
|
1219
|
+
self,
|
|
1220
|
+
text: Any,
|
|
1221
|
+
permissions: Permissions = Permissions.PROJECT_SPECIFIC_PERMISSIONS,
|
|
1222
|
+
comment: str | None = None,
|
|
1223
|
+
newline_replacement: NewlineReplacement = NewlineReplacement.LINEBREAK,
|
|
1224
|
+
) -> AudioSegmentResource:
|
|
1225
|
+
"""
|
|
1226
|
+
If the value is not empty, add it as comment, otherwise return the resource unchanged.
|
|
1227
|
+
|
|
1228
|
+
Args:
|
|
1229
|
+
text: text of the comment (or empty value)
|
|
1230
|
+
permissions: optional permissions of this value
|
|
1231
|
+
comment: optional comment about this comment
|
|
1232
|
+
newline_replacement: options how to deal with `\\n` inside the text value. Default: replace with `<br/>`
|
|
1233
|
+
|
|
1234
|
+
Returns:
|
|
1235
|
+
The original resource, with the added comment
|
|
1236
|
+
|
|
1237
|
+
Examples:
|
|
1238
|
+
```python
|
|
1239
|
+
audio_segment = audio_segment.add_comment_optional("comment text")
|
|
1240
|
+
```
|
|
1241
|
+
|
|
1242
|
+
```python
|
|
1243
|
+
audio_segment = audio_segment.add_comment_optional(None)
|
|
1244
|
+
```
|
|
1245
|
+
"""
|
|
1246
|
+
if is_nonempty_value(text):
|
|
1247
|
+
self.add_comment(text, permissions, comment, newline_replacement)
|
|
1248
|
+
return self
|
|
1249
|
+
|
|
1250
|
+
def add_description(
|
|
1251
|
+
self,
|
|
1252
|
+
description: str,
|
|
1253
|
+
permissions: Permissions = Permissions.PROJECT_SPECIFIC_PERMISSIONS,
|
|
1254
|
+
comment: str | None = None,
|
|
1255
|
+
newline_replacement: NewlineReplacement = NewlineReplacement.LINEBREAK,
|
|
1256
|
+
) -> AudioSegmentResource:
|
|
1257
|
+
"""
|
|
1258
|
+
Add a description to the resource
|
|
1259
|
+
|
|
1260
|
+
Args:
|
|
1261
|
+
description: text
|
|
1262
|
+
permissions: optional permissions of this value
|
|
1263
|
+
comment: optional comment
|
|
1264
|
+
newline_replacement: options how to deal with `\\n` inside the text value. Default: replace with `<br/>`
|
|
1265
|
+
|
|
1266
|
+
Returns:
|
|
1267
|
+
The original resource, with the added description
|
|
1268
|
+
|
|
1269
|
+
Examples:
|
|
1270
|
+
```python
|
|
1271
|
+
audio_segment = audio_segment.add_description("description text")
|
|
1272
|
+
```
|
|
1273
|
+
"""
|
|
1274
|
+
self.values.append(
|
|
1275
|
+
Richtext.new(
|
|
1276
|
+
value=description,
|
|
1277
|
+
prop_name="hasDescription",
|
|
1278
|
+
permissions=permissions,
|
|
1279
|
+
comment=comment,
|
|
1280
|
+
resource_id=self.res_id,
|
|
1281
|
+
newline_replacement=newline_replacement,
|
|
1282
|
+
)
|
|
1283
|
+
)
|
|
1284
|
+
return self
|
|
1285
|
+
|
|
1286
|
+
def add_description_multiple(
|
|
1287
|
+
self,
|
|
1288
|
+
descriptions: Collection[str],
|
|
1289
|
+
permissions: Permissions = Permissions.PROJECT_SPECIFIC_PERMISSIONS,
|
|
1290
|
+
comment: str | None = None,
|
|
1291
|
+
newline_replacement: NewlineReplacement = NewlineReplacement.LINEBREAK,
|
|
1292
|
+
) -> AudioSegmentResource:
|
|
1293
|
+
"""
|
|
1294
|
+
Add several descriptions to the resource
|
|
1295
|
+
|
|
1296
|
+
Args:
|
|
1297
|
+
descriptions: list of texts
|
|
1298
|
+
permissions: optional permissions of these values
|
|
1299
|
+
comment: optional comment
|
|
1300
|
+
newline_replacement: options how to deal with `\\n` inside the text value. Default: replace with `<br/>`
|
|
1301
|
+
|
|
1302
|
+
Returns:
|
|
1303
|
+
The original resource, with the added descriptions
|
|
1304
|
+
|
|
1305
|
+
Examples:
|
|
1306
|
+
```python
|
|
1307
|
+
audio_segment = audio_segment.add_description_multiple(["description 1", "description 2"])
|
|
1308
|
+
```
|
|
1309
|
+
"""
|
|
1310
|
+
vals = check_and_fix_collection_input(descriptions, "description", self.res_id)
|
|
1311
|
+
for v in vals:
|
|
1312
|
+
self.add_description(v, permissions, comment, newline_replacement)
|
|
1313
|
+
return self
|
|
1314
|
+
|
|
1315
|
+
def add_description_optional(
|
|
1316
|
+
self,
|
|
1317
|
+
description: Any,
|
|
1318
|
+
permissions: Permissions = Permissions.PROJECT_SPECIFIC_PERMISSIONS,
|
|
1319
|
+
comment: str | None = None,
|
|
1320
|
+
newline_replacement: NewlineReplacement = NewlineReplacement.LINEBREAK,
|
|
1321
|
+
) -> AudioSegmentResource:
|
|
1322
|
+
"""
|
|
1323
|
+
If the value is not empty, add it as description, otherwise return the resource unchanged.
|
|
1324
|
+
|
|
1325
|
+
Args:
|
|
1326
|
+
description: text or empty value
|
|
1327
|
+
permissions: optional permissions of this value
|
|
1328
|
+
comment: optional comment
|
|
1329
|
+
newline_replacement: options how to deal with `\\n` inside the text value. Default: replace with `<br/>`
|
|
1330
|
+
|
|
1331
|
+
Returns:
|
|
1332
|
+
The original resource, with the added description
|
|
1333
|
+
|
|
1334
|
+
Examples:
|
|
1335
|
+
```python
|
|
1336
|
+
audio_segment = audio_segment.add_description_optional("description text")
|
|
1337
|
+
```
|
|
1338
|
+
|
|
1339
|
+
```python
|
|
1340
|
+
audio_segment = audio_segment.add_description_optional(None)
|
|
1341
|
+
```
|
|
1342
|
+
"""
|
|
1343
|
+
if is_nonempty_value(description):
|
|
1344
|
+
self.add_description(description, permissions, comment, newline_replacement)
|
|
1345
|
+
return self
|
|
1346
|
+
|
|
1347
|
+
def add_keyword(
|
|
1348
|
+
self,
|
|
1349
|
+
keyword: str,
|
|
1350
|
+
permissions: Permissions = Permissions.PROJECT_SPECIFIC_PERMISSIONS,
|
|
1351
|
+
comment: str | None = None,
|
|
1352
|
+
) -> AudioSegmentResource:
|
|
1353
|
+
"""
|
|
1354
|
+
Add a keyword to the resource
|
|
1355
|
+
|
|
1356
|
+
Args:
|
|
1357
|
+
keyword: text
|
|
1358
|
+
permissions: optional permissions of this value
|
|
1359
|
+
comment: optional comment
|
|
1360
|
+
|
|
1361
|
+
Returns:
|
|
1362
|
+
The original resource, with the added keyword
|
|
1363
|
+
|
|
1364
|
+
Examples:
|
|
1365
|
+
```python
|
|
1366
|
+
audio_segment = audio_segment.add_keyword("keyword")
|
|
1367
|
+
```
|
|
1368
|
+
"""
|
|
1369
|
+
self.values.append(
|
|
1370
|
+
SimpleText.new(
|
|
1371
|
+
value=keyword,
|
|
1372
|
+
prop_name="hasKeyword",
|
|
1373
|
+
permissions=permissions,
|
|
1374
|
+
comment=comment,
|
|
1375
|
+
resource_id=self.res_id,
|
|
1376
|
+
)
|
|
1377
|
+
)
|
|
1378
|
+
return self
|
|
1379
|
+
|
|
1380
|
+
def add_keyword_multiple(
|
|
1381
|
+
self,
|
|
1382
|
+
keywords: Collection[str],
|
|
1383
|
+
permissions: Permissions = Permissions.PROJECT_SPECIFIC_PERMISSIONS,
|
|
1384
|
+
comment: str | None = None,
|
|
1385
|
+
) -> AudioSegmentResource:
|
|
1386
|
+
"""
|
|
1387
|
+
Add several keywords to the resource
|
|
1388
|
+
|
|
1389
|
+
Args:
|
|
1390
|
+
keywords: list of texts
|
|
1391
|
+
permissions: optional permissions of these values
|
|
1392
|
+
comment: optional comment
|
|
1393
|
+
|
|
1394
|
+
Returns:
|
|
1395
|
+
The original resource, with the added keywords
|
|
1396
|
+
|
|
1397
|
+
Examples:
|
|
1398
|
+
```python
|
|
1399
|
+
audio_segment = audio_segment.add_keyword_multiple(["keyword 1", "keyword 2"])
|
|
1400
|
+
```
|
|
1401
|
+
"""
|
|
1402
|
+
vals = check_and_fix_collection_input(keywords, "keywords", self.res_id)
|
|
1403
|
+
for v in vals:
|
|
1404
|
+
self.add_keyword(v, permissions, comment)
|
|
1405
|
+
return self
|
|
1406
|
+
|
|
1407
|
+
def add_keyword_optional(
|
|
1408
|
+
self,
|
|
1409
|
+
keyword: Any,
|
|
1410
|
+
permissions: Permissions = Permissions.PROJECT_SPECIFIC_PERMISSIONS,
|
|
1411
|
+
comment: str | None = None,
|
|
1412
|
+
) -> AudioSegmentResource:
|
|
1413
|
+
"""
|
|
1414
|
+
If the value is not empty, add it as keyword, otherwise return the resource unchanged.
|
|
1415
|
+
|
|
1416
|
+
Args:
|
|
1417
|
+
keyword: text or empty value
|
|
1418
|
+
permissions: optional permissions of this value
|
|
1419
|
+
comment: optional comment
|
|
1420
|
+
|
|
1421
|
+
Returns:
|
|
1422
|
+
The original resource, with the added keyword
|
|
1423
|
+
|
|
1424
|
+
Examples:
|
|
1425
|
+
```python
|
|
1426
|
+
audio_segment = audio_segment.add_keyword_optional("keyword")
|
|
1427
|
+
```
|
|
1428
|
+
|
|
1429
|
+
```python
|
|
1430
|
+
audio_segment = audio_segment.add_keyword_optional(None)
|
|
1431
|
+
```
|
|
1432
|
+
"""
|
|
1433
|
+
if is_nonempty_value(keyword):
|
|
1434
|
+
self.add_keyword(keyword, permissions, comment)
|
|
1435
|
+
return self
|
|
1436
|
+
|
|
1437
|
+
def add_relates_to(
|
|
1438
|
+
self,
|
|
1439
|
+
relates_to: str,
|
|
1440
|
+
permissions: Permissions = Permissions.PROJECT_SPECIFIC_PERMISSIONS,
|
|
1441
|
+
comment: str | None = None,
|
|
1442
|
+
) -> AudioSegmentResource:
|
|
1443
|
+
"""
|
|
1444
|
+
Add a link to a related resource
|
|
1445
|
+
|
|
1446
|
+
Args:
|
|
1447
|
+
relates_to: ID of the related resource
|
|
1448
|
+
permissions: optional permissions of this value
|
|
1449
|
+
comment: optional comment
|
|
1450
|
+
|
|
1451
|
+
Returns:
|
|
1452
|
+
The original resource, with the added related resource
|
|
1453
|
+
|
|
1454
|
+
Examples:
|
|
1455
|
+
```python
|
|
1456
|
+
audio_segment = audio_segment.add_relates_to("target_resource_id")
|
|
1457
|
+
```
|
|
1458
|
+
"""
|
|
1459
|
+
self.values.append(
|
|
1460
|
+
LinkValue.new(
|
|
1461
|
+
value=relates_to,
|
|
1462
|
+
prop_name="relatesTo",
|
|
1463
|
+
permissions=permissions,
|
|
1464
|
+
comment=comment,
|
|
1465
|
+
resource_id=self.res_id,
|
|
1466
|
+
)
|
|
1467
|
+
)
|
|
1468
|
+
return self
|
|
1469
|
+
|
|
1470
|
+
def add_relates_to_multiple(
|
|
1471
|
+
self,
|
|
1472
|
+
relates_to: Collection[str],
|
|
1473
|
+
permissions: Permissions = Permissions.PROJECT_SPECIFIC_PERMISSIONS,
|
|
1474
|
+
comment: str | None = None,
|
|
1475
|
+
) -> AudioSegmentResource:
|
|
1476
|
+
"""
|
|
1477
|
+
Add several links to related resources
|
|
1478
|
+
|
|
1479
|
+
Args:
|
|
1480
|
+
relates_to: list of IDs of the related resources
|
|
1481
|
+
permissions: optional permissions of these values
|
|
1482
|
+
comment: optional comment
|
|
1483
|
+
|
|
1484
|
+
Returns:
|
|
1485
|
+
The original resource, with the added related resources
|
|
1486
|
+
|
|
1487
|
+
Examples:
|
|
1488
|
+
```python
|
|
1489
|
+
audio_segment = audio_segment.add_relates_to_multiple(["target_resource_id_1", "target_resource_id_2"])
|
|
1490
|
+
```
|
|
1491
|
+
"""
|
|
1492
|
+
vals = check_and_fix_collection_input(relates_to, "relatesTo", self.res_id)
|
|
1493
|
+
for v in vals:
|
|
1494
|
+
self.add_relates_to(v, permissions, comment)
|
|
1495
|
+
return self
|
|
1496
|
+
|
|
1497
|
+
def add_relates_to_optional(
|
|
1498
|
+
self,
|
|
1499
|
+
relates_to: Any,
|
|
1500
|
+
permissions: Permissions = Permissions.PROJECT_SPECIFIC_PERMISSIONS,
|
|
1501
|
+
comment: str | None = None,
|
|
1502
|
+
) -> AudioSegmentResource:
|
|
1503
|
+
"""
|
|
1504
|
+
If the value is not empty, add it as related resource, otherwise return the resource unchanged.
|
|
1505
|
+
|
|
1506
|
+
Args:
|
|
1507
|
+
relates_to: ID of the related resource or empty value
|
|
1508
|
+
permissions: optional permissions of this value
|
|
1509
|
+
comment: optional comment
|
|
1510
|
+
|
|
1511
|
+
Returns:
|
|
1512
|
+
The original resource, with the added related resources
|
|
1513
|
+
|
|
1514
|
+
Examples:
|
|
1515
|
+
```python
|
|
1516
|
+
audio_segment = audio_segment.add_relates_to_optional("target_resource_id")
|
|
1517
|
+
```
|
|
1518
|
+
|
|
1519
|
+
```python
|
|
1520
|
+
audio_segment = audio_segment.add_relates_to_optional(None)
|
|
1521
|
+
```
|
|
1522
|
+
"""
|
|
1523
|
+
if is_nonempty_value(relates_to):
|
|
1524
|
+
self.add_relates_to(relates_to, permissions, comment)
|
|
1525
|
+
return self
|
|
1526
|
+
|
|
1527
|
+
|
|
1528
|
+
def _check_strings(
|
|
1529
|
+
*, string_to_check: str, res_id: str, prop_name: str | None = None, field_name: str | None = None
|
|
1530
|
+
) -> None:
|
|
1531
|
+
if not is_nonempty_value(string_to_check):
|
|
1532
|
+
msg_info = MessageInfo("The entered string is not valid.", res_id, prop_name, field_name)
|
|
1533
|
+
emit_xmllib_input_warning(msg_info)
|
|
1534
|
+
|
|
1535
|
+
|
|
1536
|
+
def _warn_value_exists(*, old_value: Any, new_value: Any, res_id: str | None, value_field: str | None = None) -> None:
|
|
1537
|
+
msg = (
|
|
1538
|
+
f"This resource already has a value in this location. "
|
|
1539
|
+
f"The old value '{old_value}' is being replace with '{new_value}'."
|
|
1540
|
+
)
|
|
1541
|
+
msg_info = MessageInfo(msg, res_id, field=value_field)
|
|
1542
|
+
emit_xmllib_input_warning(msg_info)
|