dsp-tools 9.1.0.post11__py3-none-any.whl → 18.3.0.post13__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (316) hide show
  1. dsp_tools/__init__.py +4 -0
  2. dsp_tools/cli/args.py +36 -0
  3. dsp_tools/cli/call_action.py +51 -231
  4. dsp_tools/cli/call_action_files_only.py +101 -0
  5. dsp_tools/cli/call_action_with_network.py +207 -0
  6. dsp_tools/cli/create_parsers.py +156 -58
  7. dsp_tools/cli/entry_point.py +56 -26
  8. dsp_tools/cli/utils.py +87 -0
  9. dsp_tools/clients/CLAUDE.md +420 -0
  10. dsp_tools/clients/authentication_client.py +14 -0
  11. dsp_tools/clients/authentication_client_live.py +66 -0
  12. dsp_tools/{utils → clients}/connection.py +2 -18
  13. dsp_tools/clients/connection_live.py +233 -0
  14. dsp_tools/clients/fuseki_metrics.py +60 -0
  15. dsp_tools/clients/group_user_clients.py +35 -0
  16. dsp_tools/clients/group_user_clients_live.py +181 -0
  17. dsp_tools/clients/legal_info_client.py +23 -0
  18. dsp_tools/clients/legal_info_client_live.py +132 -0
  19. dsp_tools/clients/list_client.py +49 -0
  20. dsp_tools/clients/list_client_live.py +166 -0
  21. dsp_tools/clients/metadata_client.py +24 -0
  22. dsp_tools/clients/metadata_client_live.py +47 -0
  23. dsp_tools/clients/ontology_clients.py +49 -0
  24. dsp_tools/clients/ontology_create_client_live.py +166 -0
  25. dsp_tools/clients/ontology_get_client_live.py +80 -0
  26. dsp_tools/clients/permissions_client.py +68 -0
  27. dsp_tools/clients/project_client.py +16 -0
  28. dsp_tools/clients/project_client_live.py +66 -0
  29. dsp_tools/commands/create/communicate_problems.py +24 -0
  30. dsp_tools/commands/create/create.py +134 -0
  31. dsp_tools/commands/create/create_on_server/cardinalities.py +111 -0
  32. dsp_tools/commands/create/create_on_server/classes.py +99 -0
  33. dsp_tools/commands/create/create_on_server/complete_ontologies.py +116 -0
  34. dsp_tools/commands/create/create_on_server/default_permissions.py +134 -0
  35. dsp_tools/commands/create/create_on_server/group_users.py +165 -0
  36. dsp_tools/commands/create/create_on_server/lists.py +163 -0
  37. dsp_tools/commands/create/create_on_server/mappers.py +12 -0
  38. dsp_tools/commands/create/create_on_server/onto_utils.py +74 -0
  39. dsp_tools/commands/create/create_on_server/ontology.py +52 -0
  40. dsp_tools/commands/create/create_on_server/project.py +68 -0
  41. dsp_tools/commands/create/create_on_server/properties.py +119 -0
  42. dsp_tools/commands/create/exceptions.py +29 -0
  43. dsp_tools/commands/create/lists_only.py +66 -0
  44. dsp_tools/commands/create/models/create_problems.py +87 -0
  45. dsp_tools/commands/create/models/parsed_ontology.py +88 -0
  46. dsp_tools/commands/create/models/parsed_project.py +81 -0
  47. dsp_tools/commands/create/models/rdf_ontology.py +12 -0
  48. dsp_tools/commands/create/models/server_project_info.py +100 -0
  49. dsp_tools/commands/create/parsing/parse_lists.py +45 -0
  50. dsp_tools/commands/create/parsing/parse_ontology.py +243 -0
  51. dsp_tools/commands/create/parsing/parse_project.py +149 -0
  52. dsp_tools/commands/create/parsing/parsing_utils.py +40 -0
  53. dsp_tools/commands/create/project_validate.py +595 -0
  54. dsp_tools/commands/create/serialisation/ontology.py +119 -0
  55. dsp_tools/commands/create/serialisation/project.py +44 -0
  56. dsp_tools/commands/excel2json/CLAUDE.md +101 -0
  57. dsp_tools/commands/excel2json/json_header.py +57 -23
  58. dsp_tools/commands/excel2json/{new_lists → lists}/compliance_checks.py +26 -26
  59. dsp_tools/commands/excel2json/{new_lists/make_new_lists.py → lists/make_lists.py} +19 -18
  60. dsp_tools/commands/excel2json/{new_lists → lists}/models/input_error.py +1 -12
  61. dsp_tools/commands/excel2json/{new_lists → lists}/models/serialise.py +9 -5
  62. dsp_tools/commands/excel2json/{new_lists → lists}/utils.py +4 -4
  63. dsp_tools/commands/excel2json/models/input_error.py +31 -11
  64. dsp_tools/commands/excel2json/models/json_header.py +53 -15
  65. dsp_tools/commands/excel2json/models/ontology.py +4 -3
  66. dsp_tools/commands/excel2json/{lists.py → old_lists.py} +26 -112
  67. dsp_tools/commands/excel2json/project.py +78 -34
  68. dsp_tools/commands/excel2json/properties.py +57 -36
  69. dsp_tools/commands/excel2json/resources.py +32 -12
  70. dsp_tools/commands/excel2json/utils.py +20 -1
  71. dsp_tools/commands/excel2xml/__init__.py +2 -2
  72. dsp_tools/commands/excel2xml/excel2xml_cli.py +7 -15
  73. dsp_tools/commands/excel2xml/excel2xml_lib.py +138 -493
  74. dsp_tools/commands/excel2xml/propertyelement.py +5 -5
  75. dsp_tools/commands/{project → get}/get.py +29 -13
  76. dsp_tools/commands/get/get_permissions.py +257 -0
  77. dsp_tools/commands/get/get_permissions_legacy.py +89 -0
  78. dsp_tools/commands/{project/models → get/legacy_models}/context.py +6 -6
  79. dsp_tools/commands/{project/models → get/legacy_models}/group.py +5 -10
  80. dsp_tools/commands/{project/models → get/legacy_models}/listnode.py +5 -35
  81. dsp_tools/commands/{project/models → get/legacy_models}/model.py +1 -1
  82. dsp_tools/commands/{project/models → get/legacy_models}/ontology.py +9 -14
  83. dsp_tools/commands/{project/models → get/legacy_models}/project.py +13 -6
  84. dsp_tools/commands/{project/models → get/legacy_models}/propertyclass.py +9 -16
  85. dsp_tools/commands/{project/models → get/legacy_models}/resourceclass.py +8 -46
  86. dsp_tools/commands/{project/models → get/legacy_models}/user.py +19 -60
  87. dsp_tools/commands/get/models/permissions_models.py +10 -0
  88. dsp_tools/commands/id2iri.py +20 -10
  89. dsp_tools/commands/ingest_xmlupload/bulk_ingest_client.py +81 -56
  90. dsp_tools/commands/ingest_xmlupload/create_resources/apply_ingest_id.py +4 -10
  91. dsp_tools/commands/ingest_xmlupload/create_resources/upload_xml.py +97 -37
  92. dsp_tools/commands/ingest_xmlupload/create_resources/user_information.py +2 -2
  93. dsp_tools/commands/ingest_xmlupload/ingest_files/ingest_files.py +9 -10
  94. dsp_tools/commands/ingest_xmlupload/upload_files/filechecker.py +3 -3
  95. dsp_tools/commands/ingest_xmlupload/upload_files/input_error.py +2 -10
  96. dsp_tools/commands/ingest_xmlupload/upload_files/upload_failures.py +12 -2
  97. dsp_tools/commands/ingest_xmlupload/upload_files/upload_files.py +8 -9
  98. dsp_tools/commands/resume_xmlupload/resume_xmlupload.py +18 -18
  99. dsp_tools/commands/start_stack.py +126 -77
  100. dsp_tools/commands/update_legal/CLAUDE.md +344 -0
  101. dsp_tools/commands/update_legal/__init__.py +0 -0
  102. dsp_tools/commands/update_legal/core.py +182 -0
  103. dsp_tools/commands/update_legal/csv_operations.py +135 -0
  104. dsp_tools/commands/update_legal/models.py +87 -0
  105. dsp_tools/commands/update_legal/xml_operations.py +247 -0
  106. dsp_tools/commands/validate_data/CLAUDE.md +159 -0
  107. dsp_tools/commands/validate_data/__init__.py +0 -0
  108. dsp_tools/commands/validate_data/constants.py +59 -0
  109. dsp_tools/commands/validate_data/mappers.py +143 -0
  110. dsp_tools/commands/validate_data/models/__init__.py +0 -0
  111. dsp_tools/commands/validate_data/models/api_responses.py +45 -0
  112. dsp_tools/commands/validate_data/models/input_problems.py +119 -0
  113. dsp_tools/commands/validate_data/models/rdf_like_data.py +117 -0
  114. dsp_tools/commands/validate_data/models/validation.py +106 -0
  115. dsp_tools/commands/validate_data/prepare_data/__init__.py +0 -0
  116. dsp_tools/commands/validate_data/prepare_data/get_rdf_like_data.py +296 -0
  117. dsp_tools/commands/validate_data/prepare_data/make_data_graph.py +91 -0
  118. dsp_tools/commands/validate_data/prepare_data/prepare_data.py +184 -0
  119. dsp_tools/commands/validate_data/process_validation_report/__init__.py +0 -0
  120. dsp_tools/commands/validate_data/process_validation_report/get_user_validation_message.py +358 -0
  121. dsp_tools/commands/validate_data/process_validation_report/query_validation_result.py +507 -0
  122. dsp_tools/commands/validate_data/process_validation_report/reformat_validation_results.py +150 -0
  123. dsp_tools/commands/validate_data/shacl_cli_validator.py +70 -0
  124. dsp_tools/commands/validate_data/sparql/__init__.py +0 -0
  125. dsp_tools/commands/{xml_validate/sparql/resource_shacl.py → validate_data/sparql/cardinality_shacl.py} +45 -47
  126. dsp_tools/commands/validate_data/sparql/construct_shacl.py +92 -0
  127. dsp_tools/commands/validate_data/sparql/legal_info_shacl.py +36 -0
  128. dsp_tools/commands/validate_data/sparql/value_shacl.py +357 -0
  129. dsp_tools/commands/validate_data/utils.py +59 -0
  130. dsp_tools/commands/validate_data/validate_data.py +283 -0
  131. dsp_tools/commands/validate_data/validation/__init__.py +0 -0
  132. dsp_tools/commands/validate_data/validation/check_duplicate_files.py +55 -0
  133. dsp_tools/commands/validate_data/validation/check_for_unknown_classes.py +67 -0
  134. dsp_tools/commands/validate_data/validation/get_validation_report.py +94 -0
  135. dsp_tools/commands/validate_data/validation/validate_ontology.py +107 -0
  136. dsp_tools/commands/xmlupload/CLAUDE.md +292 -0
  137. dsp_tools/commands/xmlupload/make_rdf_graph/__init__.py +0 -0
  138. dsp_tools/commands/xmlupload/make_rdf_graph/constants.py +63 -0
  139. dsp_tools/commands/xmlupload/make_rdf_graph/jsonld_utils.py +44 -0
  140. dsp_tools/commands/xmlupload/make_rdf_graph/make_file_value.py +77 -0
  141. dsp_tools/commands/xmlupload/make_rdf_graph/make_resource_and_values.py +114 -0
  142. dsp_tools/commands/xmlupload/make_rdf_graph/make_values.py +262 -0
  143. dsp_tools/commands/xmlupload/models/bitstream_info.py +18 -0
  144. dsp_tools/commands/xmlupload/models/formatted_text_value.py +0 -25
  145. dsp_tools/commands/xmlupload/models/ingest.py +56 -70
  146. dsp_tools/commands/xmlupload/models/input_problems.py +6 -14
  147. dsp_tools/commands/xmlupload/models/lookup_models.py +21 -0
  148. dsp_tools/commands/xmlupload/models/permission.py +0 -39
  149. dsp_tools/commands/xmlupload/models/{deserialise/xmlpermission.py → permissions_parsed.py} +2 -2
  150. dsp_tools/commands/xmlupload/models/processed/__init__.py +0 -0
  151. dsp_tools/commands/xmlupload/models/processed/file_values.py +29 -0
  152. dsp_tools/commands/xmlupload/models/processed/res.py +27 -0
  153. dsp_tools/commands/xmlupload/models/processed/values.py +101 -0
  154. dsp_tools/commands/xmlupload/models/rdf_models.py +26 -0
  155. dsp_tools/commands/xmlupload/models/upload_clients.py +3 -3
  156. dsp_tools/commands/xmlupload/models/upload_state.py +2 -4
  157. dsp_tools/commands/xmlupload/prepare_xml_input/__init__.py +0 -0
  158. dsp_tools/commands/xmlupload/{ark2iri.py → prepare_xml_input/ark2iri.py} +1 -1
  159. dsp_tools/commands/xmlupload/prepare_xml_input/get_processed_resources.py +252 -0
  160. dsp_tools/commands/xmlupload/{iiif_uri_validator.py → prepare_xml_input/iiif_uri_validator.py} +2 -14
  161. dsp_tools/commands/xmlupload/{list_client.py → prepare_xml_input/list_client.py} +15 -10
  162. dsp_tools/commands/xmlupload/prepare_xml_input/prepare_xml_input.py +67 -0
  163. dsp_tools/commands/xmlupload/prepare_xml_input/read_validate_xml_file.py +58 -0
  164. dsp_tools/commands/xmlupload/prepare_xml_input/transform_input_values.py +118 -0
  165. dsp_tools/commands/xmlupload/resource_create_client.py +7 -468
  166. dsp_tools/commands/xmlupload/richtext_id2iri.py +37 -0
  167. dsp_tools/commands/xmlupload/stash/{construct_and_analyze_graph.py → analyse_circular_reference_graph.py} +64 -157
  168. dsp_tools/commands/xmlupload/stash/create_info_for_graph.py +53 -0
  169. dsp_tools/commands/xmlupload/stash/graph_models.py +13 -8
  170. dsp_tools/commands/xmlupload/stash/stash_circular_references.py +48 -115
  171. dsp_tools/commands/xmlupload/stash/stash_models.py +4 -9
  172. dsp_tools/commands/xmlupload/stash/upload_stashed_resptr_props.py +34 -40
  173. dsp_tools/commands/xmlupload/stash/upload_stashed_xml_texts.py +98 -108
  174. dsp_tools/commands/xmlupload/upload_config.py +8 -0
  175. dsp_tools/commands/xmlupload/write_diagnostic_info.py +14 -9
  176. dsp_tools/commands/xmlupload/xmlupload.py +214 -192
  177. dsp_tools/config/__init__.py +0 -0
  178. dsp_tools/config/logger_config.py +69 -0
  179. dsp_tools/{utils → config}/warnings_config.py +4 -1
  180. dsp_tools/error/__init__.py +0 -0
  181. dsp_tools/error/custom_warnings.py +39 -0
  182. dsp_tools/error/exceptions.py +204 -0
  183. dsp_tools/error/problems.py +10 -0
  184. dsp_tools/error/xmllib_errors.py +20 -0
  185. dsp_tools/error/xmllib_warnings.py +54 -0
  186. dsp_tools/error/xmllib_warnings_util.py +159 -0
  187. dsp_tools/error/xsd_validation_error_msg.py +19 -0
  188. dsp_tools/legacy_models/__init__.py +0 -0
  189. dsp_tools/{models → legacy_models}/datetimestamp.py +7 -7
  190. dsp_tools/{models → legacy_models}/langstring.py +1 -1
  191. dsp_tools/{models → legacy_models}/projectContext.py +4 -4
  192. dsp_tools/resources/schema/data.xsd +108 -83
  193. dsp_tools/resources/schema/lists-only.json +4 -23
  194. dsp_tools/resources/schema/project.json +80 -35
  195. dsp_tools/resources/schema/properties-only.json +1 -4
  196. dsp_tools/resources/start-stack/docker-compose.override-host.j2 +11 -0
  197. dsp_tools/resources/start-stack/docker-compose.yml +34 -30
  198. dsp_tools/resources/start-stack/dsp-app-config.json +45 -0
  199. dsp_tools/resources/start-stack/dsp-app-config.override-host.j2 +26 -0
  200. dsp_tools/resources/validate_data/api-shapes-resource-cardinalities.ttl +191 -0
  201. dsp_tools/resources/validate_data/api-shapes.ttl +804 -0
  202. dsp_tools/resources/validate_data/shacl-cli-image.yml +4 -0
  203. dsp_tools/resources/validate_data/validate-ontology.ttl +99 -0
  204. dsp_tools/utils/ansi_colors.py +32 -0
  205. dsp_tools/utils/data_formats/__init__.py +0 -0
  206. dsp_tools/utils/{date_util.py → data_formats/date_util.py} +13 -1
  207. dsp_tools/utils/data_formats/iri_util.py +30 -0
  208. dsp_tools/utils/{shared.py → data_formats/shared.py} +1 -35
  209. dsp_tools/utils/{uri_util.py → data_formats/uri_util.py} +12 -2
  210. dsp_tools/utils/fuseki_bloating.py +63 -0
  211. dsp_tools/utils/json_parsing.py +22 -0
  212. dsp_tools/utils/rdf_constants.py +42 -0
  213. dsp_tools/utils/rdflib_utils.py +10 -0
  214. dsp_tools/utils/replace_id_with_iri.py +66 -0
  215. dsp_tools/utils/request_utils.py +238 -0
  216. dsp_tools/utils/xml_parsing/__init__.py +0 -0
  217. dsp_tools/utils/xml_parsing/get_lookups.py +32 -0
  218. dsp_tools/utils/xml_parsing/get_parsed_resources.py +325 -0
  219. dsp_tools/utils/xml_parsing/models/__init__.py +0 -0
  220. dsp_tools/utils/xml_parsing/models/parsed_resource.py +76 -0
  221. dsp_tools/utils/xml_parsing/parse_clean_validate_xml.py +137 -0
  222. dsp_tools/xmllib/CLAUDE.md +302 -0
  223. dsp_tools/xmllib/__init__.py +49 -0
  224. dsp_tools/xmllib/general_functions.py +877 -0
  225. dsp_tools/xmllib/internal/__init__.py +0 -0
  226. dsp_tools/xmllib/internal/checkers.py +162 -0
  227. dsp_tools/xmllib/internal/circumvent_circular_imports.py +36 -0
  228. dsp_tools/xmllib/internal/constants.py +46 -0
  229. dsp_tools/xmllib/internal/input_converters.py +155 -0
  230. dsp_tools/xmllib/internal/serialise_file_value.py +57 -0
  231. dsp_tools/xmllib/internal/serialise_resource.py +177 -0
  232. dsp_tools/xmllib/internal/serialise_values.py +152 -0
  233. dsp_tools/xmllib/internal/type_aliases.py +11 -0
  234. dsp_tools/xmllib/models/config_options.py +28 -0
  235. dsp_tools/xmllib/models/date_formats.py +48 -0
  236. dsp_tools/xmllib/models/dsp_base_resources.py +1380 -400
  237. dsp_tools/xmllib/models/internal/__init__.py +0 -0
  238. dsp_tools/xmllib/models/internal/file_values.py +172 -0
  239. dsp_tools/xmllib/models/internal/geometry.py +162 -0
  240. dsp_tools/xmllib/models/{migration_metadata.py → internal/migration_metadata.py} +14 -10
  241. dsp_tools/xmllib/models/internal/serialise_permissions.py +66 -0
  242. dsp_tools/xmllib/models/internal/values.py +342 -0
  243. dsp_tools/xmllib/models/licenses/__init__.py +0 -0
  244. dsp_tools/xmllib/models/licenses/other.py +59 -0
  245. dsp_tools/xmllib/models/licenses/recommended.py +107 -0
  246. dsp_tools/xmllib/models/permissions.py +41 -0
  247. dsp_tools/xmllib/models/res.py +1782 -0
  248. dsp_tools/xmllib/models/root.py +313 -26
  249. dsp_tools/xmllib/value_checkers.py +310 -47
  250. dsp_tools/xmllib/value_converters.py +765 -8
  251. dsp_tools-18.3.0.post13.dist-info/METADATA +90 -0
  252. dsp_tools-18.3.0.post13.dist-info/RECORD +286 -0
  253. dsp_tools-18.3.0.post13.dist-info/WHEEL +4 -0
  254. {dsp_tools-9.1.0.post11.dist-info → dsp_tools-18.3.0.post13.dist-info}/entry_points.txt +1 -0
  255. dsp_tools/commands/project/create/project_create.py +0 -1107
  256. dsp_tools/commands/project/create/project_create_lists.py +0 -204
  257. dsp_tools/commands/project/create/project_validate.py +0 -453
  258. dsp_tools/commands/project/models/project_definition.py +0 -12
  259. dsp_tools/commands/rosetta.py +0 -124
  260. dsp_tools/commands/template.py +0 -30
  261. dsp_tools/commands/xml_validate/api_connection.py +0 -122
  262. dsp_tools/commands/xml_validate/deserialise_input.py +0 -135
  263. dsp_tools/commands/xml_validate/make_data_rdf.py +0 -193
  264. dsp_tools/commands/xml_validate/models/data_deserialised.py +0 -108
  265. dsp_tools/commands/xml_validate/models/data_rdf.py +0 -214
  266. dsp_tools/commands/xml_validate/models/input_problems.py +0 -191
  267. dsp_tools/commands/xml_validate/models/validation.py +0 -29
  268. dsp_tools/commands/xml_validate/reformat_validaton_result.py +0 -89
  269. dsp_tools/commands/xml_validate/sparql/construct_shapes.py +0 -16
  270. dsp_tools/commands/xml_validate/xml_validate.py +0 -151
  271. dsp_tools/commands/xmlupload/check_consistency_with_ontology.py +0 -253
  272. dsp_tools/commands/xmlupload/models/deserialise/deserialise_value.py +0 -236
  273. dsp_tools/commands/xmlupload/models/deserialise/xmlresource.py +0 -171
  274. dsp_tools/commands/xmlupload/models/namespace_context.py +0 -39
  275. dsp_tools/commands/xmlupload/models/ontology_lookup_models.py +0 -161
  276. dsp_tools/commands/xmlupload/models/ontology_problem_models.py +0 -178
  277. dsp_tools/commands/xmlupload/models/serialise/jsonld_serialiser.py +0 -40
  278. dsp_tools/commands/xmlupload/models/serialise/serialise_value.py +0 -51
  279. dsp_tools/commands/xmlupload/ontology_client.py +0 -92
  280. dsp_tools/commands/xmlupload/project_client.py +0 -91
  281. dsp_tools/commands/xmlupload/read_validate_xml_file.py +0 -99
  282. dsp_tools/models/custom_warnings.py +0 -31
  283. dsp_tools/models/exceptions.py +0 -90
  284. dsp_tools/resources/0100-template-repo/template.json +0 -45
  285. dsp_tools/resources/0100-template-repo/template.xml +0 -27
  286. dsp_tools/resources/start-stack/docker-compose-validation.yml +0 -5
  287. dsp_tools/resources/start-stack/start-stack-config.yml +0 -4
  288. dsp_tools/resources/xml_validate/api-shapes.ttl +0 -411
  289. dsp_tools/resources/xml_validate/replace_namespace.xslt +0 -61
  290. dsp_tools/utils/connection_live.py +0 -383
  291. dsp_tools/utils/iri_util.py +0 -14
  292. dsp_tools/utils/logger_config.py +0 -41
  293. dsp_tools/utils/set_encoder.py +0 -20
  294. dsp_tools/utils/xml_utils.py +0 -145
  295. dsp_tools/utils/xml_validation.py +0 -197
  296. dsp_tools/utils/xml_validation_models.py +0 -68
  297. dsp_tools/xmllib/models/file_values.py +0 -78
  298. dsp_tools/xmllib/models/resource.py +0 -415
  299. dsp_tools/xmllib/models/values.py +0 -428
  300. dsp_tools-9.1.0.post11.dist-info/METADATA +0 -130
  301. dsp_tools-9.1.0.post11.dist-info/RECORD +0 -167
  302. dsp_tools-9.1.0.post11.dist-info/WHEEL +0 -4
  303. dsp_tools-9.1.0.post11.dist-info/licenses/LICENSE +0 -674
  304. /dsp_tools/{commands/excel2json/new_lists → clients}/__init__.py +0 -0
  305. /dsp_tools/commands/{excel2json/new_lists/models → create}/__init__.py +0 -0
  306. /dsp_tools/commands/{project → create/create_on_server}/__init__.py +0 -0
  307. /dsp_tools/commands/{project/create → create/models}/__init__.py +0 -0
  308. /dsp_tools/commands/{project/models → create/parsing}/__init__.py +0 -0
  309. /dsp_tools/commands/{xml_validate → create/serialisation}/__init__.py +0 -0
  310. /dsp_tools/commands/{xml_validate/models → excel2json/lists}/__init__.py +0 -0
  311. /dsp_tools/commands/{xml_validate/sparql → excel2json/lists/models}/__init__.py +0 -0
  312. /dsp_tools/commands/excel2json/{new_lists → lists}/models/deserialise.py +0 -0
  313. /dsp_tools/commands/{xmlupload/models/deserialise → get}/__init__.py +0 -0
  314. /dsp_tools/commands/{xmlupload/models/serialise → get/legacy_models}/__init__.py +0 -0
  315. /dsp_tools/commands/{project/models → get/legacy_models}/helpers.py +0 -0
  316. /dsp_tools/{models → commands/get/models}/__init__.py +0 -0
