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,58 @@
1
+ from __future__ import annotations
2
+
3
+ import warnings
4
+ from pathlib import Path
5
+
6
+ from loguru import logger
7
+ from lxml import etree
8
+ from tqdm import tqdm
9
+
10
+ from dsp_tools.commands.xmlupload.models.input_problems import AllIIIFUriProblems
11
+ from dsp_tools.commands.xmlupload.prepare_xml_input.iiif_uri_validator import IIIFUriValidator
12
+ from dsp_tools.error.custom_warnings import DspToolsUserWarning
13
+ from dsp_tools.error.exceptions import InputError
14
+
15
+
16
+ def validate_iiif_uris(root: etree._Element) -> None:
17
+ uris = [uri.strip() for node in root.iter(tag="iiif-uri") if (uri := node.text)]
18
+ if (num := len(uris)) > 1001:
19
+ warnings.warn(
20
+ DspToolsUserWarning(
21
+ f"Your data contains {num} IIIF-URIs. "
22
+ f"Each validation makes a server call. "
23
+ f"Due to the large number, the validation of the IIIF-URIs has to be skipped."
24
+ )
25
+ )
26
+ return
27
+ progress_bar = tqdm(uris, desc="Checking IIIF-URIs", dynamic_ncols=True)
28
+ validator = IIIFUriValidator()
29
+ problems = []
30
+ for uri in progress_bar:
31
+ if result := validator.validate_one_uri(uri):
32
+ problems.append(result)
33
+ if problems:
34
+ msg = AllIIIFUriProblems(problems).get_msg()
35
+ warnings.warn(DspToolsUserWarning(msg))
36
+ logger.warning(msg)
37
+
38
+
39
+ def check_if_bitstreams_exist(root: etree._Element, imgdir: str) -> None:
40
+ """
41
+ Make sure that all bitstreams referenced in the XML file exist in the imgdir.
42
+
43
+ Args:
44
+ root: parsed XML file
45
+ imgdir: folder where the bitstreams are stored
46
+
47
+ Raises:
48
+ InputError: if a bitstream does not exist in the imgdir
49
+ """
50
+ logger.debug("Checking if filepaths exist.")
51
+ multimedia_resources = [x for x in root if any(y.tag == "bitstream" for y in x.iter())]
52
+ progress_bar = tqdm(multimedia_resources, desc="Checking multimedia filepaths", dynamic_ncols=True)
53
+ for res in progress_bar:
54
+ pth = next(Path(x.text.strip()) for x in res.iter() if x.tag == "bitstream" and x.text)
55
+ if not Path(imgdir / pth).is_file():
56
+ raise InputError(
57
+ f"Bitstream '{pth!s}' of resource '{res.attrib['label']}' does not exist in the imgdir '{imgdir}'."
58
+ )
@@ -0,0 +1,118 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ from collections.abc import Callable
5
+ from dataclasses import dataclass
6
+ from json.decoder import JSONDecodeError
7
+ from typing import Union
8
+ from typing import assert_never
9
+ from typing import cast
10
+
11
+ from dsp_tools.commands.xmlupload.models.formatted_text_value import FormattedTextValue
12
+ from dsp_tools.commands.xmlupload.models.processed.values import IntervalFloats
13
+ from dsp_tools.commands.xmlupload.models.processed.values import ProcessedValue
14
+ from dsp_tools.commands.xmlupload.models.processed.values import ProcessedValueTypes
15
+ from dsp_tools.error.exceptions import XmlInputConversionError
16
+ from dsp_tools.utils.data_formats.date_util import Date
17
+ from dsp_tools.utils.data_formats.date_util import parse_date_string
18
+
19
+ type InputTypes = Union[str, FormattedTextValue, tuple[str | None, str | None] | None]
20
+
21
+
22
+ @dataclass
23
+ class TypeTransformerMapper:
24
+ val_type: type[ProcessedValue]
25
+ val_transformer: Callable[[InputTypes], ProcessedValueTypes]
26
+
27
+
28
+ def assert_is_string(value: InputTypes) -> str:
29
+ """Assert a value is a string."""
30
+ match value:
31
+ case str() as s:
32
+ return s
33
+ case FormattedTextValue() as xml:
34
+ raise XmlInputConversionError(f"Expected string value, but got XML value: {xml.xmlstr}")
35
+ case tuple():
36
+ raise XmlInputConversionError(f"Expected string value, but got tuple value: {value}")
37
+ case None:
38
+ raise XmlInputConversionError("Expected string value, but got None")
39
+ case _:
40
+ assert_never(value)
41
+
42
+
43
+ def assert_is_tuple(value: InputTypes) -> tuple[str, str]:
44
+ """Assert a value is a tuple."""
45
+ match value:
46
+ case tuple() as t:
47
+ if len(t) == 2 and isinstance(t[0], str) and isinstance(t[1], str):
48
+ return cast(tuple[str, str], t)
49
+ raise XmlInputConversionError(f"Expected tuple with two elements but got {value}")
50
+ case FormattedTextValue() as xml:
51
+ raise XmlInputConversionError(f"Expected tuple value, but got XML value: {xml.xmlstr}")
52
+ case str():
53
+ raise XmlInputConversionError(f"Expected tuple value, but got string value: {value}")
54
+ case None:
55
+ raise XmlInputConversionError("Expected tuple value, but got None")
56
+ case _:
57
+ assert_never(value)
58
+
59
+
60
+ def transform_boolean(value: InputTypes) -> bool:
61
+ """Transform the value into a boolean"""
62
+ match value:
63
+ case "True" | "true" | "1" | 1 | True:
64
+ return True
65
+ case "False" | "false" | "0" | 0 | False:
66
+ return False
67
+ case _:
68
+ raise XmlInputConversionError(f"Could not parse boolean value: {value}")
69
+
70
+
71
+ def transform_date(input_value: InputTypes) -> Date:
72
+ """Transform a date string into a date object."""
73
+ val = assert_is_string(input_value)
74
+ return parse_date_string(val)
75
+
76
+
77
+ def transform_decimal(value: InputTypes) -> float:
78
+ """Transform a value into a float"""
79
+ str_val = assert_is_string(value)
80
+ return float(str_val)
81
+
82
+
83
+ def transform_integer(value: InputTypes) -> int:
84
+ """Transform a value into an integer"""
85
+ str_val = assert_is_string(value)
86
+ return int(str_val)
87
+
88
+
89
+ def transform_interval(input_value: InputTypes) -> IntervalFloats:
90
+ """Transform a string input into an interval object."""
91
+ val = assert_is_tuple(input_value)
92
+ try:
93
+ return IntervalFloats(float(val[0]), float(val[1]))
94
+ except ValueError:
95
+ raise XmlInputConversionError(f"Could not parse interval: {val}") from None
96
+
97
+
98
+ def transform_geometry(value: InputTypes) -> str:
99
+ """Transform a value into a geometry string"""
100
+ str_val = assert_is_string(value)
101
+ try:
102
+ return json.dumps(json.loads(str_val))
103
+ except JSONDecodeError:
104
+ raise XmlInputConversionError(f"Could not parse json value: {value}") from None
105
+
106
+
107
+ def transform_simpletext(value: InputTypes) -> str:
108
+ str_val = assert_is_string(value)
109
+ if len(str_val) == 0:
110
+ raise XmlInputConversionError("After removing redundant whitespaces and newlines the input string is empty.")
111
+ return str_val
112
+
113
+
114
+ def transform_richtext(value: InputTypes) -> FormattedTextValue:
115
+ str_val = assert_is_string(value)
116
+ if len(str_val) == 0:
117
+ raise XmlInputConversionError("After removing redundant whitespaces and newlines the input string is empty.")
118
+ return FormattedTextValue(str_val)
@@ -1,43 +1,10 @@
1
- import json
2
1
  from dataclasses import dataclass
