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,49 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from typing import Any
5
+ from typing import Protocol
6
+
7
+ from dsp_tools.clients.authentication_client import AuthenticationClient
8
+
9
+
10
+ @dataclass
11
+ class OneList:
12
+ list_iri: str
13
+ list_name: str
14
+ nodes: list[OneNode]
15
+
16
+ def hlist(self) -> str:
17
+ return f'"hlist=<{self.list_iri}>"'
18
+
19
+
20
+ @dataclass
21
+ class OneNode:
22
+ name: str
23
+ iri: str
24
+
25
+
26
+ @dataclass
27
+ class ListGetClient(Protocol):
28
+ """Client to request and reformat the lists of a project."""
29
+
30
+ api_url: str
31
+ shortcode: str
32
+
33
+ def get_all_lists_and_nodes(self) -> list[OneList]:
34
+ """Get all lists and its nodes from a project."""
35
+
36
+ def get_all_list_iris_and_names(self) -> dict[str, str]:
37
+ """Get all list names and IRIs"""
38
+
39
+
40
+ @dataclass
41
+ class ListCreateClient(Protocol):
42
+ api_url: str
43
+ auth: AuthenticationClient
44
+
45
+ def create_new_list(self, list_info: dict[str, Any]) -> str | None:
46
+ """Create a new list."""
47
+
48
+ def add_list_node(self, node_info: dict[str, Any], parent_iri: str) -> str | None:
49
+ """Add a list node to an existing list."""
@@ -0,0 +1,166 @@
1
+ from dataclasses import dataclass
2
+ from http import HTTPStatus
3
+ from typing import Any
4
+ from typing import cast
5
+ from urllib.parse import quote_plus
6
+
7
+ import requests
8
+ from requests import RequestException
9
+ from requests import Response
10
+
11
+ from dsp_tools.clients.authentication_client import AuthenticationClient
12
+ from dsp_tools.clients.list_client import ListCreateClient
13
+ from dsp_tools.clients.list_client import ListGetClient
14
+ from dsp_tools.clients.list_client import OneList
15
+ from dsp_tools.clients.list_client import OneNode
16
+ from dsp_tools.error.exceptions import BadCredentialsError
17
+ from dsp_tools.error.exceptions import FatalNonOkApiResponseCode
18
+ from dsp_tools.utils.request_utils import RequestParameters
19
+ from dsp_tools.utils.request_utils import log_and_raise_request_exception
20
+ from dsp_tools.utils.request_utils import log_and_warn_unexpected_non_ok_response
21
+ from dsp_tools.utils.request_utils import log_request
22
+ from dsp_tools.utils.request_utils import log_response
23
+
24
+ TIMEOUT = 60
25
+
26
+
27
+ @dataclass
28
+ class ListGetClientLive(ListGetClient):
29
+ """Client to request and reformat the lists of a project."""
30
+
31
+ api_url: str
32
+ shortcode: str
33
+
34
+ def get_all_lists_and_nodes(self) -> list[OneList]:
35
+ list_json = self._get_all_list_iris()
36
+ all_iris = self._extract_list_iris(list_json)
37
+ all_lists = [self._get_one_list(iri) for iri in all_iris]
38
+ return [self._reformat_one_list(lst) for lst in all_lists]
39
+
40
+ def get_all_list_iris_and_names(self) -> dict[str, str]:
41
+ response_json = self._get_all_list_iris()
42
+ iris = self._extract_list_iris(response_json)
43
+ names = [x["name"] for x in response_json["lists"]]
44
+ return dict(zip(names, iris))
45
+
46
+ def _get_all_list_iris(self) -> dict[str, Any]:
47
+ url = f"{self.api_url}/admin/lists?projectShortcode={self.shortcode}"
48
+ timeout = 10
49
+ log_request(RequestParameters("GET", url, timeout))
50
+ try:
51
+ response = requests.get(url=url, timeout=timeout)
52
+ except RequestException as err:
53
+ log_and_raise_request_exception(err)
54
+
55
+ log_response(response)
56
+ if response.ok:
57
+ json_response = cast(dict[str, Any], response.json())
58
+ return json_response
59
+ raise FatalNonOkApiResponseCode(url, response.status_code, response.text)
60
+
61
+ def _extract_list_iris(self, response_json: dict[str, Any]) -> list[str]:
62
+ return [x["id"] for x in response_json["lists"]]
63
+
64
+ def _get_one_list(self, list_iri: str) -> dict[str, Any]:
65
+ encoded_list_iri = quote_plus(list_iri)
66
+ url = f"{self.api_url}/admin/lists/{encoded_list_iri}"
67
+ timeout = 30
68
+ log_request(RequestParameters("GET", url, timeout))
69
+ try:
70
+ response = requests.get(url=url, timeout=timeout)
71
+ except RequestException as err:
72
+ log_and_raise_request_exception(err)
73
+
74
+ log_response(response, include_response_content=False)
75
+ if response.ok:
76
+ response_json = cast(dict[str, Any], response.json())
77
+ return response_json
78
+ raise FatalNonOkApiResponseCode(url, response.status_code, response.text)
79
+
80
+ def _reformat_one_list(self, response_json: dict[str, Any]) -> OneList:
81
+ list_name = response_json["list"]["listinfo"]["name"]
82
+ list_id = response_json["list"]["listinfo"]["id"]
83
+ nodes = response_json["list"]["children"]
84
+ all_nodes = []
85
+ for child in nodes:
86
+ all_nodes.append(OneNode(child["name"], child["id"]))
87
+ if node_child := child.get("children"):
88
+ self._reformat_children(node_child, all_nodes)
89
+ return OneList(list_iri=list_id, list_name=list_name, nodes=all_nodes)
90
+
91
+ def _reformat_children(self, list_child: list[dict[str, Any]], current_nodes: list[OneNode]) -> None:
92
+ for child in list_child:
93
+ current_nodes.append(OneNode(child["name"], child["id"]))
94
+ if grand_child := child.get("children"):
95
+ self._reformat_children(grand_child, current_nodes)
96
+
97
+
98
+ @dataclass
99
+ class ListCreateClientLive(ListCreateClient):
100
+ api_url: str
101
+ project_iri: str
102
+ auth: AuthenticationClient
103
+
104
+ def create_new_list(self, list_info: dict[str, Any]) -> str | None:
105
+ url = f"{self.api_url}/admin/lists"
106
+ headers = self._get_request_header()
107
+ try:
108
+ response = _post_and_log_request(url, list_info, headers)
109
+ except RequestException as err:
110
+ log_and_raise_request_exception(err)
111
+
112
+ if response.ok:
113
+ result = response.json()
114
+ list_iri = cast(str, result["list"]["listinfo"]["id"])
115
+ return list_iri
116
+ if response.status_code == HTTPStatus.FORBIDDEN:
117
+ raise BadCredentialsError(
118
+ "Only a SystemAdmin or ProjectAdmin can create lists. "
119
+ "Your permissions are insufficient for this action."
120
+ )
121
+ log_and_warn_unexpected_non_ok_response(response.status_code, response.text)
122
+ return None
123
+
124
+ def add_list_node(self, node_info: dict[str, Any], parent_iri: str) -> str | None:
125
+ encoded_parent_iri = quote_plus(parent_iri)
126
+ url = f"{self.api_url}/admin/lists/{encoded_parent_iri}"
127
+ headers = self._get_request_header()
128
+ try:
129
+ response = _post_and_log_request(url, node_info, headers)
130
+ except RequestException as err:
131
+ log_and_raise_request_exception(err)
132
+
133
+ if response.ok:
134
+ result = response.json()
135
+ node_iri = cast(str, result["nodeinfo"]["id"])
136
+ return node_iri
137
+ if response.status_code == HTTPStatus.FORBIDDEN:
138
+ raise BadCredentialsError(
139
+ "Only a SystemAdmin or ProjectAdmin can add nodes to lists. "
140
+ "Your permissions are insufficient for this action."
141
+ )
142
+ log_and_warn_unexpected_non_ok_response(response.status_code, response.text)
143
+ return None
144
+
145
+ def _get_request_header(self) -> dict[str, str]:
146
+ return {
147
+ "Content-Type": "application/json",
148
+ "Authorization": f"Bearer {self.auth.get_token()}",
149
+ }
150
+
151
+
152
+ def _post_and_log_request(
153
+ url: str,
154
+ data: dict[str, Any],
155
+ headers: dict[str, str] | None = None,
156
+ ) -> Response:
157
+ params = RequestParameters("POST", url, TIMEOUT, data, headers)
158
+ log_request(params)
159
+ response = requests.post(
160
+ url=params.url,
161
+ headers=params.headers,
162
+ data=params.data_serialized,
163
+ timeout=params.timeout,
164
+ )
165
+ log_response(response)
166
+ return response
@@ -0,0 +1,24 @@
1
+ from dataclasses import dataclass
2
+ from enum import Enum
3
+ from enum import auto
4
+ from typing import Protocol
5
+
6
+ from dsp_tools.clients.authentication_client import AuthenticationClient
7
+
8
+
9
+ class ExistingResourcesRetrieved(Enum):
10
+ TRUE = auto()
11
+ FALSE = auto()
12
+
13
+
14
+ @dataclass
15
+ class MetadataClient(Protocol):
16
+ """
17
+ Protocol class/interface for the metadata endpoint in the API.
18
+ """
19
+
20
+ server: str
21
+ authentication_client: AuthenticationClient
22
+
23
+ def get_resource_metadata(self, shortcode: str) -> tuple[ExistingResourcesRetrieved, list[dict[str, str]]]:
24
+ """Get all resource metadata from one project."""
@@ -0,0 +1,47 @@
1
+ from dataclasses import dataclass
2
+ from http import HTTPStatus
3
+
4
+ import requests
5
+ from loguru import logger
6
+ from requests import RequestException
7
+
8
+ from dsp_tools.clients.authentication_client import AuthenticationClient
9
+ from dsp_tools.clients.metadata_client import ExistingResourcesRetrieved
10
+ from dsp_tools.clients.metadata_client import MetadataClient
11
+ from dsp_tools.utils.request_utils import RequestParameters
12
+ from dsp_tools.utils.request_utils import log_and_warn_unexpected_non_ok_response
13
+ from dsp_tools.utils.request_utils import log_request
14
+ from dsp_tools.utils.request_utils import log_response
15
+
16
+ TIMEOUT = 120
17
+
18
+
19
+ @dataclass
20
+ class MetadataClientLive(MetadataClient):
21
+ server: str
22
+ authentication_client: AuthenticationClient
23
+
24
+ def get_resource_metadata(self, shortcode: str) -> tuple[ExistingResourcesRetrieved, list[dict[str, str]]]:
25
+ url = f"{self.server}/v2/metadata/projects/{shortcode}/resources?format=JSON"
26
+ header = {"Authorization": f"Bearer {self.authentication_client.get_token()}"}
27
+ params = RequestParameters(method="GET", url=url, timeout=TIMEOUT, headers=header)
28
+ logger.debug("GET Resource Metadata")
29
+ log_request(params)
30
+ try:
31
+ response = requests.get(
32
+ url=params.url,
33
+ headers=params.headers,
34
+ timeout=params.timeout,
35
+ )
36
+ except RequestException as err:
37
+ logger.exception(err)
38
+ return ExistingResourcesRetrieved.FALSE, []
39
+ if response.ok:
40
+ log_response(response, include_response_content=False)
41
+ logger.debug(f"{len(response.json())} NUMBER OF RESOURCES RETRIEVED")
42
+ return ExistingResourcesRetrieved.TRUE, response.json()
43
+ if response.status_code != HTTPStatus.FORBIDDEN:
44
+ # this warning is to inform for unhandled status codes
45
+ # if the user has insufficient credentials but references resources in the XML, they will get informed then
46
+ log_and_warn_unexpected_non_ok_response(response.status_code, response.text)
47
+ return ExistingResourcesRetrieved.FALSE, []
@@ -0,0 +1,49 @@
1
+ from typing import Any
2
+ from typing import Protocol
3
+
4
+ from rdflib import Literal
5
+
6
+ from dsp_tools.clients.authentication_client import AuthenticationClient
7
+ from dsp_tools.utils.request_utils import ResponseCodeAndText
8
+
9
+
10
+ class OntologyCreateClient(Protocol):
11
+ """
12
+ Protocol class/interface to create / update the ontology through the API.
13
+ """
14
+
15
+ server: str
16
+ authentication_client: AuthenticationClient
17
+
18
+ def get_last_modification_date(self, project_iri: str, onto_iri: str) -> Literal:
19
+ """Get the last modification date of an ontology"""
20
+
21
+ def post_resource_cardinalities(self, cardinality_graph: dict[str, Any]) -> Literal | None:
22
+ """Add cardinalities to an existing resource class."""
23
+
24
+ def post_new_property(self, property_graph: dict[str, Any]) -> Literal | ResponseCodeAndText:
25
+ """Create a property on the server"""
26
+
27
+ def post_new_class(self, property_graph: dict[str, Any]) -> Literal | ResponseCodeAndText:
28
+ """Create a class on the server"""
29
+
30
+ def post_new_ontology(self, onto_graph: dict[str, Any]) -> str | ResponseCodeAndText:
31
+ """Create a new ontology on the server"""
32
+
33
+
34
+ class OntologyGetClient(Protocol):
35
+ """
36
+ Protocol class/interface to get ontologies from the API.
37
+ """
38
+
39
+ api_url: str
40
+ shortcode: str
41
+
42
+ def get_knora_api(self) -> str:
43
+ """Get the knora-api ontology."""
44
+
45
+ def get_ontologies(self) -> tuple[list[str], list[str]]:
46
+ """Get all project ontologies."""
47
+
48
+ def _get_one_ontology(self, ontology_iri: str) -> str:
49
+ """Get one ontology by its IRI."""
@@ -0,0 +1,166 @@
1
+ from dataclasses import dataclass
2
+ from http import HTTPStatus
3
+ from typing import Any
4
+ from typing import cast
5
+
6
+ import requests
7
+ from rdflib import Graph
8
+ from rdflib import Literal
9
+ from rdflib import URIRef
10
+ from requests import RequestException
11
+ from requests import Response
12
+
13
+ from dsp_tools.clients.authentication_client import AuthenticationClient
14
+ from dsp_tools.clients.ontology_clients import OntologyCreateClient
15
+ from dsp_tools.error.exceptions import BadCredentialsError
16
+ from dsp_tools.error.exceptions import FatalNonOkApiResponseCode
17
+ from dsp_tools.utils.rdf_constants import KNORA_API
18
+ from dsp_tools.utils.request_utils import RequestParameters
19
+ from dsp_tools.utils.request_utils import ResponseCodeAndText
20
+ from dsp_tools.utils.request_utils import log_and_raise_request_exception
21
+ from dsp_tools.utils.request_utils import log_and_warn_unexpected_non_ok_response
22
+ from dsp_tools.utils.request_utils import log_request
23
+ from dsp_tools.utils.request_utils import log_response
24
+
25
+ TIMEOUT = 60
26
+
27
+
28
+ @dataclass
29
+ class OntologyCreateClientLive(OntologyCreateClient):
30
+ """
31
+ Client for the ontology endpoint in the API.
32
+ """
33
+
34
+ server: str
35
+ authentication_client: AuthenticationClient
36
+
37
+ def get_last_modification_date(self, project_iri: str, onto_iri: str) -> Literal:
38
+ url = f"{self.server}/v2/ontologies/metadata"
39
+ header = {"X-Knora-Accept-Project": project_iri}
40
+ try:
41
+ response = self._get_and_log_request(url, header)
42
+ except RequestException as err:
43
+ log_and_raise_request_exception(err)
44
+
45
+ if response.ok:
46
+ return _parse_last_modification_date(response.text, URIRef(onto_iri))
47
+ raise FatalNonOkApiResponseCode(url, response.status_code, response.text)
48
+
49
+ def post_resource_cardinalities(self, cardinality_graph: dict[str, Any]) -> Literal | None:
50
+ url = f"{self.server}/v2/ontologies/cardinalities"
51
+ try:
52
+ response = self._post_and_log_request(url, cardinality_graph)
53
+ except RequestException as err:
54
+ log_and_raise_request_exception(err)
55
+
56
+ if response.ok:
57
+ return _parse_last_modification_date(response.text)
58
+ if response.status_code == HTTPStatus.FORBIDDEN:
59
+ raise BadCredentialsError(
60
+ "Only a SystemAdmin or ProjectAdmin can add cardinalities to resource classes. "
61
+ "Your permissions are insufficient for this action."
62
+ )
63
+ log_and_warn_unexpected_non_ok_response(response.status_code, response.text)
64
+ return None
65
+
66
+ def post_new_property(self, property_graph: dict[str, Any]) -> Literal | ResponseCodeAndText:
67
+ url = f"{self.server}/v2/ontologies/properties"
68
+ try:
69
+ response = self._post_and_log_request(url, property_graph)
70
+ except RequestException as err:
71
+ log_and_raise_request_exception(err)
72
+
73
+ if response.ok:
74
+ return _parse_last_modification_date(response.text)
75
+ if response.status_code == HTTPStatus.FORBIDDEN:
76
+ raise BadCredentialsError(
77
+ "Only a SystemAdmin or ProjectAdmin can create properties. "
78
+ "Your permissions are insufficient for this action."
79
+ )
80
+ return ResponseCodeAndText(response.status_code, response.text)
81
+
82
+ def post_new_class(self, class_graph: dict[str, Any]) -> Literal | ResponseCodeAndText:
83
+ url = f"{self.server}/v2/ontologies/classes"
84
+ try:
85
+ response = self._post_and_log_request(url, class_graph)
86
+ except RequestException as err:
87
+ log_and_raise_request_exception(err)
88
+
89
+ if response.ok:
90
+ return _parse_last_modification_date(response.text)
91
+ if response.status_code == HTTPStatus.FORBIDDEN:
92
+ raise BadCredentialsError(
93
+ "Only a SystemAdmin or ProjectAdmin can create classes. "
94
+ "Your permissions are insufficient for this action."
95
+ )
96
+ return ResponseCodeAndText(response.status_code, response.text)
97
+
98
+ def post_new_ontology(self, onto_graph: dict[str, Any]) -> str | ResponseCodeAndText:
99
+ url = f"{self.server}/v2/ontologies"
100
+ try:
101
+ response = self._post_and_log_request(url, onto_graph)
102
+ except RequestException as err:
103
+ log_and_raise_request_exception(err)
104
+
105
+ if response.ok:
106
+ response_json: dict[str, Any] = response.json()
107
+ return cast(str, response_json["@id"])
108
+ if response.status_code == HTTPStatus.FORBIDDEN:
109
+ raise BadCredentialsError(
110
+ "Only a SystemAdmin or ProjectAdmin can create new ontologies. "
111
+ "Your permissions are insufficient for this action."
112
+ )
113
+ return ResponseCodeAndText(response.status_code, response.text)
114
+
115
+ def _post_and_log_request(
116
+ self,
117
+ url: str,
118
+ data: dict[str, Any] | None,
119
+ headers: dict[str, str] | None = None,
120
+ ) -> Response:
121
+ data_dict, generic_headers = self._prepare_request(data, headers)
122
+ params = RequestParameters("POST", url, TIMEOUT, data_dict, generic_headers)
123
+ log_request(params)
124
+ response = requests.post(
125
+ url=params.url,
126
+ headers=params.headers,
127
+ data=params.data_serialized,
128
+ timeout=params.timeout,
129
+ )
130
+ log_response(response)
131
+ return response
132
+
133
+ def _get_and_log_request(
134
+ self,
135
+ url: str,
136
+ headers: dict[str, str] | None = None,
137
+ ) -> Response:
138
+ _, generic_headers = self._prepare_request({}, headers)
139
+ params = RequestParameters(method="GET", url=url, timeout=TIMEOUT, headers=generic_headers)
140
+ log_request(params)
141
+ response = requests.get(
142
+ url=params.url,
143
+ headers=params.headers,
144
+ timeout=params.timeout,
145
+ )
146
+ log_response(response)
147
+ return response
148
+
149
+ def _prepare_request(
150
+ self, data: dict[str, Any] | None, headers: dict[str, str] | None
151
+ ) -> tuple[dict[str, Any] | None, dict[str, str]]:
152
+ generic_headers = {
153
+ "Content-Type": "application/json",
154
+ "Authorization": f"Bearer {self.authentication_client.get_token()}",
155
+ }
156
+ data_dict = data if data else None
157
+ if headers:
158
+ generic_headers.update(headers)
159
+ return data_dict, generic_headers
160
+
161
+
162
+ def _parse_last_modification_date(response_text: str, onto_iri: URIRef | None = None) -> Literal:
163
+ g = Graph()
164
+ g.parse(data=response_text, format="json-ld")
165
+ date = next(g.objects(subject=onto_iri, predicate=KNORA_API.lastModificationDate))
166
+ return cast(Literal, date)
@@ -0,0 +1,80 @@
1
+ from dataclasses import dataclass
2
+ from typing import Any
3
+ from typing import cast
4
+
5
+ import requests
6
+ from requests import RequestException
7
+
8
+ from dsp_tools.clients.ontology_clients import OntologyGetClient
9
+ from dsp_tools.error.exceptions import FatalNonOkApiResponseCode
10
+ from dsp_tools.error.exceptions import ProjectOntologyNotFound
11
+ from dsp_tools.utils.request_utils import RequestParameters
12
+ from dsp_tools.utils.request_utils import log_and_raise_request_exception
13
+ from dsp_tools.utils.request_utils import log_request
14
+ from dsp_tools.utils.request_utils import log_response
15
+
16
+
17
+ @dataclass
18
+ class OntologyGetClientLive(OntologyGetClient):
19
+ api_url: str
20
+ shortcode: str
21
+
22
+ def get_knora_api(self) -> str:
23
+ url = f"{self.api_url}/ontology/knora-api/v2#"
24
+ headers = {"Accept": "text/turtle"}
25
+ timeout = 60
26
+ params = RequestParameters("GET", url, timeout=timeout, headers=headers)
27
+ log_request(params)
28
+ try:
29
+ response = requests.get(url=params.url, headers=params.headers, timeout=params.timeout)
30
+ except RequestException as err:
31
+ log_and_raise_request_exception(err)
32
+ log_response(response, include_response_content=False)
33
+ if response.ok:
34
+ return response.text
35
+ raise FatalNonOkApiResponseCode(params.url, response.status_code, response.text)
36
+
37
+ def get_ontologies(self) -> tuple[list[str], list[str]]:
38
+ """
39
+ Returns a list of project ontologies as a string in turtle format.
40
+ And a list of the ontology IRIs
41
+
42
+ Returns:
43
+ list of ontologies and IRIs
44
+ """
45
+ ontology_iris = self._get_ontology_iris()
46
+ ontologies = [self._get_one_ontology(x) for x in ontology_iris]
47
+ return ontologies, ontology_iris
48
+
49
+ def _get_ontology_iris(self) -> list[str]:
50
+ url = f"{self.api_url}/admin/projects/shortcode/{self.shortcode}"
51
+ timeout = 10
52
+ params = RequestParameters("GET", url, timeout=timeout)
53
+ log_request(params)
54
+ try:
55
+ response = requests.get(url=params.url, timeout=params.timeout)
56
+ except RequestException as err:
57
+ log_and_raise_request_exception(err)
58
+ log_response(response)
59
+ if not response.ok:
60
+ raise FatalNonOkApiResponseCode(params.url, response.status_code, response.text)
61
+ response_json = cast(dict[str, Any], response.json())
62
+ if not (ontos := response_json.get("project", {}).get("ontologies")):
63
+ raise ProjectOntologyNotFound(self.shortcode)
64
+ output = cast(list[str], ontos)
65
+ return output
66
+
67
+ def _get_one_ontology(self, ontology_iri: str) -> str:
68
+ url = ontology_iri
69
+ headers = {"Accept": "text/turtle"}
70
+ timeout = 30
71
+ params = RequestParameters("GET", url, timeout=timeout, headers=headers)
72
+ log_request(params)
73
+ try:
74
+ response = requests.get(url=params.url, headers=params.headers, timeout=params.timeout)
75
+ except RequestException as err:
76
+ log_and_raise_request_exception(err)
77
+ log_response(response, include_response_content=False)
78
+ if response.ok:
79
+ return response.text
80
+ raise FatalNonOkApiResponseCode(params.url, response.status_code, response.text)
@@ -0,0 +1,68 @@
1
+ from dataclasses import dataclass
2
+ from typing import Any
3
+ from urllib.parse import quote_plus
4
+
5
+ import requests
6
+ from loguru import logger
7
+ from requests import RequestException
8
+
9
+ from dsp_tools.clients.authentication_client import AuthenticationClient
10
+ from dsp_tools.utils.request_utils import RequestParameters
11
+ from dsp_tools.utils.request_utils import log_request
12
+ from dsp_tools.utils.request_utils import log_response
13
+
14
+
15
+ @dataclass
16
+ class PermissionsClient:
17
+ auth: AuthenticationClient
18
+ proj_iri: str
19
+
20
+ def get_project_doaps(self) -> list[dict[str, Any]]:
21
+ params = RequestParameters(
22
+ "GET",
23
+ f"{self.auth.server}/admin/permissions/doap/{quote_plus(self.proj_iri)}",
24
+ timeout=10,
25
+ headers={"Accept": "application/json", "Authorization": f"Bearer {self.auth.get_token()}"},
26
+ )
27
+ log_request(params)
28
+ try:
29
+ response = requests.get(params.url, timeout=params.timeout, headers=params.headers)
30
+ log_response(response)
31
+ except RequestException:
32
+ logger.exception("Error while retrieving existing DOAPs")
33
+ return []
34
+ res: list[dict[str, Any]] = response.json()["default_object_access_permissions"]
35
+ return res
36
+
37
+ def delete_doap(self, doap_iri: str) -> bool:
38
+ params = RequestParameters(
39
+ "DELETE",
40
+ f"{self.auth.server}/admin/permissions/{quote_plus(doap_iri)}",
41
+ timeout=10,
42
+ headers={"Authorization": f"Bearer {self.auth.get_token()}"},
43
+ )
44
+ log_request(params)
45
+ try:
46
+ response = requests.delete(params.url, timeout=params.timeout, headers=params.headers)
47
+ log_response(response)
48
+ except RequestException:
49
+ logger.exception("Error while deleting DOAP")
50
+ return False
51
+ return True
52
+
53
+ def create_new_doap(self, payload: dict[str, Any]) -> bool:
54
+ params = RequestParameters(
55
+ "POST",
56
+ f"{self.auth.server}/admin/permissions/doap",
57
+ timeout=10,
58
+ headers={"Authorization": f"Bearer {self.auth.get_token()}"},
59
+ data=payload,
60
+ )
61
+ log_request(params)
62
+ try:
63
+ response = requests.post(params.url, timeout=params.timeout, headers=params.headers, json=params.data)
64
+ log_response(response)
65
+ except RequestException:
66
+ logger.exception("Error while creating new DOAP")
67
+ return False
68
+ return True
@@ -0,0 +1,16 @@
1
+ from dataclasses import dataclass
2
+ from typing import Any
3
+ from typing import Protocol
4
+
5
+ from dsp_tools.utils.request_utils import ResponseCodeAndText
6
+
7
+
8
+ @dataclass
9
+ class ProjectClient(Protocol):
10
+ server: str
11
+
12
+ def get_project_iri(self, shortcode: str) -> str:
13
+ """Get the IRI of a project via shortcode."""
14
+
15
+ def post_new_project(self, project_info: dict[str, Any]) -> str | ResponseCodeAndText:
16
+ """Post a new project."""