@@ -0,0 +1,262 @@
1
+ from typing import Union
2
+
3
+ from rdflib import RDF
4
+ from rdflib import XSD
5
+ from rdflib import BNode
6
+ from rdflib import Graph
7
+ from rdflib import Literal
8
+ from rdflib import URIRef
9
+
10
+ from dsp_tools.commands.xmlupload.iri_resolver import IriResolver
11
+ from dsp_tools.commands.xmlupload.make_rdf_graph.constants import LINK_PROP_TYPE_INFO
12
+ from dsp_tools.commands.xmlupload.make_rdf_graph.constants import LIST_PROP_TYPE_INFO
13
+ from dsp_tools.commands.xmlupload.make_rdf_graph.constants import RDF_LITERAL_PROP_TYPE_MAPPER
14
+ from dsp_tools.commands.xmlupload.make_rdf_graph.constants import RICHTEXT_PROP_TYPE_INFO
15
+ from dsp_tools.commands.xmlupload.models.lookup_models import IRILookups
16
+ from dsp_tools.commands.xmlupload.models.permission import Permissions
17
+ from dsp_tools.commands.xmlupload.models.processed.values import ProcessedBoolean
18
+ from dsp_tools.commands.xmlupload.models.processed.values import ProcessedColor
19
+ from dsp_tools.commands.xmlupload.models.processed.values import ProcessedDate
20
+ from dsp_tools.commands.xmlupload.models.processed.values import ProcessedDecimal
21
+ from dsp_tools.commands.xmlupload.models.processed.values import ProcessedGeometry
22
+ from dsp_tools.commands.xmlupload.models.processed.values import ProcessedGeoname
23
+ from dsp_tools.commands.xmlupload.models.processed.values import ProcessedInt
24
+ from dsp_tools.commands.xmlupload.models.processed.values import ProcessedInterval
25
+ from dsp_tools.commands.xmlupload.models.processed.values import ProcessedLink
26
+ from dsp_tools.commands.xmlupload.models.processed.values import ProcessedList
27
+ from dsp_tools.commands.xmlupload.models.processed.values import ProcessedRichtext
28
+ from dsp_tools.commands.xmlupload.models.processed.values import ProcessedSimpleText
29
+ from dsp_tools.commands.xmlupload.models.processed.values import ProcessedTime
30
+ from dsp_tools.commands.xmlupload.models.processed.values import ProcessedUri
31
+ from dsp_tools.commands.xmlupload.models.processed.values import ProcessedValue
32
+ from dsp_tools.commands.xmlupload.models.rdf_models import RDFPropTypeInfo
33
+ from dsp_tools.commands.xmlupload.richtext_id2iri import prepare_richtext_string_for_upload
34
+ from dsp_tools.config.logger_config import WARNINGS_SAVEPATH
35
+ from dsp_tools.error.exceptions import BaseError
36
+ from dsp_tools.error.exceptions import InputError
37
+ from dsp_tools.utils.data_formats.date_util import DayMonthYearEra
38
+ from dsp_tools.utils.data_formats.date_util import SingleDate
39
+ from dsp_tools.utils.data_formats.date_util import StartEnd
40
+ from dsp_tools.utils.data_formats.iri_util import is_resource_iri
41
+ from dsp_tools.utils.rdf_constants import KNORA_API
42
+
43
+ type LiteralValueTypesAlias = Union[
44
+ ProcessedBoolean,
45
+ ProcessedColor,
46
+ ProcessedDecimal,
47
+ ProcessedGeoname,
48
+ ProcessedGeometry,
49
+ ProcessedInt,
50
+ ProcessedSimpleText,
51
+ ProcessedTime,
52
+ ProcessedUri,
53
+ ]
54
+
55
+
56
+ def make_values(values: list[ProcessedValue], res_node: BNode | URIRef, lookups: IRILookups) -> Graph:
57
+ """
58
+ Serialise the values of a resource.
59
+
60
+ Args:
61
+ values: list of ProcessedValues of the resource
62
+ res_node: node of the resource
63
+ lookups: lookups to resolve IRIs
64
+
65
+ Returns:
66
+ Graph with the values
67
+ """
68
+ properties_graph = Graph()
69
+ for val in values:
70
+ single_prop_graph = _make_one_value_graph(val=val, res_node=res_node, iri_lookups=lookups)
71
+ properties_graph += single_prop_graph
72
+ return properties_graph
73
+
74
+
75
+ def _make_one_value_graph(val: ProcessedValue, res_node: BNode | URIRef, iri_lookups: IRILookups) -> Graph:
76
+ match val:
77
+ case (
78
+ ProcessedBoolean()
79
+ | ProcessedColor()
80
+ | ProcessedDecimal()
81
+ | ProcessedGeometry()
82
+ | ProcessedGeoname()
83
+ | ProcessedInt()
84
+ | ProcessedTime()
85
+ | ProcessedUri()
86
+ | ProcessedSimpleText()
87
+ ):
88
+ literal_info = RDF_LITERAL_PROP_TYPE_MAPPER[type(val)]
89
+ properties_graph = _make_value_graph_with_literal_object(
90
+ val=val,
91
+ res_node=res_node,
92
+ prop_type_info=literal_info,
93
+ )
94
+ case ProcessedList():
95
+ properties_graph = _make_list_value_graph(val=val, res_node=res_node, prop_type_info=LIST_PROP_TYPE_INFO)
96
+ case ProcessedLink():
97
+ target_iri = _resolve_id_to_iri(val.value, iri_lookups.id_to_iri)
98
+ properties_graph = make_link_value_graph(
99
+ val=val,
100
+ val_node=BNode(),
101
+ res_node=res_node,
102
+ target_iri=URIRef(target_iri),
103
+ )
104
+ case ProcessedRichtext():
105
+ properties_graph = make_richtext_value_graph(
106
+ val=val,
107
+ val_node=BNode(),
108
+ res_node=res_node,
109
+ iri_resolver=iri_lookups.id_to_iri,
110
+ )
111
+ case ProcessedDate():
112
+ properties_graph = _make_date_value_graph(
113
+ val=val,
114
+ res_node=res_node,
115
+ )
116
+ case ProcessedInterval():
117
+ properties_graph = _make_interval_value_graph(
118
+ val=val,
119
+ res_node=res_node,
120
+ )
121
+ case _:
122
+ raise InputError(f"Unknown value type: {type(val).__name__}")
123
+ return properties_graph
124
+
125
+
126
+ def _make_base_value_graph(
127
+ val: ProcessedValue,
128
+ val_node: BNode | URIRef,
129
+ prop_type_info: RDFPropTypeInfo,
130
+ res_node: BNode | URIRef,
131
+ ) -> Graph:
132
+ g = _add_optional_triples(val_node, val.permissions, val.comment)
133
+ g.add((res_node, URIRef(val.prop_iri), val_node))
134
+ g.add((val_node, RDF.type, prop_type_info.knora_type))
135
+ return g
136
+
137
+
138
+ def _add_optional_triples(val_bn: BNode | URIRef, permissions: Permissions | None, comment: str | None) -> Graph:
139
+ g = Graph()
140
+ if permissions:
141
+ g.add((val_bn, KNORA_API.hasPermissions, Literal(str(permissions), datatype=XSD.string)))
142
+ if comment:
143
+ g.add((val_bn, KNORA_API.valueHasComment, Literal(comment, datatype=XSD.string)))
144
+ return g
145
+
146
+
147
+ def _make_value_graph_with_literal_object(
148
+ val: LiteralValueTypesAlias,
149
+ prop_type_info: RDFPropTypeInfo,
150
+ res_node: BNode | URIRef,
151
+ ) -> Graph:
152
+ val_bn = BNode()
153
+ g = _make_base_value_graph(val=val, val_node=val_bn, prop_type_info=prop_type_info, res_node=res_node)
154
+ g.add((val_bn, prop_type_info.knora_prop, Literal(val.value, datatype=prop_type_info.xsd_type)))
155
+ return g
156
+
157
+
158
+ def _make_list_value_graph(
159
+ val: ProcessedList,
160
+ res_node: BNode | URIRef,
161
+ prop_type_info: RDFPropTypeInfo,
162
+ ) -> Graph:
163
+ val_bn = BNode()
164
+ g = _make_base_value_graph(val=val, val_node=val_bn, prop_type_info=prop_type_info, res_node=res_node)
165
+ g.add((val_bn, prop_type_info.knora_prop, URIRef(val.value)))
166
+ return g
167
+
168
+
169
+ def make_link_value_graph(
170
+ val: ProcessedLink,
171
+ val_node: BNode | URIRef,
172
+ res_node: BNode | URIRef,
173
+ target_iri: URIRef,
174
+ ) -> Graph:
175
+ """Make a LinkValue Graph"""
176
+ g = _make_base_value_graph(val=val, val_node=val_node, prop_type_info=LINK_PROP_TYPE_INFO, res_node=res_node)
177
+ g.add((val_node, LINK_PROP_TYPE_INFO.knora_prop, target_iri))
178
+ return g
179
+
180
+
181
+ def _resolve_id_to_iri(value: str, iri_resolver: IriResolver) -> URIRef:
182
+ if is_resource_iri(value):
183
+ return URIRef(value)
184
+ elif resolved_iri := iri_resolver.get(value):
185
+ return URIRef(resolved_iri)
186
+ msg = (
187
+ f"Could not find the ID {value} in the id2iri mapping. "
188
+ f"This is probably because the resource '{value}' could not be created. "
189
+ f"See {WARNINGS_SAVEPATH} for more information."
190
+ )
191
+ raise BaseError(msg)
192
+
193
+
194
+ def _make_date_value_graph(
195
+ val: ProcessedDate,
196
+ res_node: BNode | URIRef,
197
+ ) -> Graph:
198
+ val_bn = BNode()
199
+ date = val.value
200
+ g = _add_optional_triples(val_bn, val.permissions, val.comment)
201
+ g.add((res_node, URIRef(val.prop_iri), val_bn))
202
+ g.add((val_bn, RDF.type, KNORA_API.DateValue))
203
+ if cal := date.calendar:
204
+ g.add((val_bn, KNORA_API.dateValueHasCalendar, Literal(cal.value, datatype=XSD.string)))
205
+ g += _make_single_date_graph(val_bn, date.start, StartEnd.START)
206
+ if date.end:
207
+ g += _make_single_date_graph(val_bn, date.end, StartEnd.END)
208
+ return g
209
+
210
+
211
+ def _make_single_date_graph(val_bn: BNode, date: SingleDate, start_end: StartEnd) -> Graph:
212
+ def get_prop(precision: DayMonthYearEra) -> URIRef:
213
+ return KNORA_API[f"dateValueHas{start_end.value}{precision.value}"]
214
+
215
+ g = Graph()
216
+ if yr := date.year:
217
+ g.add((val_bn, get_prop(DayMonthYearEra.YEAR), Literal(yr, datatype=XSD.integer)))
218
+ if mnt := date.month:
219
+ g.add((val_bn, get_prop(DayMonthYearEra.MONTH), Literal(mnt, datatype=XSD.integer)))
220
+ if day := date.day:
221
+ g.add((val_bn, get_prop(DayMonthYearEra.DAY), Literal(day, datatype=XSD.integer)))
222
+ if era := date.era:
223
+ g.add((val_bn, get_prop(DayMonthYearEra.ERA), Literal(era.value, datatype=XSD.string)))
224
+ return g
225
+
226
+
227
+ def _make_interval_value_graph(
228
+ val: ProcessedInterval,
229
+ res_node: BNode | URIRef,
230
+ ) -> Graph:
231
+ val_bn = BNode()
232
+ g = _add_optional_triples(val_bn, val.permissions, val.comment)
233
+ g.add((res_node, URIRef(val.prop_iri), val_bn))
234
+ g.add((val_bn, RDF.type, KNORA_API.IntervalValue))
235
+ g.add((val_bn, KNORA_API.intervalValueHasStart, Literal(val.value.start, datatype=XSD.decimal)))
236
+ g.add((val_bn, KNORA_API.intervalValueHasEnd, Literal(val.value.end, datatype=XSD.decimal)))
237
+ return g
238
+
239
+
240
+ def make_richtext_value_graph(
241
+ val: ProcessedRichtext,
242
+ val_node: BNode | URIRef,
243
+ res_node: BNode | URIRef,
244
+ iri_resolver: IriResolver,
245
+ ) -> Graph:
246
+ """
247
+ Creates an rdflib graph for a richtext value.
248
+
249
+ Args:
250
+ val: Richtext value
251
+ val_node: IRI or blank node of the value
252
+ res_node: IRI or blank node of the resource
253
+ iri_resolver: id to IRI resolver
254
+
255
+ Returns:
256
+ Graph
257
+ """
258
+ g = _make_base_value_graph(val=val, val_node=val_node, prop_type_info=RICHTEXT_PROP_TYPE_INFO, res_node=res_node)
259
+ val_str = prepare_richtext_string_for_upload(val.value.xmlstr, iri_resolver)
260
+ g.add((val_node, RICHTEXT_PROP_TYPE_INFO.knora_prop, Literal(val_str, datatype=XSD.string)))
261
+ g.add((val_node, KNORA_API.textValueHasMapping, URIRef("http://rdfh.ch/standoff/mappings/StandardMapping")))
262
+ return g
@@ -0,0 +1,18 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+
5
+ from dsp_tools.commands.xmlupload.models.permission import Permissions
6
+
7
+
8
+ @dataclass(frozen=True)
9
+ class BitstreamInfo:
10
+ """
11
+ Represents a bitstream object,
12
+ consisting of its file name on the local file system,
13
+ the internal file name assigned by the ingest service
14
+ and optionally its permissions.
15
+ """
16
+
17
+ internal_file_name: str
18
+ permissions: Permissions | None = None
@@ -2,34 +2,9 @@ from __future__ import annotations
2
2
 