3
- from pathlib import Path
4
- from typing import Any
5
- from typing import assert_never
6
2
  from typing import cast
7
3
 
8
- from loguru import logger
9
- from rdflib import RDF
10
- from rdflib import BNode
11
4
  from rdflib import Graph
12
- from rdflib import Literal
13
- from rdflib import Namespace
14
- from rdflib import URIRef
15
5
 
16
- from dsp_tools.commands.xmlupload.ark2iri import convert_ark_v0_to_resource_iri
17
- from dsp_tools.commands.xmlupload.iri_resolver import IriResolver
18
- from dsp_tools.commands.xmlupload.models.deserialise.deserialise_value import IIIFUriInfo
19
- from dsp_tools.commands.xmlupload.models.deserialise.deserialise_value import XMLProperty
20
- from dsp_tools.commands.xmlupload.models.deserialise.deserialise_value import XMLValue
21
- from dsp_tools.commands.xmlupload.models.deserialise.xmlresource import BitstreamInfo
22
- from dsp_tools.commands.xmlupload.models.deserialise.xmlresource import XMLResource
23
- from dsp_tools.commands.xmlupload.models.formatted_text_value import FormattedTextValue
24
- from dsp_tools.commands.xmlupload.models.namespace_context import get_json_ld_context_for_project
25
- from dsp_tools.commands.xmlupload.models.namespace_context import make_namespace_dict_from_onto_names
26
- from dsp_tools.commands.xmlupload.models.permission import Permissions
27
- from dsp_tools.commands.xmlupload.models.serialise.jsonld_serialiser import serialise_property_graph
28
- from dsp_tools.commands.xmlupload.models.serialise.serialise_value import SerialiseProperty
29
- from dsp_tools.commands.xmlupload.models.serialise.serialise_value import SerialiseURI
30
- from dsp_tools.commands.xmlupload.models.serialise.serialise_value import SerialiseValue
31
- from dsp_tools.models.exceptions import BaseError
32
- from dsp_tools.models.exceptions import InputError
33
- from dsp_tools.models.exceptions import PermissionNotExistsError
34
- from dsp_tools.models.exceptions import UserError
35
- from dsp_tools.utils.connection import Connection
36
- from dsp_tools.utils.date_util import parse_date_string
37
- from dsp_tools.utils.iri_util import is_resource_iri
38
- from dsp_tools.utils.logger_config import WARNINGS_SAVEPATH
39
-
40
- KNORA_API = Namespace("http://api.knora.org/ontology/knora-api/v2#")
6
+ from dsp_tools.clients.connection import Connection
7
+ from dsp_tools.commands.xmlupload.make_rdf_graph.jsonld_utils import serialise_jsonld_for_resource
41
8
 
