dsp-tools 0.9.13__py3-none-any.whl → 18.3.0.post13__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (348) hide show
  1. dsp_tools/__init__.py +5 -0
  2. dsp_tools/cli/args.py +47 -0
  3. dsp_tools/cli/call_action.py +85 -0
  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 +479 -0
  7. dsp_tools/cli/entry_point.py +322 -0
  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/clients/connection.py +35 -0
  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 +321 -0
  58. dsp_tools/commands/excel2json/lists/__init__.py +0 -0
  59. dsp_tools/commands/excel2json/lists/compliance_checks.py +292 -0
  60. dsp_tools/commands/excel2json/lists/make_lists.py +247 -0
  61. dsp_tools/commands/excel2json/lists/models/__init__.py +0 -0
  62. dsp_tools/commands/excel2json/lists/models/deserialise.py +30 -0
  63. dsp_tools/commands/excel2json/lists/models/input_error.py +216 -0
  64. dsp_tools/commands/excel2json/lists/models/serialise.py +57 -0
  65. dsp_tools/commands/excel2json/lists/utils.py +81 -0
  66. dsp_tools/commands/excel2json/models/__init__.py +0 -0
  67. dsp_tools/commands/excel2json/models/input_error.py +416 -0
  68. dsp_tools/commands/excel2json/models/json_header.py +175 -0
  69. dsp_tools/commands/excel2json/models/list_node_name.py +16 -0
  70. dsp_tools/commands/excel2json/models/ontology.py +76 -0
  71. dsp_tools/commands/excel2json/old_lists.py +328 -0
  72. dsp_tools/commands/excel2json/project.py +280 -0
  73. dsp_tools/commands/excel2json/properties.py +370 -0
  74. dsp_tools/commands/excel2json/resources.py +336 -0
  75. dsp_tools/commands/excel2json/utils.py +352 -0
  76. dsp_tools/commands/excel2xml/__init__.py +7 -0
  77. dsp_tools/commands/excel2xml/excel2xml_cli.py +523 -0
  78. dsp_tools/commands/excel2xml/excel2xml_lib.py +1953 -0
  79. dsp_tools/commands/excel2xml/propertyelement.py +47 -0
  80. dsp_tools/commands/get/__init__.py +0 -0
  81. dsp_tools/commands/get/get.py +166 -0
  82. dsp_tools/commands/get/get_permissions.py +257 -0
  83. dsp_tools/commands/get/get_permissions_legacy.py +89 -0
  84. dsp_tools/commands/get/legacy_models/__init__.py +0 -0
  85. dsp_tools/commands/get/legacy_models/context.py +318 -0
  86. dsp_tools/commands/get/legacy_models/group.py +241 -0
  87. dsp_tools/commands/get/legacy_models/helpers.py +47 -0
  88. dsp_tools/commands/get/legacy_models/listnode.py +390 -0
  89. dsp_tools/commands/get/legacy_models/model.py +12 -0
  90. dsp_tools/commands/get/legacy_models/ontology.py +324 -0
  91. dsp_tools/commands/get/legacy_models/project.py +366 -0
  92. dsp_tools/commands/get/legacy_models/propertyclass.py +417 -0
  93. dsp_tools/commands/get/legacy_models/resourceclass.py +676 -0
  94. dsp_tools/commands/get/legacy_models/user.py +438 -0
  95. dsp_tools/commands/get/models/__init__.py +0 -0
  96. dsp_tools/commands/get/models/permissions_models.py +10 -0
  97. dsp_tools/commands/id2iri.py +258 -0
  98. dsp_tools/commands/ingest_xmlupload/__init__.py +0 -0
  99. dsp_tools/commands/ingest_xmlupload/bulk_ingest_client.py +178 -0
  100. dsp_tools/commands/ingest_xmlupload/create_resources/__init__.py +0 -0
  101. dsp_tools/commands/ingest_xmlupload/create_resources/apply_ingest_id.py +69 -0
  102. dsp_tools/commands/ingest_xmlupload/create_resources/upload_xml.py +166 -0
  103. dsp_tools/commands/ingest_xmlupload/create_resources/user_information.py +121 -0
  104. dsp_tools/commands/ingest_xmlupload/ingest_files/__init__.py +0 -0
  105. dsp_tools/commands/ingest_xmlupload/ingest_files/ingest_files.py +64 -0
  106. dsp_tools/commands/ingest_xmlupload/upload_files/__init__.py +0 -0
  107. dsp_tools/commands/ingest_xmlupload/upload_files/filechecker.py +20 -0
  108. dsp_tools/commands/ingest_xmlupload/upload_files/input_error.py +57 -0
  109. dsp_tools/commands/ingest_xmlupload/upload_files/upload_failures.py +66 -0
  110. dsp_tools/commands/ingest_xmlupload/upload_files/upload_files.py +67 -0
  111. dsp_tools/commands/resume_xmlupload/__init__.py +0 -0
  112. dsp_tools/commands/resume_xmlupload/resume_xmlupload.py +96 -0
  113. dsp_tools/commands/start_stack.py +428 -0
  114. dsp_tools/commands/update_legal/CLAUDE.md +344 -0
  115. dsp_tools/commands/update_legal/__init__.py +0 -0
  116. dsp_tools/commands/update_legal/core.py +182 -0
  117. dsp_tools/commands/update_legal/csv_operations.py +135 -0
  118. dsp_tools/commands/update_legal/models.py +87 -0
  119. dsp_tools/commands/update_legal/xml_operations.py +247 -0
  120. dsp_tools/commands/validate_data/CLAUDE.md +159 -0
  121. dsp_tools/commands/validate_data/__init__.py +0 -0
  122. dsp_tools/commands/validate_data/constants.py +59 -0
  123. dsp_tools/commands/validate_data/mappers.py +143 -0
  124. dsp_tools/commands/validate_data/models/__init__.py +0 -0
  125. dsp_tools/commands/validate_data/models/api_responses.py +45 -0
  126. dsp_tools/commands/validate_data/models/input_problems.py +119 -0
  127. dsp_tools/commands/validate_data/models/rdf_like_data.py +117 -0
  128. dsp_tools/commands/validate_data/models/validation.py +106 -0
  129. dsp_tools/commands/validate_data/prepare_data/__init__.py +0 -0
  130. dsp_tools/commands/validate_data/prepare_data/get_rdf_like_data.py +296 -0
  131. dsp_tools/commands/validate_data/prepare_data/make_data_graph.py +91 -0
  132. dsp_tools/commands/validate_data/prepare_data/prepare_data.py +184 -0
  133. dsp_tools/commands/validate_data/process_validation_report/__init__.py +0 -0
  134. dsp_tools/commands/validate_data/process_validation_report/get_user_validation_message.py +358 -0
  135. dsp_tools/commands/validate_data/process_validation_report/query_validation_result.py +507 -0
  136. dsp_tools/commands/validate_data/process_validation_report/reformat_validation_results.py +150 -0
  137. dsp_tools/commands/validate_data/shacl_cli_validator.py +70 -0
  138. dsp_tools/commands/validate_data/sparql/__init__.py +0 -0
  139. dsp_tools/commands/validate_data/sparql/cardinality_shacl.py +209 -0
  140. dsp_tools/commands/validate_data/sparql/construct_shacl.py +92 -0
  141. dsp_tools/commands/validate_data/sparql/legal_info_shacl.py +36 -0
  142. dsp_tools/commands/validate_data/sparql/value_shacl.py +357 -0
  143. dsp_tools/commands/validate_data/utils.py +59 -0
  144. dsp_tools/commands/validate_data/validate_data.py +283 -0
  145. dsp_tools/commands/validate_data/validation/__init__.py +0 -0
  146. dsp_tools/commands/validate_data/validation/check_duplicate_files.py +55 -0
  147. dsp_tools/commands/validate_data/validation/check_for_unknown_classes.py +67 -0
  148. dsp_tools/commands/validate_data/validation/get_validation_report.py +94 -0
  149. dsp_tools/commands/validate_data/validation/validate_ontology.py +107 -0
  150. dsp_tools/commands/xmlupload/CLAUDE.md +292 -0
  151. dsp_tools/commands/xmlupload/__init__.py +0 -0
  152. dsp_tools/commands/xmlupload/iri_resolver.py +21 -0
  153. dsp_tools/commands/xmlupload/make_rdf_graph/__init__.py +0 -0
  154. dsp_tools/commands/xmlupload/make_rdf_graph/constants.py +63 -0
  155. dsp_tools/commands/xmlupload/make_rdf_graph/jsonld_utils.py +44 -0
  156. dsp_tools/commands/xmlupload/make_rdf_graph/make_file_value.py +77 -0
  157. dsp_tools/commands/xmlupload/make_rdf_graph/make_resource_and_values.py +114 -0
  158. dsp_tools/commands/xmlupload/make_rdf_graph/make_values.py +262 -0
  159. dsp_tools/commands/xmlupload/models/__init__.py +0 -0
  160. dsp_tools/commands/xmlupload/models/bitstream_info.py +18 -0
  161. dsp_tools/commands/xmlupload/models/formatted_text_value.py +10 -0
  162. dsp_tools/commands/xmlupload/models/ingest.py +143 -0
  163. dsp_tools/commands/xmlupload/models/input_problems.py +58 -0
  164. dsp_tools/commands/xmlupload/models/lookup_models.py +21 -0
  165. dsp_tools/commands/xmlupload/models/permission.py +45 -0
  166. dsp_tools/commands/xmlupload/models/permissions_parsed.py +93 -0
  167. dsp_tools/commands/xmlupload/models/processed/__init__.py +0 -0
  168. dsp_tools/commands/xmlupload/models/processed/file_values.py +29 -0
  169. dsp_tools/commands/xmlupload/models/processed/res.py +27 -0
  170. dsp_tools/commands/xmlupload/models/processed/values.py +101 -0
  171. dsp_tools/commands/xmlupload/models/rdf_models.py +26 -0
  172. dsp_tools/commands/xmlupload/models/upload_clients.py +14 -0
  173. dsp_tools/commands/xmlupload/models/upload_state.py +20 -0
  174. dsp_tools/commands/xmlupload/prepare_xml_input/__init__.py +0 -0
  175. dsp_tools/commands/xmlupload/prepare_xml_input/ark2iri.py +55 -0
  176. dsp_tools/commands/xmlupload/prepare_xml_input/get_processed_resources.py +252 -0
  177. dsp_tools/commands/xmlupload/prepare_xml_input/iiif_uri_validator.py +50 -0
  178. dsp_tools/commands/xmlupload/prepare_xml_input/list_client.py +120 -0
  179. dsp_tools/commands/xmlupload/prepare_xml_input/prepare_xml_input.py +67 -0
  180. dsp_tools/commands/xmlupload/prepare_xml_input/read_validate_xml_file.py +58 -0
  181. dsp_tools/commands/xmlupload/prepare_xml_input/transform_input_values.py +118 -0
  182. dsp_tools/commands/xmlupload/resource_create_client.py +25 -0
  183. dsp_tools/commands/xmlupload/richtext_id2iri.py +37 -0
  184. dsp_tools/commands/xmlupload/stash/__init__.py +0 -0
  185. dsp_tools/commands/xmlupload/stash/analyse_circular_reference_graph.py +236 -0
  186. dsp_tools/commands/xmlupload/stash/create_info_for_graph.py +53 -0
  187. dsp_tools/commands/xmlupload/stash/graph_models.py +87 -0
  188. dsp_tools/commands/xmlupload/stash/stash_circular_references.py +68 -0
  189. dsp_tools/commands/xmlupload/stash/stash_models.py +109 -0
  190. dsp_tools/commands/xmlupload/stash/upload_stashed_resptr_props.py +106 -0
  191. dsp_tools/commands/xmlupload/stash/upload_stashed_xml_texts.py +196 -0
  192. dsp_tools/commands/xmlupload/upload_config.py +76 -0
  193. dsp_tools/commands/xmlupload/write_diagnostic_info.py +27 -0
  194. dsp_tools/commands/xmlupload/xmlupload.py +516 -0
  195. dsp_tools/config/__init__.py +0 -0
  196. dsp_tools/config/logger_config.py +69 -0
  197. dsp_tools/config/warnings_config.py +32 -0
  198. dsp_tools/error/__init__.py +0 -0
  199. dsp_tools/error/custom_warnings.py +39 -0
  200. dsp_tools/error/exceptions.py +204 -0
  201. dsp_tools/error/problems.py +10 -0
  202. dsp_tools/error/xmllib_errors.py +20 -0
  203. dsp_tools/error/xmllib_warnings.py +54 -0
  204. dsp_tools/error/xmllib_warnings_util.py +159 -0
  205. dsp_tools/error/xsd_validation_error_msg.py +19 -0
  206. dsp_tools/legacy_models/__init__.py +0 -0
  207. dsp_tools/legacy_models/datetimestamp.py +81 -0
  208. dsp_tools/legacy_models/langstring.py +253 -0
  209. dsp_tools/legacy_models/projectContext.py +49 -0
  210. dsp_tools/py.typed +0 -0
  211. dsp_tools/resources/schema/data.xsd +648 -0
  212. dsp_tools/resources/schema/lists-only.json +72 -0
  213. dsp_tools/resources/schema/project.json +1258 -0
  214. dsp_tools/resources/schema/properties-only.json +874 -0
  215. dsp_tools/resources/schema/resources-only.json +140 -0
  216. dsp_tools/resources/start-stack/docker-compose.override-host.j2 +11 -0
  217. dsp_tools/resources/start-stack/docker-compose.override.yml +11 -0
  218. dsp_tools/resources/start-stack/docker-compose.yml +88 -0
  219. dsp_tools/resources/start-stack/dsp-app-config.json +45 -0
  220. dsp_tools/resources/start-stack/dsp-app-config.override-host.j2 +26 -0
  221. dsp_tools/resources/validate_data/api-shapes-resource-cardinalities.ttl +191 -0
  222. dsp_tools/resources/validate_data/api-shapes.ttl +804 -0
  223. dsp_tools/resources/validate_data/shacl-cli-image.yml +4 -0
  224. dsp_tools/resources/validate_data/validate-ontology.ttl +99 -0
  225. dsp_tools/utils/__init__.py +0 -0
  226. dsp_tools/utils/ansi_colors.py +32 -0
  227. dsp_tools/utils/data_formats/__init__.py +0 -0
  228. dsp_tools/utils/data_formats/date_util.py +166 -0
  229. dsp_tools/utils/data_formats/iri_util.py +30 -0
  230. dsp_tools/utils/data_formats/shared.py +81 -0
  231. dsp_tools/utils/data_formats/uri_util.py +76 -0
  232. dsp_tools/utils/fuseki_bloating.py +63 -0
  233. dsp_tools/utils/json_parsing.py +22 -0
  234. dsp_tools/utils/rdf_constants.py +42 -0
  235. dsp_tools/utils/rdflib_utils.py +10 -0
  236. dsp_tools/utils/replace_id_with_iri.py +66 -0
  237. dsp_tools/utils/request_utils.py +238 -0
  238. dsp_tools/utils/xml_parsing/__init__.py +0 -0
  239. dsp_tools/utils/xml_parsing/get_lookups.py +32 -0
  240. dsp_tools/utils/xml_parsing/get_parsed_resources.py +325 -0
  241. dsp_tools/utils/xml_parsing/models/__init__.py +0 -0
  242. dsp_tools/utils/xml_parsing/models/parsed_resource.py +76 -0
  243. dsp_tools/utils/xml_parsing/parse_clean_validate_xml.py +137 -0
  244. dsp_tools/xmllib/CLAUDE.md +302 -0
  245. dsp_tools/xmllib/__init__.py +49 -0
  246. dsp_tools/xmllib/general_functions.py +877 -0
  247. dsp_tools/xmllib/internal/__init__.py +0 -0
  248. dsp_tools/xmllib/internal/checkers.py +162 -0
  249. dsp_tools/xmllib/internal/circumvent_circular_imports.py +36 -0
  250. dsp_tools/xmllib/internal/constants.py +46 -0
  251. dsp_tools/xmllib/internal/input_converters.py +155 -0
  252. dsp_tools/xmllib/internal/serialise_file_value.py +57 -0
  253. dsp_tools/xmllib/internal/serialise_resource.py +177 -0
  254. dsp_tools/xmllib/internal/serialise_values.py +152 -0
  255. dsp_tools/xmllib/internal/type_aliases.py +11 -0
  256. dsp_tools/xmllib/models/__init__.py +0 -0
  257. dsp_tools/xmllib/models/config_options.py +28 -0
  258. dsp_tools/xmllib/models/date_formats.py +48 -0
  259. dsp_tools/xmllib/models/dsp_base_resources.py +1542 -0
  260. dsp_tools/xmllib/models/internal/__init__.py +0 -0
  261. dsp_tools/xmllib/models/internal/file_values.py +172 -0
  262. dsp_tools/xmllib/models/internal/geometry.py +162 -0
  263. dsp_tools/xmllib/models/internal/migration_metadata.py +55 -0
  264. dsp_tools/xmllib/models/internal/serialise_permissions.py +66 -0
  265. dsp_tools/xmllib/models/internal/values.py +342 -0
  266. dsp_tools/xmllib/models/licenses/__init__.py +0 -0
  267. dsp_tools/xmllib/models/licenses/other.py +59 -0
  268. dsp_tools/xmllib/models/licenses/recommended.py +107 -0
  269. dsp_tools/xmllib/models/permissions.py +41 -0
  270. dsp_tools/xmllib/models/res.py +1782 -0
  271. dsp_tools/xmllib/models/root.py +348 -0
  272. dsp_tools/xmllib/value_checkers.py +434 -0
  273. dsp_tools/xmllib/value_converters.py +777 -0
  274. dsp_tools-18.3.0.post13.dist-info/METADATA +90 -0
  275. dsp_tools-18.3.0.post13.dist-info/RECORD +286 -0
  276. dsp_tools-18.3.0.post13.dist-info/WHEEL +4 -0
  277. dsp_tools-18.3.0.post13.dist-info/entry_points.txt +3 -0
  278. dsp_tools-0.9.13.dist-info/LICENSE +0 -674
  279. dsp_tools-0.9.13.dist-info/METADATA +0 -144
  280. dsp_tools-0.9.13.dist-info/RECORD +0 -71
  281. dsp_tools-0.9.13.dist-info/WHEEL +0 -5
  282. dsp_tools-0.9.13.dist-info/entry_points.txt +0 -3
  283. dsp_tools-0.9.13.dist-info/top_level.txt +0 -1
  284. dsplib/models/connection.py +0 -272
  285. dsplib/models/group.py +0 -296
  286. dsplib/models/helpers.py +0 -505
  287. dsplib/models/langstring.py +0 -277
  288. dsplib/models/listnode.py +0 -578
  289. dsplib/models/model.py +0 -20
  290. dsplib/models/ontology.py +0 -448
  291. dsplib/models/permission.py +0 -112
  292. dsplib/models/project.py +0 -547
  293. dsplib/models/propertyclass.py +0 -505
  294. dsplib/models/resource.py +0 -366
  295. dsplib/models/resourceclass.py +0 -810
  296. dsplib/models/sipi.py +0 -30
  297. dsplib/models/user.py +0 -731
  298. dsplib/models/value.py +0 -1000
  299. dsplib/utils/knora-data-schema.xsd +0 -454
  300. dsplib/utils/knora-schema-lists.json +0 -83
  301. dsplib/utils/knora-schema.json +0 -434
  302. dsplib/utils/onto_commons.py +0 -24
  303. dsplib/utils/onto_create_lists.py +0 -73
  304. dsplib/utils/onto_create_ontology.py +0 -442
  305. dsplib/utils/onto_get.py +0 -58
  306. dsplib/utils/onto_validate.py +0 -33
  307. dsplib/utils/xml_upload.py +0 -539
  308. dsplib/widgets/doublepassword.py +0 -80
  309. knora/MLS-import-libraries.py +0 -84
  310. knora/dsp_tools.py +0 -96
  311. knora/dsplib/models/connection.py +0 -272
  312. knora/dsplib/models/group.py +0 -296
  313. knora/dsplib/models/helpers.py +0 -506
  314. knora/dsplib/models/langstring.py +0 -277
  315. knora/dsplib/models/listnode.py +0 -578
  316. knora/dsplib/models/model.py +0 -20
  317. knora/dsplib/models/ontology.py +0 -448
  318. knora/dsplib/models/permission.py +0 -112
  319. knora/dsplib/models/project.py +0 -583
  320. knora/dsplib/models/propertyclass.py +0 -505
  321. knora/dsplib/models/resource.py +0 -416
  322. knora/dsplib/models/resourceclass.py +0 -811
  323. knora/dsplib/models/sipi.py +0 -35
  324. knora/dsplib/models/user.py +0 -731
  325. knora/dsplib/models/value.py +0 -1000
  326. knora/dsplib/utils/knora-data-schema.xsd +0 -464
  327. knora/dsplib/utils/knora-schema-lists.json +0 -83
  328. knora/dsplib/utils/knora-schema.json +0 -444
  329. knora/dsplib/utils/onto_commons.py +0 -24
  330. knora/dsplib/utils/onto_create_lists.py +0 -73
  331. knora/dsplib/utils/onto_create_ontology.py +0 -451
  332. knora/dsplib/utils/onto_get.py +0 -58
  333. knora/dsplib/utils/onto_validate.py +0 -33
  334. knora/dsplib/utils/xml_upload.py +0 -540
  335. knora/dsplib/widgets/doublepassword.py +0 -80
  336. knora/knora.py +0 -2108
  337. knora/test.py +0 -99
  338. knora/testit.py +0 -76
  339. knora/xml2knora.py +0 -633
  340. {dsplib → dsp_tools/cli}/__init__.py +0 -0
  341. {dsplib/models → dsp_tools/clients}/__init__.py +0 -0
  342. {dsplib/utils → dsp_tools/commands}/__init__.py +0 -0
  343. {dsplib/widgets → dsp_tools/commands/create}/__init__.py +0 -0
  344. {knora → dsp_tools/commands/create/create_on_server}/__init__.py +0 -0
  345. {knora/dsplib → dsp_tools/commands/create/models}/__init__.py +0 -0
  346. {knora/dsplib/models → dsp_tools/commands/create/parsing}/__init__.py +0 -0
  347. {knora/dsplib/utils → dsp_tools/commands/create/serialisation}/__init__.py +0 -0
  348. {knora/dsplib/widgets → dsp_tools/commands/excel2json}/__init__.py +0 -0
