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,27 @@
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.commands.xmlupload.models.processed.file_values import ProcessedFileValue
7
+ from dsp_tools.commands.xmlupload.models.processed.file_values import ProcessedIIIFUri
8
+ from dsp_tools.commands.xmlupload.models.processed.values import ProcessedValue
9
+ from dsp_tools.legacy_models.datetimestamp import DateTimeStamp
10
+
11
+
12
+ @dataclass
13
+ class ProcessedResource:
14
+ res_id: str
15
+ type_iri: str
16
+ label: str
17
+ permissions: Permissions | None
18
+ values: list[ProcessedValue]
19
+ file_value: ProcessedFileValue | None = None
20
+ iiif_uri: ProcessedIIIFUri | None = None
21
+ migration_metadata: MigrationMetadata | None = None
22
+
23
+
24
+ @dataclass
25
+ class MigrationMetadata:
26
+ iri_str: str | None
27
+ creation_date: DateTimeStamp | None
@@ -0,0 +1,101 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from typing import Union
5
+
6
+ from dsp_tools.commands.xmlupload.models.formatted_text_value import FormattedTextValue
7
+ from dsp_tools.commands.xmlupload.models.permission import Permissions
8
+ from dsp_tools.utils.data_formats.date_util import Date
9
+
10
+
11
+ @dataclass
12
+ class IntervalFloats:
13
+ start: float
14
+ end: float
15
+
16
+
17
+ type ProcessedValueTypes = Union[bool, str, float, int, FormattedTextValue, Date, IntervalFloats]
18
+
19
+
20
+ @dataclass
21
+ class ProcessedValue:
22
+ value: ProcessedValueTypes
23
+ prop_iri: str
24
+ comment: str | None
25
+ permissions: Permissions | None
26
+
27
+
28
+ @dataclass
29
+ class ProcessedBoolean(ProcessedValue):
30
+ value: bool
31
+
32
+
33
+ @dataclass
34
+ class ProcessedColor(ProcessedValue):
35
+ value: str
36
+
37
+
38
+ @dataclass
39
+ class ProcessedDate(ProcessedValue):
40
+ value: Date
41
+
42
+
43
+ @dataclass
44
+ class ProcessedDecimal(ProcessedValue):
45
+ value: float
46
+
47
+
48
+ @dataclass
49
+ class ProcessedGeoname(ProcessedValue):
50
+ value: str
51
+
52
+
53
+ @dataclass
54
+ class ProcessedGeometry(ProcessedValue):
55
+ value: str
56
+
57
+
58
+ @dataclass
59
+ class ProcessedInt(ProcessedValue):
60
+ value: int
61
+
62
+
63
+ @dataclass
64
+ class ProcessedInterval(ProcessedValue):
65
+ value: IntervalFloats
66
+
67
+
68
+ @dataclass
69
+ class ProcessedLink(ProcessedValue):
70
+ value: str
71
+ value_uuid: str
72
+
73
+ def __post_init__(self) -> None:
74
+ self.prop_iri = f"{self.prop_iri}Value"
75
+
76
+
77
+ @dataclass
78
+ class ProcessedList(ProcessedValue):
79
+ value: str
80
+
81
+
82
+ @dataclass
83
+ class ProcessedSimpleText(ProcessedValue):
84
+ value: str
85
+
86
+
87
+ @dataclass
88
+ class ProcessedRichtext(ProcessedValue):
89
+ value: FormattedTextValue
90
+ resource_references: set[str]
91
+ value_uuid: str
92
+
93
+
94
+ @dataclass
95
+ class ProcessedTime(ProcessedValue):
96
+ value: str
97
+
98
+
99
+ @dataclass
100
+ class ProcessedUri(ProcessedValue):
101
+ value: str
@@ -0,0 +1,26 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+
5
+ from rdflib import URIRef
6
+
7
+
8
+ @dataclass
9
+ class RDFPropTypeInfo:
10
+ knora_type: URIRef
11
+ knora_prop: URIRef
12
+ xsd_type: URIRef | None = None
13
+
14
+
15
+ @dataclass
16
+ class AbstractFileValue:
17
+ value: str
18
+ metadata: FileValueMetadata
19
+
20
+
21
+ @dataclass
22
+ class FileValueMetadata:
23
+ license_iri: str
24
+ copyright_holder: str
25
+ authorships: list[str]
26
+ permissions: str | None
@@ -1,8 +1,8 @@
1
1
  from dataclasses import dataclass