42
9
 
43
10
  @dataclass(frozen=True)
@@ -45,442 +12,14 @@ class ResourceCreateClient:
45
12
  """client class that creates resources on a DSP server."""
46
13
 
47
14
  con: Connection
48
- project_iri: str
49
- iri_resolver: IriResolver
50
- project_onto_dict: dict[str, str]
51
- permissions_lookup: dict[str, Permissions]
52
- listnode_lookup: dict[str, str]
53
- media_previously_ingested: bool = False
54
15
 
55
16
  def create_resource(
56
17
  self,
57
- resource: XMLResource,
58
- bitstream_information: BitstreamInfo | None,
18
+ graph: Graph,
19
+ resource_has_bitstream: bool,
59
20
  ) -> str:
60
21
  """Creates a resource on the DSP server, and returns its IRI"""
61
- logger.info(
62
- f"Attempting to create resource {resource.res_id} (label: {resource.label}, iri: {resource.iri})..."
63
- )
64
- resource_dict = self._make_resource_with_values(resource, bitstream_information)
65
- headers = {"X-Asset-Ingested": "true"} if bitstream_information else None
66
- res = self.con.post(route="/v2/resources", data=resource_dict, headers=headers)
22
+ res_dict = serialise_jsonld_for_resource(graph)
23
+ headers = {"X-Asset-Ingested": "true"} if resource_has_bitstream else None
24
+ res = self.con.post(route="/v2/resources", data=res_dict, headers=headers)
67
25
  return cast(str, res["@id"])