3
3
  from dataclasses import dataclass
4
4
 
5
- import regex
6
-
7
- from dsp_tools.commands.xmlupload.iri_resolver import IriResolver
8
- from dsp_tools.models.exceptions import BaseError
9
-
10
5
 
11
6
  @dataclass
12
7
  class FormattedTextValue:
13
8
  """Represents a formatted text value with standard standoff markup"""
14
9
 
15
10
  xmlstr: str
16
-
17
- def as_xml(self) -> str:
18
- """Returns the formatted text value as XML (with XML declaration and wrapped in a <text> element)"""
19
- return f'<?xml version="1.0" encoding="UTF-8"?>\n<text>{self.xmlstr}</text>'
20
-
21
- def find_internal_ids(self) -> set[str]:
22
- """Returns a set of all internal ids found in the text value"""
23
- return set(regex.findall(pattern='href="IRI:(.*?):IRI"', string=self.xmlstr))
24
-
25
- def with_iris(self, iri_resolver: IriResolver) -> FormattedTextValue:
26
- """
27
- Returns a copy of this object, where all internal ids are replaced with iris according to the provided mapping.
28
- """
29
- s = self.xmlstr
30
- for internal_id in self.find_internal_ids():
31
- if iri := iri_resolver.get(internal_id):
32
- s = s.replace(f'href="IRI:{internal_id}:IRI"', f'href="{iri}"')
33
- else:
34
- raise BaseError(f"Internal ID {internal_id} could not be resolved to an IRI")
35
- return FormattedTextValue(s)
@@ -1,6 +1,9 @@
1
+ from __future__ import annotations
2
+
1
3
  import urllib