@@ -0,0 +1,119 @@
1
+ from http import HTTPStatus
2
+ from typing import Any
3
+
4
+ import rustworkx as rx
5
+ from loguru import logger
6
+ from rdflib import Literal
7
+ from rdflib import URIRef
8
+ from tqdm import tqdm
9
+
10
+ from dsp_tools.clients.ontology_clients import OntologyCreateClient
11
+ from dsp_tools.commands.create.create_on_server.onto_utils import get_modification_date_onto_lookup
12
+ from dsp_tools.commands.create.create_on_server.onto_utils import should_retry_request
13
+ from dsp_tools.commands.create.create_on_server.onto_utils import sort_for_upload
14
+ from dsp_tools.commands.create.models.create_problems import CollectedProblems
15
+ from dsp_tools.commands.create.models.create_problems import CreateProblem
16
+ from dsp_tools.commands.create.models.create_problems import UploadProblem
17
+ from dsp_tools.commands.create.models.create_problems import UploadProblemType
18
+ from dsp_tools.commands.create.models.parsed_ontology import ParsedProperty
19
+ from dsp_tools.commands.create.models.server_project_info import CreatedIriCollection
20
+ from dsp_tools.commands.create.models.server_project_info import ListNameToIriLookup
21
+ from dsp_tools.commands.create.models.server_project_info import OntoLastModDateLookup
22
+ from dsp_tools.commands.create.models.server_project_info import ProjectIriLookup
23
+ from dsp_tools.commands.create.serialisation.ontology import serialise_property_graph_for_request
24
+
25
+
26
+ def create_all_properties(
27
+ properties: list[ParsedProperty],
28
+ project_iri_lookup: ProjectIriLookup,
29
+ created_iris: CreatedIriCollection,
30
+ list_lookup: ListNameToIriLookup,
31
+ client: OntologyCreateClient,
32
+ ) -> tuple[CreatedIriCollection, CollectedProblems | None]:
33
+ upload_order = _get_property_create_order(properties)
34
+ logger.debug(f"Property creation order: {upload_order}")
35
+ prop_lookup = {p.name: p for p in properties}
36
+ all_problems: list[CreateProblem] = []
37
+ onto_lookup = get_modification_date_onto_lookup(project_iri_lookup, client)
38
+ progress_bar = tqdm(upload_order, desc=" Creating properties", dynamic_ncols=True)
39
+ logger.debug("Starting property creation")
40
+ for p in progress_bar:
41
+ prop = prop_lookup[p]
42
+ if previous_blocker := _is_property_blocked(prop, created_iris):
43
+ all_problems.append(previous_blocker)
44
+ created_iris.failed_properties.add(prop.name)
45
+ else:
46
+ list_iri = None
47
+ if prop.node_name is not None:
48
+ if not (found := list_lookup.get_iri(prop.node_name)):
49
+ all_problems.append(UploadProblem(prop.name, UploadProblemType.PROPERTY_LIST_NOT_FOUND))
50
+ continue
51
+ else:
52
+ list_iri = Literal(f"hlist=<{found}>")
53
+ create_result = _create_one_property(prop, list_iri, onto_lookup, client)
54
+ if isinstance(create_result, Literal):
55
+ onto_lookup.update_last_mod_date(prop.onto_iri, create_result)
56
+ created_iris.created_properties.add(prop.name)
57
+ else:
58
+ all_problems.append(create_result)
59
+ created_iris.failed_properties.add(prop.name)
60
+ upload_problems = None
61
+ if all_problems:
62
+ upload_problems = CollectedProblems(
63
+ " While creating properties the following problems occurred:", all_problems
64
+ )
65
+ return created_iris, upload_problems
66
+
67
+
68
+ def _is_property_blocked(prop: ParsedProperty, created_iris: CreatedIriCollection) -> CreateProblem | None:
69
+ if created_iris.any_properties_failed(set(prop.supers)):
70
+ return UploadProblem(prop.name, UploadProblemType.PROPERTY_SUPER_FAILED)
71
+ if prop.object:
72
+ if created_iris.any_classes_failed({str(prop.object)}):
73
+ return UploadProblem(prop.name, UploadProblemType.PROPERTY_REFERENCES_FAILED_CLASS)
74
+ if prop.subject:
75
+ if created_iris.any_classes_failed({prop.subject}):
76
+ return UploadProblem(prop.name, UploadProblemType.PROPERTY_REFERENCES_FAILED_CLASS)
77
+ return None
78
+
79
+
80
+ def _get_property_create_order(properties: list[ParsedProperty]) -> list[str]:
81
+ logger.debug("Creating property upload order.")
82
+ graph, node_to_iri = _make_graph_to_sort(properties)
83
+ return sort_for_upload(graph, node_to_iri)
84
+
85
+
86
+ def _make_graph_to_sort(properties: list[ParsedProperty]) -> tuple[rx.PyDiGraph, dict[int, str]]:
87
+ graph: rx.PyDiGraph[Any, Any] = rx.PyDiGraph()
88
+ prop_iris = [x.name for x in properties]
89
+ node_indices = list(graph.add_nodes_from(prop_iris))
90
+ iri_to_node = dict(zip(prop_iris, node_indices))
91
+ node_to_iri = dict(zip(node_indices, prop_iris))
92
+ for i, p in enumerate(properties):
93
+ for super_prop in p.supers:
94
+ if super_prop in prop_iris:
95
+ graph.add_edge(iri_to_node[p.name], iri_to_node[super_prop], i)
96
+ return graph, node_to_iri
97
+
98
+
99
+ def _create_one_property(
100
+ prop: ParsedProperty,
101
+ list_iri: Literal | None,
102
+ onto_lookup: OntoLastModDateLookup,
103
+ client: OntologyCreateClient,
104
+ ) -> Literal | CreateProblem:
105
+ prop_serialised = serialise_property_graph_for_request(
106
+ prop, list_iri, URIRef(prop.onto_iri), onto_lookup.get_last_mod_date(prop.onto_iri)
107
+ )
108
+ request_result = client.post_new_property(prop_serialised)
109
+ if isinstance(request_result, Literal):
110
+ return request_result
111
+ if should_retry_request(request_result):
112
+ new_mod_date = client.get_last_modification_date(onto_lookup.project_iri, prop.onto_iri)
113
+ prop_serialised = serialise_property_graph_for_request(prop, list_iri, URIRef(prop.onto_iri), new_mod_date)
114
+ request_result = client.post_new_property(prop_serialised)
115
+ if isinstance(request_result, Literal):
116
+ return request_result
117
+ if request_result.status_code == HTTPStatus.BAD_REQUEST:
118
+ return UploadProblem(prop.name, request_result.text)
119
+ return UploadProblem(prop.name, UploadProblemType.PROPERTY_COULD_NOT_BE_CREATED)
@@ -0,0 +1,29 @@
1
+ from dsp_tools.error.exceptions import InternalError
2
+ from dsp_tools.error.exceptions import UserError
3
+
4
+ #######
5
+ # Input Validation Errors
6
+
7
+
8
+ class ProjectJsonSchemaValidationError(UserError):
9
+ def __init__(self, detail_msg: str) -> None:
10
+ super().__init__(detail_msg)
11
+
12
+
13
+ class CircularOntologyDependency(UserError):
14
+ """Class if a circular dependency was found in the ontology."""
15
+
16
+ def __init__(self, dependency_location: str) -> None:
17
+ msg = (
18
+ f"A circular dependency of {dependency_location} was found in your project. "
19
+ f"It is not possible for an ontology to have circular dependencies."
20
+ )
21
+ super().__init__(msg)
22
+
23
+
24
+ #######
25
+ # Internal Errors
26
+
27
+
28
+ class UnableToCreateProjectError(InternalError):
29
+ """Class if a project cannot be created."""
@@ -0,0 +1,66 @@
1
+ from pathlib import Path
2
+
3
+ from loguru import logger
4
+
5
+ from dsp_tools.cli.args import ServerCredentials
6
+ from dsp_tools.clients.authentication_client_live import AuthenticationClientLive
7
+ from dsp_tools.clients.project_client_live import ProjectClientLive
8
+ from dsp_tools.commands.create.communicate_problems import print_all_problem_collections
9
+ from dsp_tools.commands.create.communicate_problems import print_problem_collection
10
+ from dsp_tools.commands.create.create_on_server.lists import create_lists
11
+ from dsp_tools.commands.create.models.parsed_project import ParsedList
12
+ from dsp_tools.commands.create.models.parsed_project import ParsedProject
13
+ from dsp_tools.commands.create.models.parsed_project import ParsedProjectMetadata
14
+ from dsp_tools.commands.create.project_validate import parse_and_validate_project
15
+ from dsp_tools.error.exceptions import InternalError
16
+ from dsp_tools.error.exceptions import ProjectNotFoundError
17
+ from dsp_tools.utils.ansi_colors import BACKGROUND_BOLD_YELLOW
18
+ from dsp_tools.utils.ansi_colors import RESET_TO_DEFAULT
19
+
20
+
21
+ def create_lists_only(project_file: Path, creds: ServerCredentials) -> bool:
22
+ parsing_result = parse_and_validate_project(project_file, creds.server)
23
+ match parsing_result:
24
+ case ParsedProject():
25
+ return _handle_parsed_project_result(parsing_result, creds)
26
+ case list():
27
+ print_all_problem_collections(parsing_result)
28
+ return False
29
+ case _:
30
+ raise InternalError("Unreachable result of project parsing.")
31
+
32
+
33
+ def _handle_parsed_project_result(parsed_project: ParsedProject, creds: ServerCredentials) -> bool:
34
+ list_result = parsed_project.lists
35
+ match list_result:
36
+ case list():
37
+ return _execute_list_creation(parsed_project.project_metadata, list_result, creds)
38
+ case None:
39
+ msg = "Your file did not contain any lists, therefore no lists were created on the server."
40
+ logger.info(msg)
41
+ print(BACKGROUND_BOLD_YELLOW + msg + RESET_TO_DEFAULT)
42
+ return False
43
+ case _:
44
+ raise InternalError("Unreachable result of project parsing.")
45
+
46
+
47
+ def _execute_list_creation(
48
+ project_metadata: ParsedProjectMetadata, parsed_lists: list[ParsedList], creds: ServerCredentials
49
+ ) -> bool:
50
+ auth = AuthenticationClientLive(creds.server, creds.user, creds.password)
51
+ project_info = ProjectClientLive(creds.server, auth)
52
+ try:
53
+ project_iri = project_info.get_project_iri(project_metadata.shortcode)
54
+ except ProjectNotFoundError:
55
+ # we want a more precise error message
56
+ raise ProjectNotFoundError(
57
+ f"This commands adds lists to an existing project. "
58
+ f"The project with the shortcode {project_metadata.shortcode} does not exist on this server. "
59
+ f"If you wish to create an entire project, please use the `create` command without the flag."
60
+ ) from None
61
+
62
+ _, problems = create_lists(parsed_lists, project_metadata.shortcode, auth, project_iri)
63
+ if problems:
64
+ print_problem_collection(problems)
65
+ return False
66
+ return True
@@ -0,0 +1,87 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from enum import StrEnum
5
+
6
+
7
+ @dataclass
8
+ class CollectedProblems:
9
+ header: str
10
+ problems: list[CreateProblem]
11
+
12
+
13
+ @dataclass
14
+ class UserInformation:
15
+ focus_object: str
16
+ msg: UserInformationMessage
17
+
18
+
19
+ class UserInformationMessage(StrEnum):
20
+ LIST_EXISTS_ON_SERVER = "The list already exists on the server, therefore it is skipped entirely."
21
+
22
+
23
+ @dataclass
24
+ class CreateProblem:
25
+ problematic_object: str
26
+ problem: ProblemType | str
27
+
28
+
29
+ @dataclass
30
+ class InputProblem(CreateProblem):
31
+ problem: InputProblemType | str
32
+
33
+
34
+ @dataclass
35
+ class UploadProblem(CreateProblem):
36
+ problem: UploadProblemType | str
37
+
38
+
39
+ class ProblemType(StrEnum): ...
40
+
41
+
42
+ class InputProblemType(ProblemType):
43
+ USER_PASSWORD_NOT_SET = (
44
+ "This user cannot be created as no password is specified and no default password is saved in a .env file."
45
+ )
46
+ DUPLICATE_LIST_NAME = "You have lists in your project with the same name, this is not permitted."
47
+ PREFIX_COULD_NOT_BE_RESOLVED = (
48
+ "The prefix used is not defined in the 'prefix' section of the file, "
49
+ "nor does it belong to one of the project ontologies."
50
+ )
51
+ INVALID_PERMISSIONS_OVERRULE = (
52
+ "This class cannot be used in limited_view permissions "
53
+ "because it is not a subclass of StillImageRepresentation."
54
+ )
55
+ UNDEFINED_REFERENCE = "Reference not defined in the project."
56
+ UNDEFINED_SUPER_PROPERTY = "This property is derived from an invalid super-property."
57
+ UNDEFINED_SUPER_CLASS = "This resource is derived from an invalid super-class."
58
+ UNDEFINED_PROPERTY_IN_CARDINALITY = "This cardinality references a property that does not exist."
59
+ DUPLICATE_CLASS_NAME = "This class name appears multiple times in the same ontology."
60
+ DUPLICATE_PROPERTY_NAME = "This property name appears multiple times in the same ontology."
61
+ MIN_CARDINALITY_ONE_WITH_CIRCLE = (
62
+ "This property is part of a circular reference and must have cardinality 0-1 or 0-n."
63
+ )
64
+
65
+
66
+ class UploadProblemType(ProblemType):
67
+ # Groups
68
+ GROUP_COULD_NOT_BE_CREATED = "The group could not be created."
69
+ # Users
70
+ USER_COULD_NOT_BE_CREATED = "The user could not be created."
71
+ USER_COULD_NOT_BE_ADDED_TO_GROUP = "The user could not be added to some or all of the custom groups."
72
+ USER_GROUPS_NOT_FOUND = "The user could not be added to the groups because they do not exist on the server."
73
+ PROJECT_MEMBERSHIP_COULD_NOT_BE_ADDED = "The user could not be added as project member."
74
+ PROJECT_ADMIN_COULD_NOT_BE_ADDED = "The user could not be added as project admin."
75
+ # Lists
76
+ LIST_COULD_NOT_BE_CREATED = "The list could not be created on the server."
77
+ LIST_NODE_COULD_NOT_BE_CREATED = "The list node could not be created on the server."
78
+ # Ontology
79
+ CARDINALITY_COULD_NOT_BE_ADDED = "The cardinality could not be added."
80
+ CARDINALITY_PROPERTY_NOT_FOUND = "The referenced property does not exist on the server."
81
+ PROPERTY_COULD_NOT_BE_CREATED = "The property could not be created."
82
+ PROPERTY_LIST_NOT_FOUND = "The property cannot be created, because the list it references does not exist."
83
+ PROPERTY_SUPER_FAILED = "The property cannot be created, because its super-property was not created."
84
+ PROPERTY_REFERENCES_FAILED_CLASS = "The property cannot be created, because a class it references was not created."
85
+ CLASS_COULD_NOT_BE_CREATED = "The class could not be created."
86
+ CLASS_SUPER_FAILED = "The class cannot be created, because its super-class was not created."
87
+ ONTOLOGY_COULD_NOT_BE_CREATED = "The ontology cannot be created."
@@ -0,0 +1,88 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from enum import Enum
5
+ from enum import StrEnum
6
+ from enum import auto
7
+
8
+ from dsp_tools.utils.rdf_constants import KNORA_API_PREFIX
9
+ from dsp_tools.utils.rdf_constants import SALSAH_GUI_PREFIX
10
+
11
+
12
+ @dataclass
13
+ class ParsedOntology:
14
+ name: str
15
+ label: str
16
+ comment: str | None
17
+ classes: list[ParsedClass]
18
+ properties: list[ParsedProperty]
19
+ cardinalities: list[ParsedClassCardinalities]
20
+
21
+
22
+ @dataclass
23
+ class ParsedClass:
24
+ name: str
25
+ labels: dict[str, str]
26
+ comments: dict[str, str] | None
27
+ supers: list[str]
28
+ onto_iri: str
29
+
30
+
31
+ @dataclass
32
+ class ParsedProperty:
33
+ name: str
34
+ labels: dict[str, str]
35
+ comments: dict[str, str] | None
36
+ supers: list[str]
37
+ object: KnoraObjectType | str
38
+ subject: str | None
39
+ gui_element: GuiElement
40
+ node_name: str | None
41
+ onto_iri: str
42
+
43
+
44
+ class KnoraObjectType(StrEnum):
45
+ BOOLEAN = f"{KNORA_API_PREFIX}BooleanValue"
46
+ COLOR = f"{KNORA_API_PREFIX}ColorValue"
47
+ DATE = f"{KNORA_API_PREFIX}DateValue"
48
+ DECIMAL = f"{KNORA_API_PREFIX}DecimalValue"
49
+ GEONAME = f"{KNORA_API_PREFIX}GeonameValue"
50
+ INT = f"{KNORA_API_PREFIX}IntValue"
51
+ LIST = f"{KNORA_API_PREFIX}ListValue"
52
+ TEXT = f"{KNORA_API_PREFIX}TextValue"
53
+ TIME = f"{KNORA_API_PREFIX}TimeValue"
54
+ URI = f"{KNORA_API_PREFIX}UriValue"
55
+
56
+
57
+ class GuiElement(StrEnum):
58
+ CHECKBOX = f"{SALSAH_GUI_PREFIX}Checkbox"
59
+ COLORPICKER = f"{SALSAH_GUI_PREFIX}Colorpicker"
60
+ DATE = f"{SALSAH_GUI_PREFIX}Date"
61
+ SPINBOX = f"{SALSAH_GUI_PREFIX}Spinbox"
62
+ GEONAMES = f"{SALSAH_GUI_PREFIX}Geonames"
63
+ LIST = f"{SALSAH_GUI_PREFIX}List"
64
+ SIMPLETEXT = f"{SALSAH_GUI_PREFIX}SimpleText"
65
+ TEXTAREA = f"{SALSAH_GUI_PREFIX}Textarea"
66
+ RICHTEXT = f"{SALSAH_GUI_PREFIX}Richtext"
67
+ SEARCHBOX = f"{SALSAH_GUI_PREFIX}Searchbox"
68
+ TIME_STAMP = f"{SALSAH_GUI_PREFIX}TimeStamp"
69
+
70
+
71
+ @dataclass
72
+ class ParsedClassCardinalities:
73
+ class_iri: str
74
+ cards: list[ParsedPropertyCardinality]
75
+
76
+
77
+ @dataclass
78
+ class ParsedPropertyCardinality:
79
+ propname: str
80
+ cardinality: Cardinality
81
+ gui_order: int | None
82
+
83
+
84
+ class Cardinality(Enum):
85
+ C_0_1 = auto()
86
+ C_1 = auto()
87
+ C_0_N = auto()
88
+ C_1_N = auto()
@@ -0,0 +1,81 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+
5
+ from dsp_tools.commands.create.models.parsed_ontology import ParsedOntology
6
+
7
+
8
+ @dataclass
9
+ class ParsedProject:
10
+ prefixes: dict[str, str]
11
+ project_metadata: ParsedProjectMetadata
12
+ permissions: ParsedPermissions
13
+ groups: list[ParsedGroup]
14
+ users: list[ParsedUser]
15
+ user_memberships: list[ParsedUserMemberShipInfo]
16
+ lists: list[ParsedList]
17
+ ontologies: list[ParsedOntology]
18
+
19
+
20
+ @dataclass
21
+ class ParsedProjectMetadata:
22
+ shortcode: str
23
+ shortname: str
24
+ longname: str
25
+ descriptions: dict[str, str]
26
+ keywords: list[str]
27
+ enabled_licenses: list[str]
28
+
29
+
30
+ @dataclass
31
+ class ParsedPermissions:
32
+ default_permissions: str
33
+ default_permissions_overrule: dict[str, str | list[str]] | None
34
+
35
+
36
+ @dataclass
37
+ class ParsedGroup:
38
+ name: str
39
+ descriptions: list[ParsedGroupDescription]
40
+
41
+
42
+ @dataclass
43
+ class ParsedGroupDescription:
44
+ lang: str
45
+ text: str
46
+
47
+
48
+ @dataclass
49
+ class ParsedUser:
50
+ username: str
51
+ email: str
52
+ given_name: str
53
+ family_name: str
54
+ password: str
55
+ lang: str
56
+
57
+
58
+ @dataclass
59
+ class ParsedUserMemberShipInfo:
60
+ username: str
61
+ is_admin: bool
62
+ groups: list[str]
63
+
64
+
65
+ @dataclass
66
+ class ParsedList:
67
+ list_info: ParsedNodeInfo
68
+ children: list[ParsedListNode]
69
+
70
+
71
+ @dataclass
72
+ class ParsedNodeInfo:
73
+ name: str
74
+ labels: dict[str, str]
75
+ comments: dict[str, str] | None
76
+
77
+
78
+ @dataclass
79
+ class ParsedListNode:
80
+ node_info: ParsedNodeInfo
81
+ children: list[ParsedListNode]
@@ -0,0 +1,12 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+
5
+ from rdflib import Literal
6
+ from rdflib import URIRef
7
+
8
+
9
+ @dataclass
10
+ class RdfCardinalityRestriction:
11
+ owl_property: URIRef
12
+ cardinality_value: Literal
@@ -0,0 +1,100 @@
1
+ from dataclasses import dataclass
2
+ from dataclasses import field
3
+
4
+ from rdflib import Literal
5
+ from rdflib import URIRef
6
+
7
+ from dsp_tools.error.exceptions import InternalError
8
+ from dsp_tools.utils.rdf_constants import KNORA_API_PREFIX
9
+
10
+
11
+ @dataclass
12
+ class ProjectIriLookup:
13
+ project_iri: str
14
+ onto_iris: dict[str, str] = field(default_factory=dict)
15
+
16
+ def add_onto(self, name: str, iri: str) -> None:
17
+ self.onto_iris[name] = iri
18
+
19
+ def does_onto_exist(self, name: str) -> bool:
20
+ return bool(self.onto_iris.get(name))
21
+
22
+
23
+ @dataclass
24
+ class OntoLastModDateLookup:
25
+ project_iri: str
26
+ onto_iris: dict[str, URIRef]
27
+ iri_to_last_modification_date: dict[str, Literal] = field(default_factory=dict)
28
+
29
+ def get_last_mod_date(self, iri: str) -> Literal:
30
+ return self.iri_to_last_modification_date[iri]
31
+
32
+ def update_last_mod_date(self, iri: str, last_modification_date: Literal) -> None:
33
+ self.iri_to_last_modification_date[iri] = last_modification_date
34
+
35
+
36
+ @dataclass
37
+ class GroupNameToIriLookup:
38
+ name2iri: dict[str, str]
39
+ shortname: str
40
+
41
+ def check_exists(self, name: str) -> bool:
42
+ return name in self.name2iri.keys()
43
+
44
+ def add_iri(self, name: str, iri: str) -> None:
45
+ if self.check_exists(name):
46
+ raise InternalError(f"Group with the name '{name}' already exists in the lookup.")
47
+ self.name2iri[name] = iri
48
+ self.name2iri[f"{self.shortname}:{name}"] = iri
49
+
50
+ def get_iri(self, name: str) -> str | None:
51
+ return self.name2iri.get(name)
52
+
53
+
54
+ @dataclass
55
+ class UserNameToIriLookup:
56
+ name2iri: dict[str, str] = field(default_factory=dict)
57
+
58
+ def check_exists(self, name: str) -> bool:
59
+ return name in self.name2iri.keys()
60
+
61
+ def add_iri(self, name: str, iri: str) -> None:
62
+ if self.check_exists(name):
63
+ raise InternalError(f"User with the name '{name}' already exists in the lookup.")
64
+ self.name2iri[name] = iri
65
+
66
+ def get_iri(self, name: str) -> str | None:
67
+ return self.name2iri.get(name)
68
+
69
+
70
+ @dataclass
71
+ class CreatedIriCollection:
72
+ created_classes: set[str] = field(default_factory=set)
73
+ created_properties: set[str] = field(default_factory=set)
74
+ failed_classes: set[str] = field(default_factory=set)
75
+ failed_properties: set[str] = field(default_factory=set)
76
+
77
+ def __post_init__(self) -> None:
78
+ self.created_properties.update({f"{KNORA_API_PREFIX}seqnum", f"{KNORA_API_PREFIX}isPartOf"})
79
+
80
+ def any_properties_failed(self, props: set[str]) -> bool:
81
+ return bool(props.intersection(self.failed_properties))
82
+
83
+ def any_classes_failed(self, classes: set[str]) -> bool:
84
+ return bool(classes.intersection(self.failed_classes))
85
+
86
+
87
+ @dataclass
88
+ class ListNameToIriLookup:
89
+ name2iri: dict[str, str]
90
+
91
+ def check_list_exists(self, name: str) -> bool:
92
+ return name in self.name2iri.keys()
93
+
94
+ def add_iri(self, name: str, iri: str) -> None:
95
+ if self.check_list_exists(name):
96
+ raise InternalError(f"List with the name '{name}' already exists in the lookup.")
97
+ self.name2iri[name] = iri
98
+
99
+ def get_iri(self, name: str) -> str | None:
100
+ return self.name2iri.get(name)
@@ -0,0 +1,45 @@
1
+ from collections import Counter
2
+ from typing import Any
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_project import ParsedList
9
+ from dsp_tools.commands.create.models.parsed_project import ParsedListNode
10
+ from dsp_tools.commands.create.models.parsed_project import ParsedNodeInfo
11
+
12
+
13
+ def parse_list_section(lists: list[dict[str, Any]]) -> list[ParsedList] | CollectedProblems:
14
+ list_section = [_parse_one_list(one_list) for one_list in lists]
15
+ list_names = [parsed_list.list_info.name for parsed_list in list_section]
16
+ duplicates = {name for name, count in Counter(list_names).items() if count > 1}
17
+ if duplicates:
18
+ problems: list[CreateProblem] = [
19
+ InputProblem(problematic_object=name, problem=InputProblemType.DUPLICATE_LIST_NAME) for name in duplicates
20
+ ]
21
+ return CollectedProblems(header="The following problems were found in the list section:", problems=problems)
22
+ return list_section
23
+
24
+
25
+ def _parse_one_list(one_list: dict[str, Any]) -> ParsedList:
26
+ list_info = _parse_node_info(one_list)
27
+ children = _parse_nodes_and_children(one_list["nodes"]) if "nodes" in one_list else []
28
+ return ParsedList(list_info=list_info, children=children)
29
+
30
+
31
+ def _parse_node_info(one_node: dict[str, Any]) -> ParsedNodeInfo:
32
+ return ParsedNodeInfo(
33
+ name=one_node["name"],
34
+ labels=one_node["labels"],
35
+ comments=one_node.get("comments"),
36
+ )
37
+
38
+
39
+ def _parse_nodes_and_children(list_nodes: list[dict[str, Any]]) -> list[ParsedListNode]:
40
+ parsed_nodes = []
41
+ for node in list_nodes:
42
+ node_info = _parse_node_info(node)
43
+ children = _parse_nodes_and_children(node["nodes"]) if "nodes" in node else []
44
+ parsed_nodes.append(ParsedListNode(node_info=node_info, children=children))
45
+ return parsed_nodes