2
2
 
3
- from dsp_tools.commands.xmlupload.list_client import ListClient
3
+ from dsp_tools.clients.legal_info_client import LegalInfoClient
4
4
  from dsp_tools.commands.xmlupload.models.ingest import AssetClient
5
- from dsp_tools.commands.xmlupload.project_client import ProjectClient
5
+ from dsp_tools.commands.xmlupload.prepare_xml_input.list_client import ListClient
6
6
 
7
7
 
8
8
  @dataclass(frozen=True)
@@ -10,5 +10,5 @@ class UploadClients:
10
10
  """Holds all the clients needed for the upload process."""
11
11
 
12
12
  asset_client: AssetClient
13
- project_client: ProjectClient
14
13
  list_client: ListClient
14
+ legal_info_client: LegalInfoClient
@@ -2,8 +2,7 @@ from dataclasses import dataclass
2
2
  from dataclasses import field
3
3
 
4
4
  from dsp_tools.commands.xmlupload.iri_resolver import IriResolver
5
- from dsp_tools.commands.xmlupload.models.deserialise.xmlresource import XMLResource
6
- from dsp_tools.commands.xmlupload.models.permission import Permissions
5
+ from dsp_tools.commands.xmlupload.models.processed.res import ProcessedResource
7
6
  from dsp_tools.commands.xmlupload.stash.stash_models import Stash
8
7
  from dsp_tools.commands.xmlupload.upload_config import UploadConfig
9
8
 
@@ -14,9 +13,8 @@ class UploadState:
14
13
  Save the state of an xmlupload, so that after an interruption, it can be resumed.