2
4
  from dataclasses import dataclass
3
5
  from dataclasses import field
6
+ from http import HTTPStatus
4
7
  from pathlib import Path
5
8
  from typing import Protocol
6
9
 
@@ -10,16 +13,15 @@ from requests import Session
10
13
  from requests.adapters import HTTPAdapter
11
14
  from requests.adapters import Retry
12
15
 
13
- from dsp_tools.commands.xmlupload.models.deserialise.deserialise_value import XMLBitstream
14
- from dsp_tools.commands.xmlupload.models.deserialise.xmlresource import BitstreamInfo
15
- from dsp_tools.commands.xmlupload.models.permission import Permissions
16
- from dsp_tools.models.exceptions import BadCredentialsError
17
- from dsp_tools.models.exceptions import PermanentConnectionError
18
- from dsp_tools.utils.logger_config import WARNINGS_SAVEPATH
19
-
20
- STATUS_OK = 200
21
- STATUS_UNAUTHORIZED = 401
22
- STATUS_INTERNAL_SERVER_ERROR = 500
16
+ from dsp_tools.clients.authentication_client import AuthenticationClient
17
+ from dsp_tools.commands.xmlupload.models.bitstream_info import BitstreamInfo
18
+ from dsp_tools.commands.xmlupload.models.processed.file_values import ProcessedFileValue
19
+ from dsp_tools.error.exceptions import BadCredentialsError
20
+ from dsp_tools.error.exceptions import InvalidIngestFileNameError
21
+ from dsp_tools.error.exceptions import PermanentConnectionError
22
+ from dsp_tools.utils.request_utils import RequestParameters
23
+ from dsp_tools.utils.request_utils import log_request
24
+ from dsp_tools.utils.request_utils import log_response
23
25
 