68
-
69
- def _make_resource_with_values(
70
- self,
71
- resource: XMLResource,
72
- bitstream_information: BitstreamInfo | None,
73
- ) -> dict[str, Any]:
74
- res_bnode = BNode()
75
- namespaces = make_namespace_dict_from_onto_names(self.project_onto_dict)
76
- res = self._make_resource(
77
- resource=resource,
78
- bitstream_information=bitstream_information,
79
- )
80
- vals = self._make_values(resource, res_bnode, namespaces)
81
- res.update(vals)
82
- return res
83
-
84
- def _make_resource(
85
- self,
86
- resource: XMLResource,
87
- bitstream_information: BitstreamInfo | None,
88
- ) -> dict[str, Any]:
89
- resource_iri = resource.iri
90
- if resource.ark:
91
- resource_iri = convert_ark_v0_to_resource_iri(resource.ark)
92
- context = get_json_ld_context_for_project(self.project_onto_dict)
93
- res = {
94
- "@type": resource.restype,
95
- "rdfs:label": resource.label,
96
- "knora-api:attachedToProject": {"@id": self.project_iri},
97
- "@context": context,
98
- }
99
- if resource_iri:
100
- res["@id"] = resource_iri
101
- if resource.permissions:
102
- if perm := self.permissions_lookup.get(resource.permissions):
103
- res["knora-api:hasPermissions"] = str(perm)
104
- else:
105
- raise PermissionNotExistsError(
106
- f"Could not find permissions for resource {resource.res_id} with permissions {resource.permissions}"
107
- )
108
- if resource.creation_date:
109
- res["knora-api:creationDate"] = {
110
- "@type": "xsd:dateTimeStamp",
111
- "@value": str(resource.creation_date),
112
- }
113
- if bitstream_information:
114
- res.update(_make_bitstream_file_value(bitstream_information))
115
- return res
116
-
117
- def _make_values(self, resource: XMLResource, res_bnode: BNode, namespaces: dict[str, Namespace]) -> dict[str, Any]:
118
- def prop_name(p: XMLProperty) -> str:
119
- if p.valtype != "resptr":
120
- return p.name
121
- elif p.name == "knora-api:isSegmentOf" and resource.restype == "knora-api:VideoSegment":
122
- return "knora-api:isVideoSegmentOfValue"
123
- elif p.name == "knora-api:isSegmentOf" and resource.restype == "knora-api:AudioSegment":
124
- return "knora-api:isAudioSegmentOfValue"
125
- else:
126
- return f"{p.name}Value"
127
-
128
- def make_values(p: XMLProperty) -> list[dict[str, Any]]:
129
- return [self._make_value(v, p.valtype) for v in p.values]
130
-
131
- properties_serialised = {}
132
- properties_graph = Graph()
133
- # To frame the json-ld correctly, we need one property used in the graph. It does not matter which.
134
- last_prop_name = None
135
-
136
- for prop in resource.properties:
137
- match prop.valtype:
138
- case "uri":
139
- properties_serialised.update(_serialise_uri_prop(prop, self.permissions_lookup))
140
- case "integer":
141
- int_prop_name = self._get_absolute_prop_iri(prop.name, namespaces)
142
- int_graph = _make_integer_prop(prop, res_bnode, int_prop_name, self.permissions_lookup)
143
- properties_graph += int_graph
144
- last_prop_name = int_prop_name
145
- case "boolean":
146
- bool_prop_name = self._get_absolute_prop_iri(prop.name, namespaces)
147
- bool_graph = _make_boolean_prop(prop, res_bnode, bool_prop_name, self.permissions_lookup)
148
- properties_graph += bool_graph
149
- last_prop_name = bool_prop_name
150
- case _:
151
- properties_serialised[prop_name(prop)] = make_values(prop)
152
- if resource.iiif_uri:
153
- properties_graph += _make_iiif_uri_value(resource.iiif_uri, res_bnode, self.permissions_lookup)
154
- last_prop_name = KNORA_API.hasStillImageFileValue
155
- if last_prop_name:
156
- serialised_graph_props = serialise_property_graph(properties_graph, last_prop_name)
157
- properties_serialised.update(serialised_graph_props)
158
- return properties_serialised
159
-
160
- def _get_absolute_prop_iri(self, prefixed_prop: str, namespaces: dict[str, Namespace]) -> URIRef:
161
- prefix, prop = prefixed_prop.split(":", maxsplit=1)
162
- if not (namespace := namespaces.get(prefix)):
163
- raise InputError(f"Could not find namespace for prefix: {prefix}")
164
- return namespace[prop]
165
-
166
- def _make_value(self, value: XMLValue, value_type: str) -> dict[str, Any]: # noqa: PLR0912 (too many branches)
167
- match value_type:
168
- case "color":
169
- res = _make_color_value(value)
170
- case "date":
171
- res = _make_date_value(value)
172
- case "decimal":
173
- res = _make_decimal_value(value)
174
- case "geometry":
175
- res = _make_geometry_value(value)
176
- case "geoname":
177
- res = _make_geoname_value(value)
178
- case "interval":
179
- res = _make_interval_value(value)
180
- case "resptr":
181
- res = _make_link_value(value, self.iri_resolver)
182
- case "list":
183
- res = _make_list_value(value, self.listnode_lookup)
184
- case "text":
185
- res = _make_text_value(value, self.iri_resolver)
186
- case "time":
187
- res = _make_time_value(value)
188
- case _:
189
- raise UserError(f"Unknown value type: {value_type}")
190
- if value.comment:
191
- res["knora-api:valueHasComment"] = value.comment
192
- if value.permissions:
193
- if perm := self.permissions_lookup.get(value.permissions):
194
- res["knora-api:hasPermissions"] = str(perm)
195
- else:
196
- raise PermissionNotExistsError(f"Could not find permissions for value: {value.permissions}")
197
- return res
198
-
199
-
200
- def _add_optional_permission_triple(
201
- value: XMLValue | IIIFUriInfo, val_bn: BNode, g: Graph, permissions_lookup: dict[str, Permissions]
202
- ) -> None:
203
- if value.permissions:
204
- if not (per := permissions_lookup.get(value.permissions)):
205
- raise PermissionNotExistsError(f"Could not find permissions for value: {value.permissions}")
206
- g.add((val_bn, KNORA_API.hasPermissions, Literal(str(per))))
207
-
208
-
209
- def _make_iiif_uri_value(iiif_uri: IIIFUriInfo, res_bnode: BNode, permissions_lookup: dict[str, Permissions]) -> Graph:
210
- g = Graph()
211
- iiif_bn = BNode()
212
- g.add((res_bnode, KNORA_API.hasStillImageFileValue, iiif_bn))
213
- g.add((iiif_bn, RDF.type, KNORA_API.StillImageExternalFileValue))
214
- g.add((iiif_bn, KNORA_API.fileValueHasExternalUrl, Literal(iiif_uri.value)))
215
- _add_optional_permission_triple(iiif_uri, iiif_bn, g, permissions_lookup)
216
- return g
217
-
218
-
219
- def _make_bitstream_file_value(bitstream_info: BitstreamInfo) -> dict[str, Any]:
220
- local_file = Path(bitstream_info.local_file)
221
- file_ending = local_file.suffix[1:]
222
- match file_ending.lower():
223
- case "zip" | "tar" | "gz" | "z" | "tgz" | "gzip" | "7z":
224
- prop = "knora-api:hasArchiveFileValue"
225
- value_type = "ArchiveFileValue"
226
- case "mp3" | "wav":
227
- prop = "knora-api:hasAudioFileValue"
228
- value_type = "AudioFileValue"
229
- case "pdf" | "doc" | "docx" | "xls" | "xlsx" | "ppt" | "pptx":
230
- prop = "knora-api:hasDocumentFileValue"
231
- value_type = "DocumentFileValue"
232
- case "mp4":
233
- prop = "knora-api:hasMovingImageFileValue"
234
- value_type = "MovingImageFileValue"
235
- # jpx is the extension of the files returned by dsp-ingest
236
- case "jpg" | "jpeg" | "jp2" | "png" | "tif" | "tiff" | "jpx":
237
- prop = "knora-api:hasStillImageFileValue"
238
- value_type = "StillImageFileValue"
239
- case "odd" | "rng" | "txt" | "xml" | "xsd" | "xsl" | "csv":
240
- prop = "knora-api:hasTextFileValue"
241
- value_type = "TextFileValue"
242
- case _:
243
- raise BaseError(f"Unknown file ending '{file_ending}' for file '{local_file}'")
244
- file_value = {
245
- "@type": f"knora-api:{value_type}",
246
- "knora-api:fileValueHasFilename": bitstream_info.internal_file_name,
247
- }
248
- if bitstream_info.permissions:
249
- file_value["knora-api:hasPermissions"] = str(bitstream_info.permissions)
250
- return {prop: file_value}
251
-
252
-
253
- def _to_boolean(s: str | int | bool) -> bool:
254
- match s:
255
- case "True" | "true" | "1" | 1 | True:
256
- return True
257
- case "False" | "false" | "0" | 0 | False:
258
- return False
259
- case _:
260
- raise BaseError(f"Could not parse boolean value: {s}")
261
-
262
-
263
- def _make_color_value(value: XMLValue) -> dict[str, Any]:
264
- return {
265
- "@type": "knora-api:ColorValue",
266
- "knora-api:colorValueAsColor": value.value,
267
- }
268
-
269
-
270
- def _make_date_value(value: XMLValue) -> dict[str, Any]:
271
- string_value = _assert_is_string(value.value)
272
- date = parse_date_string(string_value)
273
- res: dict[str, Any] = {
274
- "@type": "knora-api:DateValue",
275
- "knora-api:dateValueHasStartYear": date.start.year,
276
- }
277
- if month := date.start.month:
278
- res["knora-api:dateValueHasStartMonth"] = month
279
- if day := date.start.day:
280
- res["knora-api:dateValueHasStartDay"] = day
281
- if era := date.start.era:
282
- res["knora-api:dateValueHasStartEra"] = era.value
283
- if calendar := date.calendar:
284
- res["knora-api:dateValueHasCalendar"] = calendar.value
285
- if date.end:
286
- res["knora-api:dateValueHasEndYear"] = date.end.year
287
- if month := date.end.month:
288
- res["knora-api:dateValueHasEndMonth"] = month
289
- if day := date.end.day:
290
- res["knora-api:dateValueHasEndDay"] = day
291
- if era := date.end.era:
292
- res["knora-api:dateValueHasEndEra"] = era.value
293
- return res
294
-
295
-
296
- def _make_decimal_value(value: XMLValue) -> dict[str, Any]:
297
- s = _assert_is_string(value.value)
298
- return {
299
- "@type": "knora-api:DecimalValue",
300
- "knora-api:decimalValueAsDecimal": {
301
- "@type": "xsd:decimal",
302
- "@value": str(float(s)),
303
- },
304
- }
305
-
306
-
307
- def _make_geometry_value(value: XMLValue) -> dict[str, Any]:
308
- s = _assert_is_string(value.value)
309
- # this removes all whitespaces from the embedded json string
310
- encoded_value = json.dumps(json.loads(s))
311
- return {
312
- "@type": "knora-api:GeomValue",
313
- "knora-api:geometryValueAsGeometry": encoded_value,
314
- }
315
-
316
-
317
- def _make_geoname_value(value: XMLValue) -> dict[str, Any]:
318
- return {
319
- "@type": "knora-api:GeonameValue",
320
- "knora-api:geonameValueAsGeonameCode": value.value,
321
- }
322
-
323
-
324
- def _make_boolean_prop(
325
- prop: XMLProperty, res_bn: BNode, prop_name: URIRef, permissions_lookup: dict[str, Permissions]
326
- ) -> Graph:
327
- g = Graph()
328
- for value in prop.values:
329
- single_val_bn = BNode()
330
- g.add((res_bn, prop_name, single_val_bn))
331
- g += _make_boolean_value(value, single_val_bn, permissions_lookup)
332
- return g
333
-
334
-
335
- def _make_boolean_value(value: XMLValue, val_bn: BNode, permissions_lookup: dict[str, Permissions]) -> Graph:
336
- s = _assert_is_string(value.value)
337
- g = Graph()
338
- g.add((val_bn, RDF.type, KNORA_API.BooleanValue))
339
- g.add((val_bn, KNORA_API.booleanValueAsBoolean, Literal(_to_boolean(s))))
340
- _add_optional_permission_triple(value, val_bn, g, permissions_lookup)
341
- if value.comment:
342
- g.add((val_bn, KNORA_API.valueHasComment, Literal(value.comment)))
343
- return g
344
-
345
-
346
- def _make_integer_prop(
347
- prop: XMLProperty, res_bn: BNode, prop_name: URIRef, permissions_lookup: dict[str, Permissions]
348
- ) -> Graph:
349
- g = Graph()
350
- for value in prop.values:
351
- single_val_bn = BNode()
352
- g.add((res_bn, prop_name, single_val_bn))
353
- g += _make_integer_value(value, single_val_bn, permissions_lookup)
354
- return g
355
-
356
-
357
- def _make_integer_value(value: XMLValue, val_bn: BNode, permissions_lookup: dict[str, Permissions]) -> Graph:
358
- s = _assert_is_string(value.value)
359
- g = Graph()
360
- g.add((val_bn, RDF.type, KNORA_API.IntValue))
361
- g.add((val_bn, KNORA_API.intValueAsInt, Literal(int(s))))
362
- _add_optional_permission_triple(value, val_bn, g, permissions_lookup)
363
- if value.comment:
364
- g.add((val_bn, KNORA_API.valueHasComment, Literal(value.comment)))
365
- return g
366
-
367
-
368
- def _make_interval_value(value: XMLValue) -> dict[str, Any]:
369
- s = _assert_is_string(value.value)
370
- match s.split(":", 1):
371
- case [start, end]:
372
- return {
373
- "@type": "knora-api:IntervalValue",
374
- "knora-api:intervalValueHasStart": {
375
- "@type": "xsd:decimal",
376
- "@value": str(float(start)),
377
- },
378
- "knora-api:intervalValueHasEnd": {
379
- "@type": "xsd:decimal",
380
- "@value": str(float(end)),
381
- },
382
- }
383
- case _:
384
- raise BaseError(f"Could not parse interval value: {s}")
385
-
386
-
387
- def _make_link_value(value: XMLValue, iri_resolver: IriResolver) -> dict[str, Any]:
388
- s = _assert_is_string(value.value)
389
- if is_resource_iri(s):
390
- iri = s
391
- elif resolved_iri := iri_resolver.get(s):
392
- iri = resolved_iri
393
- else:
394
- msg = (
395
- f"Could not find the ID {s} in the id2iri mapping. "
396
- f"This is probably because the resource '{s}' could not be created. "
397
- f"See {WARNINGS_SAVEPATH} for more information."
398
- )
399
- raise BaseError(msg)
400
- return {
401
- "@type": "knora-api:LinkValue",
402
- "knora-api:linkValueHasTargetIri": {
403
- "@id": iri,
404
- },
405
- }
406
-
407
-
408
- def _make_list_value(value: XMLValue, iri_lookup: dict[str, str]) -> dict[str, Any]:
409
- s = _assert_is_string(value.value)
410
- if iri := iri_lookup.get(s):
411
- return {
412
- "@type": "knora-api:ListValue",
413
- "knora-api:listValueAsListNode": {
414
- "@id": iri,
415
- },
416
- }
417
- else:
418
- msg = (
419
- f"Could not resolve list node ID '{s}' to IRI. "
420
- f"This is probably because the list node '{s}' does not exist on the server."
421
- )
422
- raise BaseError(msg)
423
-
424
-
425
- def _make_text_value(value: XMLValue, iri_resolver: IriResolver) -> dict[str, Any]:
426
- match value.value:
427
- case str() as s:
428
- return {
429
- "@type": "knora-api:TextValue",
430
- "knora-api:valueAsString": s,
431
- }
432
- case FormattedTextValue() as xml:
433
- xml_with_iris = xml.with_iris(iri_resolver)
434
- return {
435
- "@type": "knora-api:TextValue",
436
- "knora-api:textValueAsXml": xml_with_iris.as_xml(),
437
- "knora-api:textValueHasMapping": {
438
- "@id": "http://rdfh.ch/standoff/mappings/StandardMapping",
439
- },
440
- }
441
- case _:
442
- assert_never(value.value)
443
-
444
-
445
- def _make_time_value(value: XMLValue) -> dict[str, Any]:
446
- return {
447
- "@type": "knora-api:TimeValue",
448
- "knora-api:timeValueAsTimeStamp": {
449
- "@type": "xsd:dateTimeStamp",
450
- "@value": value.value,
451
- },
452
- }
453
-
454
-
455
- def _serialise_uri_prop(prop: XMLProperty, permissions_lookup: dict[str, Permissions]) -> dict[str, Any]:
456
- uri_values: list[SerialiseValue] = []
457
- for v in prop.values:
458
- if v.permissions:
459
- if not (per := permissions_lookup.get(v.permissions)):
460
- raise PermissionNotExistsError(f"Could not find permissions for value: {v.permissions}")
461
- permission = str(per)
462
- else:
463
- permission = None
464
- uri = cast(str, v.value)
465
- uri_values.append(
466
- SerialiseURI(
467
- value=uri,
468
- permissions=permission,
469
- comment=v.comment,
470
- )
471
- )
472
- prop_serialise = SerialiseProperty(
473
- property_name=prop.name,
474
- values=uri_values,
475
- )
476
- return prop_serialise.serialise()
477
-
478
-
479
- def _assert_is_string(value: str | FormattedTextValue) -> str:
480
- match value:
481
- case str() as s:
482
- return s
483
- case FormattedTextValue() as xml:
484
- raise BaseError(f"Expected string value, but got XML value: {xml.as_xml()}")
485
- case _:
486
- assert_never(value)