15
14
  """
16
15
 
17
- pending_resources: list[XMLResource]
16
+ pending_resources: list[ProcessedResource]
18
17
  pending_stash: Stash | None
19
18
  config: UploadConfig
20
- permissions_lookup: dict[str, Permissions]
21
19
  failed_uploads: list[str] = field(default_factory=list)
22
20
  iri_resolver: IriResolver = field(default_factory=IriResolver)
@@ -5,7 +5,7 @@ import uuid
5
5
 
6
6
  import regex
7
7
 
8
- from dsp_tools.models.exceptions import BaseError
8
+ from dsp_tools.error.exceptions import BaseError
9
9
 
10
10
 
11
11
  def convert_ark_v0_to_resource_iri(ark: str) -> str:
@@ -0,0 +1,252 @@
1
+ from typing import cast
2
+ from uuid import uuid4
3
+
4
+ from loguru import logger
5
+ from tqdm import tqdm
6
+
7
+ from dsp_tools.commands.xmlupload.models.lookup_models import XmlReferenceLookups
8
+ from dsp_tools.commands.xmlupload.models.permission import Permissions
9
+ from dsp_tools.commands.xmlupload.models.processed.file_values import ProcessedFileMetadata
10
+ from dsp_tools.commands.xmlupload.models.processed.file_values import ProcessedFileValue
11
+ from dsp_tools.commands.xmlupload.models.processed.file_values import ProcessedIIIFUri
12
+ from dsp_tools.commands.xmlupload.models.processed.res import MigrationMetadata
13
+ from dsp_tools.commands.xmlupload.models.processed.res import ProcessedResource
14
+ from dsp_tools.commands.xmlupload.models.processed.values import ProcessedBoolean
15
+ from dsp_tools.commands.xmlupload.models.processed.values import ProcessedColor
16
+ from dsp_tools.commands.xmlupload.models.processed.values import ProcessedDate
17
+ from dsp_tools.commands.xmlupload.models.processed.values import ProcessedDecimal
18
+ from dsp_tools.commands.xmlupload.models.processed.values import ProcessedGeometry
19
+ from dsp_tools.commands.xmlupload.models.processed.values import ProcessedGeoname
20
+ from dsp_tools.commands.xmlupload.models.processed.values import ProcessedInt
21
+ from dsp_tools.commands.xmlupload.models.processed.values import ProcessedInterval
22
+ from dsp_tools.commands.xmlupload.models.processed.values import ProcessedLink
23
+ from dsp_tools.commands.xmlupload.models.processed.values import ProcessedList
24
+ from dsp_tools.commands.xmlupload.models.processed.values import ProcessedRichtext
25
+ from dsp_tools.commands.xmlupload.models.processed.values import ProcessedSimpleText
26
+ from dsp_tools.commands.xmlupload.models.processed.values import ProcessedTime
27
+ from dsp_tools.commands.xmlupload.models.processed.values import ProcessedUri
28
+ from dsp_tools.commands.xmlupload.models.processed.values import ProcessedValue
29
+ from dsp_tools.commands.xmlupload.prepare_xml_input.ark2iri import convert_ark_v0_to_resource_iri
30
+ from dsp_tools.commands.xmlupload.prepare_xml_input.transform_input_values import TypeTransformerMapper
31
+ from dsp_tools.commands.xmlupload.prepare_xml_input.transform_input_values import assert_is_string
32
+ from dsp_tools.commands.xmlupload.prepare_xml_input.transform_input_values import assert_is_tuple
33
+ from dsp_tools.commands.xmlupload.prepare_xml_input.transform_input_values import transform_boolean
34
+ from dsp_tools.commands.xmlupload.prepare_xml_input.transform_input_values import transform_date
35
+ from dsp_tools.commands.xmlupload.prepare_xml_input.transform_input_values import transform_decimal
36
+ from dsp_tools.commands.xmlupload.prepare_xml_input.transform_input_values import transform_geometry
37
+ from dsp_tools.commands.xmlupload.prepare_xml_input.transform_input_values import transform_integer
38
+ from dsp_tools.commands.xmlupload.prepare_xml_input.transform_input_values import transform_interval
39
+ from dsp_tools.commands.xmlupload.prepare_xml_input.transform_input_values import transform_richtext
40
+ from dsp_tools.commands.xmlupload.prepare_xml_input.transform_input_values import transform_simpletext
41
+ from dsp_tools.commands.xmlupload.richtext_id2iri import find_internal_ids
42
+ from dsp_tools.error.exceptions import XmlUploadAuthorshipsNotFoundError
43
+ from dsp_tools.error.exceptions import XmlUploadListNodeNotFoundError
44
+ from dsp_tools.error.exceptions import XmlUploadPermissionsNotFoundError
45
+ from dsp_tools.legacy_models.datetimestamp import DateTimeStamp
46
+ from dsp_tools.utils.xml_parsing.models.parsed_resource import KnoraValueType
47
+ from dsp_tools.utils.xml_parsing.models.parsed_resource import ParsedFileValue
48
+ from dsp_tools.utils.xml_parsing.models.parsed_resource import ParsedFileValueMetadata
49
+ from dsp_tools.utils.xml_parsing.models.parsed_resource import ParsedMigrationMetadata
50
+ from dsp_tools.utils.xml_parsing.models.parsed_resource import ParsedResource
51
+ from dsp_tools.utils.xml_parsing.models.parsed_resource import ParsedValue
52
+
53
+ TYPE_TRANSFORMER_MAPPER: dict[KnoraValueType, TypeTransformerMapper] = {
54
+ KnoraValueType.BOOLEAN_VALUE: TypeTransformerMapper(ProcessedBoolean, transform_boolean),
55
+ KnoraValueType.COLOR_VALUE: TypeTransformerMapper(ProcessedColor, assert_is_string),
56
+ KnoraValueType.DECIMAL_VALUE: TypeTransformerMapper(ProcessedDecimal, transform_decimal),
57
+ KnoraValueType.DATE_VALUE: TypeTransformerMapper(ProcessedDate, transform_date),
58
+ KnoraValueType.GEOM_VALUE: TypeTransformerMapper(ProcessedGeometry, transform_geometry),
59
+ KnoraValueType.GEONAME_VALUE: TypeTransformerMapper(ProcessedGeoname, assert_is_string),
60
+ KnoraValueType.INT_VALUE: TypeTransformerMapper(ProcessedInt, transform_integer),
61
+ KnoraValueType.INTERVAL_VALUE: TypeTransformerMapper(ProcessedInterval, transform_interval),
62
+ KnoraValueType.TIME_VALUE: TypeTransformerMapper(ProcessedTime, assert_is_string),
63
+ KnoraValueType.SIMPLETEXT_VALUE: TypeTransformerMapper(ProcessedSimpleText, transform_simpletext),
64
+ KnoraValueType.URI_VALUE: TypeTransformerMapper(ProcessedUri, assert_is_string),
65
+ }
66
+
67
+
68
+ def get_processed_resources(
69
+ resources: list[ParsedResource], lookups: XmlReferenceLookups, is_on_prod_like_server: bool
70
+ ) -> list[ProcessedResource]:
71
+ logger.debug("Transform ParsedResource into ProcessedResource")
72
+ progress_bar = tqdm(resources, desc="Preparing data for upload", dynamic_ncols=True)
73
+ return [_get_one_resource(res, lookups, is_on_prod_like_server) for res in progress_bar]
74
+
75
+
76
+ def _get_one_resource(
77
+ resource: ParsedResource, lookups: XmlReferenceLookups, is_on_prod_like_server: bool
78
+ ) -> ProcessedResource:
79
+ permissions = _resolve_permission(resource.permissions_id, lookups.permissions)
80
+ values = [_get_one_processed_value(val, lookups) for val in resource.values]
81
+ migration_metadata = None
82
+ file_val, iiif_uri = _resolve_file_value(resource, lookups, is_on_prod_like_server)
83
+ if resource.migration_metadata:
84
+ migration_metadata = _get_resource_migration_metadata(resource.migration_metadata)
85
+ return ProcessedResource(
86
+ res_id=resource.res_id,
87
+ type_iri=resource.res_type,
88
+ label=resource.label,
89
+ permissions=permissions,
90
+ values=values,
91
+ file_value=file_val,
92
+ iiif_uri=iiif_uri,
93
+ migration_metadata=migration_metadata,
94
+ )
95
+
96
+
97
+ def _get_resource_migration_metadata(metadata: ParsedMigrationMetadata) -> MigrationMetadata:
98
+ res_iri = metadata.iri
99
+ # ARK takes precedence over the IRI,
100
+ # but must be transformed into an IRI as it is only for external reference and not consistent with a DB IRI
101
+ if metadata.ark:
102
+ res_iri = convert_ark_v0_to_resource_iri(metadata.ark)
103
+ date = DateTimeStamp(metadata.creation_date) if metadata.creation_date else None
104
+ return MigrationMetadata(res_iri, date)
105
+
106
+
107
+ def _resolve_file_value(
108
+ resource: ParsedResource, lookups: XmlReferenceLookups, is_on_prod_like_server: bool
109
+ ) -> tuple[None | ProcessedFileValue, None | ProcessedIIIFUri]:
110
+ file_val, iiif_uri = None, None
111
+ if not resource.file_value:
112
+ return file_val, iiif_uri
113
+
114
+ if is_on_prod_like_server:
115
+ metadata = _get_file_metadata(resource.file_value.metadata, lookups)
116
+ else:
117
+ metadata = _get_file_metadata_for_test_environments(resource.file_value.metadata, lookups)
118
+ if resource.file_value.value_type == KnoraValueType.STILL_IMAGE_IIIF:
119
+ iiif_uri = _get_iiif_uri_value(resource.file_value, metadata)
120
+ else:
121
+ file_val = _get_file_value(
122
+ val=resource.file_value, metadata=metadata, res_id=resource.res_id, res_label=resource.label
123
+ )
124
+ return file_val, iiif_uri
125
+
126
+
127
+ def _get_file_value(
128
+ val: ParsedFileValue, metadata: ProcessedFileMetadata, res_id: str, res_label: str
129
+ ) -> ProcessedFileValue:
130
+ file_type = cast(KnoraValueType, val.value_type)
131
+ file_val = assert_is_string(val.value)
132
+ return ProcessedFileValue(
133
+ value=file_val,
134
+ file_type=file_type,
135
+ metadata=metadata,
136
+ res_id=res_id,
137
+ res_label=res_label,
138
+ )
139
+
140
+
141
+ def _get_iiif_uri_value(iiif_uri: ParsedFileValue, metadata: ProcessedFileMetadata) -> ProcessedIIIFUri:
142
+ file_val = assert_is_string(iiif_uri.value)
143
+ return ProcessedIIIFUri(file_val, metadata)
144
+
145
+
146
+ def _get_file_metadata(file_metadata: ParsedFileValueMetadata, lookups: XmlReferenceLookups) -> ProcessedFileMetadata:
147
+ license_iri = assert_is_string(file_metadata.license_iri)
148
+ copyright_holder = assert_is_string(file_metadata.copyright_holder)
149
+ auth_id = assert_is_string(file_metadata.authorship_id)
150
+ authorships = _resolve_authorship(auth_id, lookups.authorships)
151
+ permissions = _resolve_permission(file_metadata.permissions_id, lookups.permissions)
152
+ return ProcessedFileMetadata(
153
+ license_iri=license_iri,
154
+ copyright_holder=copyright_holder,
155
+ authorships=authorships,
156
+ permissions=permissions,
157
+ )
158
+
159
+
160
+ def _get_file_metadata_for_test_environments(
161
+ metadata: ParsedFileValueMetadata, lookups: XmlReferenceLookups
162
+ ) -> ProcessedFileMetadata:
163
+ lic_iri = metadata.license_iri or "http://rdfh.ch/licenses/unknown"
164
+ copy_right = metadata.copyright_holder if metadata.copyright_holder else "DUMMY"
165
+ if not metadata.authorship_id:
166
+ authorship = ["DUMMY"]
167
+ else:
168
+ authorship = _resolve_authorship(metadata.authorship_id, lookups.authorships)
169
+ permissions = _resolve_permission(metadata.permissions_id, lookups.permissions)
170
+ return ProcessedFileMetadata(
171
+ license_iri=lic_iri,
172
+ copyright_holder=copy_right,
173
+ authorships=authorship,
174
+ permissions=permissions,
175
+ )
176
+
177
+
178
+ def _resolve_authorship(authorship_id: str, lookup: dict[str, list[str]]) -> list[str]:
179
+ if not (found := lookup.get(authorship_id)):
180
+ raise XmlUploadAuthorshipsNotFoundError(f"Could not find authorships for value: {authorship_id}")
181
+ return found
182
+
183
+
184
+ def _get_one_processed_value(val: ParsedValue, lookups: XmlReferenceLookups) -> ProcessedValue:
185
+ match val.value_type:
186
+ case KnoraValueType.LIST_VALUE:
187
+ return _get_list_value(val, lookups)
188
+ case KnoraValueType.LINK_VALUE:
189
+ return _get_link_value(val, lookups)
190
+ case KnoraValueType.RICHTEXT_VALUE:
191
+ return _get_richtext_value(val, lookups)
192
+ case _ as val_type:
193
+ transformation_mapper = TYPE_TRANSFORMER_MAPPER[val_type]
194
+ return _get_generic_value(val=val, lookups=lookups, transformation_mapper=transformation_mapper)
195
+
196
+
197
+ def _get_generic_value(
198
+ val: ParsedValue, lookups: XmlReferenceLookups, transformation_mapper: TypeTransformerMapper
199
+ ) -> ProcessedValue:
200
+ transformed_value = transformation_mapper.val_transformer(val.value)
201
+ permission_val = _resolve_permission(val.permissions_id, lookups.permissions)
202
+ return transformation_mapper.val_type(transformed_value, val.prop_name, val.comment, permission_val)
203
+
204
+
205
+ def _get_link_value(val: ParsedValue, lookups: XmlReferenceLookups) -> ProcessedValue:
206
+ transformed_value = assert_is_string(val.value)
207
+ permission_val = _resolve_permission(val.permissions_id, lookups.permissions)
208
+ link_val: ProcessedValue = ProcessedLink(
209
+ value=transformed_value,
210
+ prop_iri=val.prop_name,
211
+ comment=val.comment,
212
+ permissions=permission_val,
213
+ value_uuid=str(uuid4()),
214
+ )
215
+ return link_val
216
+
217
+
218
+ def _get_list_value(val: ParsedValue, lookups: XmlReferenceLookups) -> ProcessedValue:
219
+ tuple_val = assert_is_tuple(val.value)
220
+ if not (list_iri := lookups.listnodes.get(tuple_val)):
221
+ raise XmlUploadListNodeNotFoundError(f"Could not find list IRI for value: {tuple_val}")
222
+ permission_val = _resolve_permission(val.permissions_id, lookups.permissions)
223
+ list_val: ProcessedValue = ProcessedList(
224
+ value=list_iri,
225
+ prop_iri=val.prop_name,
226
+ comment=val.comment,
227
+ permissions=permission_val,
228
+ )
229
+ return list_val
230
+
231
+
232
+ def _get_richtext_value(val: ParsedValue, lookups: XmlReferenceLookups) -> ProcessedValue:
233
+ transformed_value = transform_richtext(val.value)
234
+ permission_val = _resolve_permission(val.permissions_id, lookups.permissions)
235
+ richtext: ProcessedValue = ProcessedRichtext(
236
+ value=transformed_value,
237
+ prop_iri=val.prop_name,
238
+ comment=val.comment,
239
+ permissions=permission_val,
240
+ resource_references=find_internal_ids(transformed_value.xmlstr),
241
+ value_uuid=str(uuid4()),
242
+ )
243
+ return richtext
244
+
245
+
246
+ def _resolve_permission(permissions: str | None, permissions_lookup: dict[str, Permissions]) -> Permissions | None:
247
+ """Resolve the permission into a string that can be sent to the API."""
248
+ if permissions:
249
+ if not (per := permissions_lookup.get(permissions)):
250
+ raise XmlUploadPermissionsNotFoundError(f"Could not find permissions for value: {permissions}")
251
+ return per
252
+ return None
@@ -2,25 +2,15 @@ from dataclasses import dataclass
2
2
 
3
3
  import requests
4
4
 
5
- from dsp_tools.commands.xmlupload.models.input_problems import AllIIIFUriProblems
6
5
  from dsp_tools.commands.xmlupload.models.input_problems import IIIFUriProblem
7
- from dsp_tools.utils.uri_util import is_iiif_uri
6
+ from dsp_tools.utils.data_formats.uri_util import is_iiif_uri
8
7
 
9
8
 
10
9
  @dataclass(frozen=True)
11
10
  class IIIFUriValidator:
12
11
  """Client handling communication with external IIIF-servers to do a health check."""
13
12
 
14
- uri_list: list[str]
15
-
16
- def validate(self) -> AllIIIFUriProblems | None:
17
- """Validate the URI and return a list of problems if any."""
18
- iiif_uri_problems = [res for uri in self.uri_list if (res := self._validate_one_uri(uri)) is not None]
19
- if iiif_uri_problems:
20
- return AllIIIFUriProblems(problems=iiif_uri_problems)
21
- return None
22
-
23
- def _validate_one_uri(self, uri: str) -> IIIFUriProblem | None:
13
+ def validate_one_uri(self, uri: str) -> IIIFUriProblem | None:
24
14
  """Check if the IIIF-server is reachable. If not, it returns information for error message."""
25
15
  regex_has_passed = is_iiif_uri(uri)
26
16
  response = self._make_network_call(uri)
@@ -29,7 +19,6 @@ class IIIFUriValidator:
29
19
  uri=uri,
30
20
  regex_has_passed=regex_has_passed,
31
21
  raised_exception_name=response.__class__.__name__,
32
- original_text=str(response),
33
22
  )
34
23
  match response.ok, regex_has_passed:
35
24
  case True, True:
@@ -39,7 +28,6 @@ class IIIFUriValidator:
39
28
  uri=uri,
40
29
  regex_has_passed=regex_has_passed,
41
30
  status_code=response.status_code,
42
- original_text=response.text,
43
31
  )
44
32
 
45
33
  def _make_network_call(self, uri: str) -> requests.Response | Exception:
@@ -1,15 +1,15 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from collections.abc import Iterable
3
4
  from dataclasses import dataclass
4
5
  from dataclasses import field
5
6
  from typing import Any
6
- from typing import Iterable
7
7
  from typing import Protocol
8
8
  from urllib.parse import quote_plus
9
9
 
10
10
  from loguru import logger
11
11
 
12
- from dsp_tools.utils.connection import Connection
12
+ from dsp_tools.clients.connection import Connection
13
13
 
14
14
 
15
15
  @dataclass(frozen=True)
@@ -39,7 +39,10 @@ class ProjectLists:
39
39
  class ListClient(Protocol):
40
40
  """Interface (protocol) for list-related requests to the DSP-API."""
41
41
 
42
- def get_list_node_id_to_iri_lookup(self) -> dict[str, str]:
42
+ con: Connection
43
+ project_iri: str
44
+
45
+ def get_list_node_id_to_iri_lookup(self) -> dict[tuple[str, str], str]:
43
46
  """Get a lookup of list node names to IRIs."""
44
47
 
45
48
 
@@ -51,27 +54,29 @@ class ListClientLive:
51
54
  project_iri: str
52
55
  list_info: ProjectLists | None = field(init=False, default=None)
53
56
 
54
- def get_list_node_id_to_iri_lookup(self) -> dict[str, str]:
57
+ def get_list_node_id_to_iri_lookup(self) -> dict[tuple[str, str], str]:
55
58
  """