24
26
 
25
27
  @dataclass(frozen=True)
@@ -32,20 +34,11 @@ class IngestResponse:
32
34
  class AssetClient(Protocol):
33
35
  """Protocol for asset handling clients."""
34
36
 
35
- def get_bitstream_info(
36
- self,
37
- bitstream: XMLBitstream,
38
- permissions_lookup: dict[str, Permissions],
39
- res_label: str,
40
- res_id: str,
41
- ) -> tuple[bool, None | BitstreamInfo]:
42
- """Uploads the file to the ingest server if applicable, and returns the BitstreamInfo.
37
+ def get_bitstream_info(self, file_info: ProcessedFileValue) -> BitstreamInfo | None:
38
+ """Uploads the file to the ingest server if applicable, and returns the upload results.
43
39
 
44
40
  Args:
45
- bitstream: The bitstream to upload.
46
- permissions_lookup: The permissions lookup.
47
- res_label: The resource label (for error message in failure case).
48
- res_id: The resource ID (for error message in failure case).
41
+ file_info: Information required for ingesting an asset
49
42
  """
50
43
 
51
44
 
@@ -54,7 +47,7 @@ class DspIngestClientLive(AssetClient):
54
47
  """Client for uploading assets to the DSP-Ingest."""
55
48
 
56
49
  dsp_ingest_url: str
57
- token: str
50
+ authentication_client: AuthenticationClient
58
51
  shortcode: str
59
52
  imgdir: str
60
53
  session: Session = field(init=False)
@@ -68,7 +61,7 @@ class DspIngestClientLive(AssetClient):
68
61
  connect=retries,
69
62
  backoff_factor=0.3,
70
63
  allowed_methods=None, # means all methods
71
- status_forcelist=[STATUS_INTERNAL_SERVER_ERROR],
64
+ status_forcelist=[HTTPStatus.INTERNAL_SERVER_ERROR.value],
72
65
  )
73
66
  adapter = HTTPAdapter(max_retries=retry)
74
67
  self.session.mount("http://", adapter)
@@ -83,6 +76,10 @@ class DspIngestClientLive(AssetClient):
83
76
  After all retry attempts are exhausted it will raise exceptions if the upload failed.
84
77
  The http status code is also checked and if it is not 200, a PermanentConnectionError is raised.
85
78
 
79
+ The load balancer on DSP servers currently has a timeout of 10m,
80
+ so we need to use a slightly shorter timeout of 9m.
81
+ See https://linear.app/dasch/issue/INFRA-847/increase-traefik-readtimeout
82
+
86
83
  Args:
87
84
  filepath: Path to the file to ingest, could be either absolute or relative.
88
85
 
@@ -95,63 +92,52 @@ class DspIngestClientLive(AssetClient):
95
92
  """
