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,243 @@
1
+ from typing import Any
2
+ from typing import cast
3
+
4
+ from dsp_tools.commands.create.models.create_problems import CollectedProblems
5
+ from dsp_tools.commands.create.models.create_problems import CreateProblem
6
+ from dsp_tools.commands.create.models.create_problems import InputProblem
7
+ from dsp_tools.commands.create.models.create_problems import InputProblemType
8
+ from dsp_tools.commands.create.models.parsed_ontology import Cardinality
9
+ from dsp_tools.commands.create.models.parsed_ontology import GuiElement
10
+ from dsp_tools.commands.create.models.parsed_ontology import KnoraObjectType
11
+ from dsp_tools.commands.create.models.parsed_ontology import ParsedClass
12
+ from dsp_tools.commands.create.models.parsed_ontology import ParsedClassCardinalities
13
+ from dsp_tools.commands.create.models.parsed_ontology import ParsedOntology
14
+ from dsp_tools.commands.create.models.parsed_ontology import ParsedProperty
15
+ from dsp_tools.commands.create.models.parsed_ontology import ParsedPropertyCardinality
16
+ from dsp_tools.commands.create.parsing.parsing_utils import resolve_to_absolute_iri
17
+
18
+ CARDINALITY_MAPPER = {
19
+ "0-1": Cardinality.C_0_1,
20
+ "1": Cardinality.C_1,
21
+ "0-n": Cardinality.C_0_N,
22
+ "1-n": Cardinality.C_1_N,
23
+ }
24
+
25
+ OBJECT_TYPE_MAPPER = {
26
+ "BooleanValue": KnoraObjectType.BOOLEAN,
27
+ "ColorValue": KnoraObjectType.COLOR,
28
+ "DateValue": KnoraObjectType.DATE,
29
+ "DecimalValue": KnoraObjectType.DECIMAL,
30
+ "GeonameValue": KnoraObjectType.GEONAME,
31
+ "IntValue": KnoraObjectType.INT,
32
+ "ListValue": KnoraObjectType.LIST,
33
+ "TextValue": KnoraObjectType.TEXT,
34
+ "TimeValue": KnoraObjectType.TIME,
35
+ "UriValue": KnoraObjectType.URI,
36
+ }
37
+
38
+ GUI_ELEMENT_MAPPER = {
39
+ "Checkbox": GuiElement.CHECKBOX,
40
+ "Colorpicker": GuiElement.COLORPICKER,
41
+ "Date": GuiElement.DATE,
42
+ "Spinbox": GuiElement.SPINBOX,
43
+ "Geonames": GuiElement.GEONAMES,
44
+ "List": GuiElement.LIST,
45
+ "SimpleText": GuiElement.SIMPLETEXT,
46
+ "Textarea": GuiElement.TEXTAREA,
47
+ "Richtext": GuiElement.RICHTEXT,
48
+ "Searchbox": GuiElement.SEARCHBOX,
49
+ "TimeStamp": GuiElement.TIME_STAMP,
50
+ }
51
+
52
+
53
+ def parse_ontology(ontology_json: dict[str, Any], prefixes: dict[str, str]) -> ParsedOntology | CollectedProblems:
54
+ onto_name = ontology_json["name"]
55
+ current_onto = prefixes[onto_name]
56
+ fails = []
57
+ props, prop_fails = _parse_properties(ontology_json["properties"], current_onto, prefixes)
58
+ fails.extend(prop_fails)
59
+ classes, cls_fails = _parse_classes(ontology_json["resources"], current_onto, prefixes)
60
+ fails.extend(cls_fails)
61
+ cards, card_fails = _parse_cardinalities(ontology_json["resources"], current_onto, prefixes)
62
+ fails.extend(card_fails)
63
+ if fails:
64
+ return CollectedProblems(
65
+ f"During the parsing of the ontology '{onto_name}' the following errors occurred", fails
66
+ )
67
+ return ParsedOntology(
68
+ name=onto_name,
69
+ label=ontology_json["label"],
70
+ comment=ontology_json.get("comment"),
71
+ classes=classes,
72
+ properties=props,
73
+ cardinalities=cards,
74
+ )
75
+
76
+
77
+ def _parse_properties(
78
+ properties_list: list[dict[str, Any]],
79
+ current_onto_prefix: str,
80
+ prefixes: dict[str, str],
81
+ ) -> tuple[list[ParsedProperty], list[CreateProblem]]:
82
+ problems: list[CreateProblem] = []
83
+ parsed = []
84
+ for prop in properties_list:
85
+ result = _parse_one_property(prop, current_onto_prefix, prefixes)
86
+ if isinstance(result, ParsedProperty):
87
+ parsed.append(result)
88
+ else:
89
+ problems.extend(result)
90
+ return parsed, problems
91
+
92
+
93
+ def _parse_one_property(
94
+ prop: dict[str, Any], current_onto_prefix: str, prefixes: dict[str, str]
95
+ ) -> ParsedProperty | list[CreateProblem]:
96
+ problems: list[CreateProblem] = []
97
+ prop_name = f"{current_onto_prefix}{prop['name']}"
98
+ labels = prop["labels"]
99
+ comments = prop.get("comments")
100
+ object_str = prop["object"]
101
+ gui_element = GUI_ELEMENT_MAPPER[prop["gui_element"]]
102
+ subject = prop.get("subject")
103
+
104
+ supers = []
105
+ for super_prop in prop["super"]:
106
+ if not (resolved := resolve_to_absolute_iri(super_prop, current_onto_prefix, prefixes)):
107
+ problems.append(
108
+ InputProblem(
109
+ f'At property "{prop["name"]}" / Super: "{super_prop}"',
110
+ InputProblemType.PREFIX_COULD_NOT_BE_RESOLVED,
111
+ )
112
+ )
113
+ else:
114
+ supers.append(resolved)
115
+
116
+ if gui_element == GuiElement.SEARCHBOX:
117
+ if not (obj_iri := resolve_to_absolute_iri(object_str, current_onto_prefix, prefixes)):
118
+ problems.append(
119
+ InputProblem(
120
+ f'At property "{prop["name"]}" / Object: "{object_str}"',
121
+ InputProblemType.PREFIX_COULD_NOT_BE_RESOLVED,
122
+ )
123
+ )
124
+ object_value = ""
125
+ else:
126
+ object_value = obj_iri
127
+ else:
128
+ object_value = OBJECT_TYPE_MAPPER[object_str]
129
+
130
+ if subject:
131
+ if not (resolved_subject := resolve_to_absolute_iri(prop["subject"], current_onto_prefix, prefixes)):
132
+ problems.append(
133
+ InputProblem(
134
+ f'At property "{prop["name"]}" / Subject: "{subject}"',
135
+ InputProblemType.PREFIX_COULD_NOT_BE_RESOLVED,
136
+ )
137
+ )
138
+ subject = resolved_subject
139
+
140
+ list_name = None
141
+ if object_value == KnoraObjectType.LIST:
142
+ list_name = prop["gui_attributes"]["hlist"]
143
+
144
+ if problems:
145
+ return problems
146
+ return ParsedProperty(
147
+ name=prop_name,
148
+ labels=labels,
149
+ comments=comments,
150
+ supers=supers,
151
+ object=object_value,
152
+ subject=subject,
153
+ gui_element=gui_element,
154
+ node_name=list_name,
155
+ onto_iri=current_onto_prefix.rstrip("#"),
156
+ )
157
+
158
+
159
+ def _parse_classes(
160
+ classes_list: list[dict[str, Any]], current_onto_prefix: str, prefixes: dict[str, str]
161
+ ) -> tuple[list[ParsedClass], list[CreateProblem]]:
162
+ parsed = []
163
+ problems = []
164
+ for cls in classes_list:
165
+ result = _parse_one_class(cls, current_onto_prefix, prefixes)
166
+ if isinstance(result, ParsedClass):
167
+ parsed.append(result)
168
+ else:
169
+ problems.extend(result)
170
+ return parsed, problems
171
+
172
+
173
+ def _parse_one_class(
174
+ cls: dict[str, Any], current_onto_prefix: str, prefixes: dict[str, str]
175
+ ) -> ParsedClass | list[CreateProblem]:
176
+ problems: list[CreateProblem] = []
177
+ supers = [cls["super"]] if isinstance(cls["super"], str) else cls["super"]
178
+ resolved_supers = []
179
+ for s in supers:
180
+ if not (resolved_super := resolve_to_absolute_iri(s, current_onto_prefix, prefixes)):
181
+ problems.append(
182
+ InputProblem(
183
+ f'At class "{cls["name"]}" / Super: "{s}"',
184
+ InputProblemType.PREFIX_COULD_NOT_BE_RESOLVED,
185
+ )
186
+ )
187
+ else:
188
+ resolved_supers.append(resolved_super)
189
+ if problems:
190
+ return problems
191
+ return ParsedClass(
192
+ name=f"{current_onto_prefix}{cls['name']}",
193
+ labels=cls["labels"],
194
+ comments=cls.get("comments"),
195
+ supers=resolved_supers,
196
+ onto_iri=current_onto_prefix.rstrip("#"),
197
+ )
198
+
199
+
200
+ def _parse_cardinalities(
201
+ classes_list: list[dict[str, Any]], current_onto_prefix: str, prefixes: dict[str, str]
202
+ ) -> tuple[list[ParsedClassCardinalities], list[CreateProblem]]:
203
+ parsed = []
204
+ failures = []
205
+ for c in classes_list:
206
+ if c.get("cardinalities"):
207
+ result = _parse_one_class_cardinality(c, current_onto_prefix, prefixes)
208
+ if isinstance(result, ParsedClassCardinalities):
209
+ parsed.append(result)
210
+ else:
211
+ failures.extend(result)
212
+ return parsed, failures
213
+
214
+
215
+ def _parse_one_class_cardinality(
216
+ cls_json: dict[str, Any], current_onto_prefix: str, prefixes: dict[str, str]
217
+ ) -> ParsedClassCardinalities | list[CreateProblem]:
218
+ failures = []
219
+ parsed = []
220
+ for c in cls_json["cardinalities"]:
221
+ result = _parse_one_cardinality(c, current_onto_prefix, prefixes)
222
+ if isinstance(result, ParsedPropertyCardinality):
223
+ parsed.append(result)
224
+ else:
225
+ failures.append(result)
226
+ if failures:
227
+ return failures
228
+ cls_iri = f"{current_onto_prefix}{cls_json['name']}"
229
+ return ParsedClassCardinalities(cls_iri, parsed)
230
+
231
+
232
+ def _parse_one_cardinality(
233
+ card_json: dict[str, str | int], current_onto_prefix: str, prefixes: dict[str, str]
234
+ ) -> ParsedPropertyCardinality | CreateProblem:
235
+ prp_name = cast(str, card_json["propname"])
236
+ if not (resolved := resolve_to_absolute_iri(prp_name, current_onto_prefix, prefixes)):
237
+ return CreateProblem(prp_name, InputProblemType.PREFIX_COULD_NOT_BE_RESOLVED)
238
+ gui = cast(int | None, card_json.get("gui_order"))
239
+ return ParsedPropertyCardinality(
240
+ propname=resolved,
241
+ cardinality=CARDINALITY_MAPPER[cast(str, card_json["cardinality"])],
242
+ gui_order=gui,
243
+ )
@@ -0,0 +1,149 @@
1
+ import os
2
+ from typing import Any
3
+
4
+ from dotenv import find_dotenv
5
+ from dotenv import load_dotenv
6
+
7
+ from dsp_tools.commands.create.models.create_problems import CollectedProblems
8
+ from dsp_tools.commands.create.models.create_problems import CreateProblem
9
+ from dsp_tools.commands.create.models.create_problems import InputProblem
10
+ from dsp_tools.commands.create.models.create_problems import InputProblemType
11
+ from dsp_tools.commands.create.models.parsed_ontology import ParsedOntology
12
+ from dsp_tools.commands.create.models.parsed_project import ParsedGroup
13
+ from dsp_tools.commands.create.models.parsed_project import ParsedGroupDescription
14
+ from dsp_tools.commands.create.models.parsed_project import ParsedList
15
+ from dsp_tools.commands.create.models.parsed_project import ParsedPermissions
16
+ from dsp_tools.commands.create.models.parsed_project import ParsedProject
17
+ from dsp_tools.commands.create.models.parsed_project import ParsedProjectMetadata
18
+ from dsp_tools.commands.create.models.parsed_project import ParsedUser
19
+ from dsp_tools.commands.create.models.parsed_project import ParsedUserMemberShipInfo
20
+ from dsp_tools.commands.create.parsing.parse_lists import parse_list_section
21
+ from dsp_tools.commands.create.parsing.parse_ontology import parse_ontology
22
+ from dsp_tools.commands.create.parsing.parsing_utils import create_prefix_lookup
23
+
24
+ # Load .env file only if it exists in the current working directory
25
+ # This allows CI to set environment variables directly without interference
26
+ dotenv_file = find_dotenv(usecwd=True)
27
+ if dotenv_file:
28
+ load_dotenv(dotenv_path=dotenv_file, override=False)
29
+
30
+
31
+ def parse_project(complete_json: dict[str, Any], api_url: str) -> ParsedProject | list[CollectedProblems]:
32
+ prefix_lookup = create_prefix_lookup(complete_json, api_url)
33
+ project_json = complete_json["project"]
34
+ ontologies, failures = _parse_all_ontologies(project_json, prefix_lookup)
35
+ parsed_lists, list_problems = _parse_lists(project_json)
36
+ if list_problems:
37
+ failures.append(list_problems)
38
+ users, memberships, user_problems = _parse_users(project_json)
39
+ if user_problems:
40
+ failures.append(user_problems)
41
+ if failures:
42
+ return failures
43
+ return ParsedProject(
44
+ prefixes=prefix_lookup,
45
+ project_metadata=_parse_metadata(project_json),
46
+ permissions=_parse_permissions(project_json),
47
+ groups=_parse_groups(project_json),
48
+ users=users,
49
+ user_memberships=memberships,
50
+ lists=parsed_lists,
51
+ ontologies=ontologies,
52
+ )
53
+
54
+
55
+ def _parse_metadata(project_json: dict[str, Any]) -> ParsedProjectMetadata:
56
+ return ParsedProjectMetadata(
57
+ shortcode=project_json["shortcode"],
58
+ shortname=project_json["shortname"],
59
+ longname=project_json["longname"],
60
+ descriptions=project_json["descriptions"],
61
+ keywords=project_json["keywords"],
62
+ enabled_licenses=project_json.get("enabled_licenses", []),
63
+ )
64
+
65
+
66
+ def _parse_permissions(project_json: dict[str, Any]) -> ParsedPermissions:
67
+ return ParsedPermissions(
68
+ default_permissions=project_json["default_permissions"],
69
+ default_permissions_overrule=project_json.get("default_permissions_overrule"),
70
+ )
71
+
72
+
73
+ def _parse_groups(project_json: dict[str, Any]) -> list[ParsedGroup]:
74
+ if not (found := project_json.get("groups")):
75
+ return []
76
+ return [_parse_one_group(x) for x in found]
77
+
78
+
79
+ def _parse_one_group(group_dict: dict[str, Any]) -> ParsedGroup:
80
+ descriptions = [ParsedGroupDescription(lang=lang, text=text) for lang, text in group_dict["descriptions"].items()]
81
+ return ParsedGroup(name=group_dict["name"], descriptions=descriptions)
82
+
83
+
84
+ def _parse_users(
85
+ project_json: dict[str, Any],
86
+ ) -> tuple[list[ParsedUser], list[ParsedUserMemberShipInfo], CollectedProblems | None]:
87
+ if not (found := project_json.get("users")):
88
+ return [], [], None
89
+ users, memberships = [], []
90
+ input_problems: list[CreateProblem] = []
91
+ for u in found:
92
+ result = _parse_one_user(u)
93
+ if isinstance(result, InputProblem):
94
+ input_problems.append(result)
95
+ else:
96
+ usr, mbmr = result
97
+ users.append(usr)
98
+ memberships.append(mbmr)
99
+ if input_problems:
100
+ problem_collection = CollectedProblems(
101
+ "When parsing the user section the following problems occurred:", input_problems
102
+ )
103
+ else:
104
+ problem_collection = None
105
+ return users, memberships, problem_collection
106
+
107
+
108
+ def _parse_one_user(user_dict: dict[str, Any]) -> tuple[ParsedUser, ParsedUserMemberShipInfo] | InputProblem:
109
+ projects = user_dict.get("projects", [])
110
+ is_admin = ":admin" in projects
111
+ groups = [g.removeprefix(":") for g in user_dict.get("groups", [])]
112
+ pw = user_dict["password"]
113
+ if not pw:
114
+ pw = os.getenv("DSP_USER_PASSWORD")
115
+ if not pw:
116
+ return InputProblem(user_dict["username"], InputProblemType.USER_PASSWORD_NOT_SET)
117
+ usr = ParsedUser(
118
+ username=user_dict["username"],
119
+ email=user_dict["email"],
120
+ given_name=user_dict["givenName"],
121
+ family_name=user_dict["familyName"],
122
+ password=pw,
123
+ lang=user_dict.get("lang", "en"),
124
+ )
125
+ memberships = ParsedUserMemberShipInfo(user_dict["username"], is_admin, groups)
126
+ return usr, memberships
127
+
128
+
129
+ def _parse_lists(project_json: dict[str, Any]) -> tuple[list[ParsedList], CollectedProblems | None]:
130
+ if not (found := project_json.get("lists")):
131
+ return [], None
132
+ result = parse_list_section(found)
133
+ if isinstance(result, CollectedProblems):
134
+ return [], result
135
+ return result, None
136
+
137
+
138
+ def _parse_all_ontologies(
139
+ project_json: dict[str, Any], prefix_lookup: dict[str, str]
140
+ ) -> tuple[list[ParsedOntology], list[CollectedProblems]]:
141
+ ontos = []
142
+ failures = []
143
+ for o in project_json["ontologies"]:
144
+ result = parse_ontology(o, prefix_lookup)
145
+ if isinstance(result, ParsedOntology):
146
+ ontos.append(result)
147
+ else:
148
+ failures.append(result)
149
+ return ontos, failures
@@ -0,0 +1,40 @@
1
+ from typing import Any
2
+
3
+ import regex
4
+
5
+ from dsp_tools.utils.data_formats.iri_util import make_dsp_ontology_prefix
6
+ from dsp_tools.utils.data_formats.uri_util import is_uri
7
+ from dsp_tools.utils.rdf_constants import DSP_NAME_TO_PREFIX
8
+ from dsp_tools.utils.rdf_constants import KNORA_API_PREFIX
9
+
10
+
11
+ def resolve_to_absolute_iri(prefixed: str, current_onto: str, prefix_lookup: dict[str, str]) -> str | None:
12
+ if is_uri(prefixed):
13
+ return prefixed
14
+ if prefixed.startswith(":"):
15
+ return f"{current_onto}{prefixed.lstrip(':')}"
16
+ segments = prefixed.split(":", maxsplit=1)
17
+ if len(segments) == 1:
18
+ return f"{KNORA_API_PREFIX}{segments[0]}"
19
+ if not (found := prefix_lookup.get(segments[0])):
20
+ return None
21
+ return f"{found}{segments[1]}"
22
+
23
+
24
+ def create_prefix_lookup(project_json: dict[str, Any], api_url: str) -> dict[str, str]:
25
+ defined_prefixes = project_json.get("prefixes", {})
26
+ defined_prefixes = defined_prefixes | DSP_NAME_TO_PREFIX
27
+ defined_prefixes = _correct_external_prefix(defined_prefixes)
28
+ shortcode = project_json["project"]["shortcode"]
29
+ for onto in project_json["project"]["ontologies"]:
30
+ onto_name = onto["name"]
31
+ defined_prefixes[onto_name] = make_dsp_ontology_prefix(api_url, shortcode, onto_name)
32
+ return defined_prefixes
33
+
34
+
35
+ def _correct_external_prefix(prefixes: dict[str, str]) -> dict[str, str]:
36
+ for prfx, namespace in prefixes.items():
37
+ if regex.search(r"(#|\/)$", namespace):
38
+ continue
39
+ prefixes[prfx] = f"{namespace}/"
40
+ return prefixes