56
59
  Get a mapping of list node IDs to their respective IRIs.
57
60
  A list node ID is structured as follows:
58
- `<list name>`:`<node name>` where the list name is the node name of the root node.
61
+ `("<list name>", "<node name>") where the list name is the node name of the root node.
59
62
 
60
63
  Returns:
61
64
  The mapping of list node IDs to IRIs.
62
65
  """
63
66
  if not self.list_info:
64
67
  self.list_info = _get_list_info_from_server(self.con, self.project_iri)
65
- return dict(_get_node_tuples(self.list_info.lists))
68
+ lookup = dict(_get_node_tuples(self.list_info.lists))
69
+ # Enable referencing list node IRIs in the XML:
70
+ # add a reference of the list node IRIs to themselves (with empty list names)
71
+ lookup.update({("", v): v for v in lookup.values()})
72
+ return lookup
66
73
 
67
74
 
68
- def _get_node_tuples(lists: list[List]) -> Iterable[tuple[str, str]]:
75
+ def _get_node_tuples(lists: list[List]) -> Iterable[tuple[tuple[str, str], str]]:
69
76
  for lst in lists:
70
77
  list_name = lst.list_name
71
78
  for node in lst.nodes:
72
- node_name = node.node_name
73
- node_id = f"{list_name}:{node_name}"
74
- yield node_id, node.node_iri
79
+ yield (list_name, node.node_name), node.node_iri
75
80
 
76
81
 
77
82
  def _get_list_info_from_server(con: Connection, project_iri: str) -> ProjectLists:
@@ -0,0 +1,67 @@
1
+ from __future__ import annotations
2
+
3
+ from loguru import logger
4
+ from lxml import etree
5
+
6
+ from dsp_tools.clients.connection import Connection
7
+ from dsp_tools.commands.xmlupload.models.lookup_models import XmlReferenceLookups
8
+ from dsp_tools.commands.xmlupload.models.processed.res import ProcessedResource
9
+ from dsp_tools.commands.xmlupload.models.upload_clients import UploadClients
10
+ from dsp_tools.commands.xmlupload.stash.analyse_circular_reference_graph import generate_upload_order
11
+ from dsp_tools.commands.xmlupload.stash.create_info_for_graph import create_info_for_graph_from_processed_resources
12
+ from dsp_tools.commands.xmlupload.stash.stash_circular_references import stash_circular_references
13
+ from dsp_tools.commands.xmlupload.stash.stash_models import Stash
14
+ from dsp_tools.error.exceptions import BaseError
15
+ from dsp_tools.error.exceptions import InputError
16
+ from dsp_tools.legacy_models.projectContext import ProjectContext
17
+ from dsp_tools.utils.xml_parsing.get_lookups import get_authorship_lookup
18
+ from dsp_tools.utils.xml_parsing.get_lookups import get_permissions_lookup
19
+ from dsp_tools.utils.xml_parsing.get_parsed_resources import get_parsed_resources
20
+ from dsp_tools.utils.xml_parsing.models.parsed_resource import ParsedResource
21
+
22
+ LIST_SEPARATOR = "\n- "
23
+
24
+
25
+ def get_parsed_resources_and_mappers(
26
+ root: etree._Element, clients: UploadClients
27
+ ) -> tuple[list[ParsedResource], XmlReferenceLookups]:
28
+ logger.debug("Get ParsedResource and XML-Lookups from root")
29
+ print("Parsing XML file for upload.")
30
+ parsed_resources = get_parsed_resources(root, clients.legal_info_client.server)
31
+ processed_lookups = _get_xml_reference_lookups(root=root, clients=clients)
32
+ return parsed_resources, processed_lookups
33
+
34
+
35
+ def _get_xml_reference_lookups(root: etree._Element, clients: UploadClients) -> XmlReferenceLookups:
36
+ proj_context = _get_project_context_from_server(
37
+ connection=clients.list_client.con, shortcode=root.attrib["shortcode"]
38
+ )
39
+ permissions_lookup = get_permissions_lookup(root, proj_context)
40
+ authorship_lookup = get_authorship_lookup(root)
41
+ listnode_lookup = clients.list_client.get_list_node_id_to_iri_lookup()
42
+ return XmlReferenceLookups(
43
+ permissions=permissions_lookup,
44
+ listnodes=listnode_lookup,
45
+ authorships=authorship_lookup,
46
+ )
47
+
48
+
49
+ def _get_project_context_from_server(connection: Connection, shortcode: str) -> ProjectContext:
50
+ try:
51
+ proj_context = ProjectContext(con=connection, shortcode=shortcode)
52
+ except BaseError:
53
+ logger.exception("Unable to retrieve project context from DSP server")
54
+ raise InputError("Unable to retrieve project context from DSP server") from None
55
+ return proj_context
56
+
57
+
58
+ def get_stash_and_upload_order(
59
+ resources: list[ProcessedResource],
60
+ ) -> tuple[list[ProcessedResource], Stash | None]:
61
+ logger.debug("Get stash and upload order")
62
+ info_for_graph = create_info_for_graph_from_processed_resources(resources)
63
+ stash_lookup, upload_order = generate_upload_order(info_for_graph)
64
+ sorting_lookup = {res.res_id: res for res in resources}
65
+ sorted_resources = [sorting_lookup[res_id] for res_id in upload_order]
66
+ stash = stash_circular_references(sorted_resources, stash_lookup)
67
+ return sorted_resources, stash