96
93
  filename = urllib.parse.quote(filepath.name)
97
94
  url = f"{self.dsp_ingest_url}/projects/{self.shortcode}/assets/ingest/{filename}"
98
- headers = {"Authorization": f"Bearer {self.token}", "Content-Type": "application/octet-stream"}
99
- timeout = 600
100
- err = f"Failed to ingest {filepath} to '{url}'."
95
+ headers = {
96
+ "Authorization": f"Bearer {self.authentication_client.get_token()}",
97
+ "Content-Type": "application/octet-stream",
98
+ }
99
+ timeout = 9 * 60
100
+ params = RequestParameters(method="POST", url=url, timeout=timeout, headers=headers)
101
101
  with open(filepath, "rb") as binary_io:
102
102
  try:
103
- logger.debug(f"REQUEST: POST to {url}, timeout: {timeout}, headers: {headers | {"Authorization": "*"}}")
103
+ log_request(params)
104
104
  res = self.session.post(
105
- url=url,
106
- headers=headers,
105
+ url=params.url,
106
+ headers=params.headers,
107
107
  data=binary_io,
108
- timeout=timeout,
108
+ timeout=params.timeout,
109
109
  )
110
- logger.debug(f"RESPONSE: {res.status_code}: {res.text}")
111
- if res.status_code == STATUS_OK:
112
- return IngestResponse(internal_filename=res.json()["internalFilename"])
113
- elif res.status_code == STATUS_UNAUTHORIZED:
114
- raise BadCredentialsError("Bad credentials")
115
- else:
116
- user_msg = f"{err} See {WARNINGS_SAVEPATH} for more information."
117
- print(user_msg)
118
- log_msg = f"{err}. Response status code {res.status_code} '{res.text}'"
119
- logger.error(log_msg)
120
- raise PermanentConnectionError(log_msg)
110
+ log_response(res)
121
111
  except requests.exceptions.RequestException as e:
122
- raise PermanentConnectionError(f"{err}. {e}") from e
123
-
124
- def get_bitstream_info(
125
- self,
126
- bitstream: XMLBitstream,
127
- permissions_lookup: dict[str, Permissions],
128
- res_label: str,
129
- res_id: str,
130
- ) -> tuple[bool, None | BitstreamInfo]:
131
- """Uploads a file to the ingest server and returns the BitstreamInfo."""
112
+ raise PermanentConnectionError() from e
113
+
114
+ if res.ok:
115
+ return IngestResponse(internal_filename=res.json()["internalFilename"])
116
+ elif res.status_code == HTTPStatus.FORBIDDEN:
117
+ raise BadCredentialsError("Only SystemAdmins and ProjectAdmins can upload assets.")
118
+ elif res.status_code == HTTPStatus.BAD_REQUEST and res.text == "Invalid value for: path parameter filename":
119
+ raise InvalidIngestFileNameError()
120
+ else:
121
+ raise PermanentConnectionError()
122
+
123
+ def get_bitstream_info(self, file_info: ProcessedFileValue) -> BitstreamInfo | None:
124
+ """Uploads a file to the ingest server and returns the upload results."""
132
125
  try:
133
- res = self._ingest(Path(self.imgdir) / Path(bitstream.value))
134
- msg = f"Uploaded file '{bitstream.value}'"
135
- logger.info(msg)
136
- permissions = permissions_lookup.get(bitstream.permissions) if bitstream.permissions else None
137
- return True, BitstreamInfo(bitstream.value, res.internal_filename, permissions)
126
+ res = self._ingest(Path(self.imgdir) / Path(file_info.value))
127
+ logger.info(f"Uploaded file '{file_info.value}'")
128
+ return BitstreamInfo(res.internal_filename, file_info.metadata.permissions)
129
+ except InvalidIngestFileNameError:
130
+ msg = f"Invalid filename: Unable to upload file '{file_info.value}' of resource '{file_info.res_id}'"
138
131
  except PermanentConnectionError:
139
- msg = f"Unable to upload file '{bitstream.value}' of resource '{res_label}' ({res_id})"
140
- logger.opt(exception=True).warning(msg)
141
- return False, None
132
+ msg = f"Unable to upload file '{file_info.value}' of resource '{file_info.res_id}'"
133
+ logger.error(msg)
134
+ return None
142
135
 
143
136
 
144
137
  @dataclass(frozen=True)
145
138
  class BulkIngestedAssetClient(AssetClient):
146
139
  """Client for handling media info, if the assets were bulk ingested previously."""
147
140
 
148
- def get_bitstream_info(
149
- self,
150
- bitstream: XMLBitstream,
151
- permissions_lookup: dict[str, Permissions],
152
- res_label: str, # noqa: ARG002
153
- res_id: str, # noqa: ARG002
154
- ) -> tuple[bool, BitstreamInfo | None]:
155
- """Returns the BitstreamInfo of the already ingested file based on the `XMLBitstream.value`."""
156
- permissions = permissions_lookup.get(bitstream.permissions) if bitstream.permissions else None
157
- return True, BitstreamInfo(bitstream.value, bitstream.value, permissions)
141
+ def get_bitstream_info(self, file_info: ProcessedFileValue) -> BitstreamInfo:
142
+ """Returns the BitstreamInfo of the already ingested file based on the `ProcessedFileValue.value`."""
143
+ return BitstreamInfo(file_info.value, file_info.metadata.permissions)
@@ -29,7 +29,6 @@ class IIIFUriProblem:
29
29
  regex_has_passed: bool
30
30
  status_code: int | None = None
31
31
  raised_exception_name: str | None = None
32
- original_text: str | None = None
33
32
 
34
33
  def get_msg(self) -> str:
35
34
  """Get a message describing the problem with the IIIF URI."""
@@ -43,24 +42,17 @@ class IIIFUriProblem:
43
42
  elif self.status_code is not None:
44
43
  msg.extend(self._bad_status_code_msg())
45
44
  else:
46
- msg.extend(self._exception_msg())
45
+ msg.append(self._exception_msg())
47
46
  return list_separator.join(msg)
48
47
 
49
- def _exception_msg(self) -> list[str]:
50
- return [
51
- f"An error occurred during the network call: {self.raised_exception_name}",
52
- f"Error message: {self.original_text}",
53
- ]
48
+ def _exception_msg(self) -> str:
49
+ return f"An error occurred during the network call: {self.raised_exception_name}"
54
50
 
55
51
  def _bad_status_code_msg(self) -> list[str]:
56
- return [
57
- "The server did not respond as expected.",
58
- f"Status code: {self.status_code}",
59
- f"Response text: {self.original_text}",
60
- ]
52
+ return ["The server did not respond as expected.", f"Status code: {self.status_code}"]
61
53
 
62
54
  def _good_status_code_bad_regex_msg(self) -> list[str]:
63
55
  return [
64
- "The URI is correct and the server responded as expected.",
65
- "Please contact the dsp-tools development team with this information.",
56
+ "Although the IIIF-server responded as expected, this URI did not pass validation.",
57
+ "Please contact the dsp-tools development team (at support@dasch.swiss) with this information.",
66
58
  ]
@@ -0,0 +1,21 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+
5
+ from rdflib import URIRef
6
+
7
+ from dsp_tools.commands.xmlupload.iri_resolver import IriResolver
8
+ from dsp_tools.commands.xmlupload.models.permission import Permissions
9
+
10
+
11
+ @dataclass
12
+ class XmlReferenceLookups:
13
+ permissions: dict[str, Permissions]
14
+ listnodes: dict[tuple[str, str], str]
15
+ authorships: dict[str, list[str]]
16
+
17
+
18
+ @dataclass
19
+ class IRILookups:
20
+ project_iri: URIRef
21
+ id_to_iri: IriResolver
@@ -3,9 +3,6 @@ from __future__ import annotations
3
3
  from enum import Enum
4
4
  from enum import unique
5
5
  from typing import Optional
6
- from typing import Union
7
-
8
- import regex
9
6
 
10
7
 
11
8
  @unique
@@ -33,21 +30,6 @@ class Permissions:
33
30
  def __init__(self, permissions: Optional[dict[PermissionValue, list[str]]] = None):
34
31
  self._permissions = permissions or {}
35
32
 
36
- def __getitem__(self, key: PermissionValue) -> Union[list[str], None]:
37
- return self._permissions.get(key)
38
-
39
- def __setitem__(self, key: PermissionValue, value: list[str]) -> None:
40
- self._permissions[key] = value
41
-
42
- def __delitem__(self, key: PermissionValue) -> None:
43
- del self._permissions[key]
44
-
45
- def __missing__(self, key: PermissionValue) -> None:
46
- return None
47
-
48
- def __contains__(self, key: PermissionValue) -> bool:
49
- return key in self._permissions
50
-
51
33
  def __str__(self) -> str:
52
34
  tmpstr = ""
53
35
  for permission, groups in self._permissions.items():
@@ -61,24 +43,3 @@ class Permissions:
61
43
  self._permissions[key] = [val]
62
44
  else:
63
45
  self._permissions[key].append(val)
64
-
65
- def toJsonLdObj(self) -> str:
66
- tmpstr = ""
67
- for permission, groups in self._permissions.items():
68
- if tmpstr:
69
- tmpstr += "|"
70
- tmpstr += f"{permission!s} " + ",".join(groups)
71
- return tmpstr
72
-
73
- @classmethod
74
- def fromString(cls, permstr: str) -> Permissions:
75
- tmpstr = permstr.split("|")
76
- permissions: dict[PermissionValue, list[str]] = {}
77
- for s in tmpstr:
78
- key, *vals = regex.split("[\\s,]+", s)
79
- permissions[PermissionValue[key]] = vals
80
- return cls(permissions)
81
-
82
- @property
83
- def permissions(self) -> Union[dict[PermissionValue, list[str]], None]:
84
- return self._permissions
@@ -4,8 +4,8 @@ from lxml import etree
4
4
 
5
5
  from dsp_tools.commands.xmlupload.models.permission import Permissions
6
6
  from dsp_tools.commands.xmlupload.models.permission import PermissionValue
7
- from dsp_tools.models.exceptions import XmlUploadError
8
- from dsp_tools.models.projectContext import ProjectContext
7
+ from dsp_tools.error.exceptions import XmlUploadError
8
+ from dsp_tools.legacy_models.projectContext import ProjectContext
9
9
 
10
10
 
11
11
  class XmlPermission:
@@ -0,0 +1,29 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+
5
+ from dsp_tools.commands.xmlupload.models.permission import Permissions
6
+ from dsp_tools.utils.xml_parsing.models.parsed_resource import KnoraValueType
7
+
8
+
9
+ @dataclass
10
+ class ProcessedFileMetadata:
11
+ license_iri: str
12
+ copyright_holder: str
13
+ authorships: list[str]
14
+ permissions: Permissions | None = None
15
+
16
+
17
+ @dataclass
18
+ class ProcessedFileValue:
19
+ value: str
20
+ file_type: KnoraValueType
21
+ metadata: ProcessedFileMetadata
22
+ res_id: str
23
+ res_label: str
24
+
25
+
26
+ @dataclass
27
+ class ProcessedIIIFUri:
28
+ value: str
29
+ metadata: ProcessedFileMetadata