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
@@ -23,9 +23,11 @@ class ListNode:
23
23
  return [nd.to_dict() for nd in self.sub_nodes]
24
24
 
25
25
  def _make_own_node(self) -> dict[str, Any]:
26
- d = {"name": self.id_, "labels": self.labels}
26
+ sorted_labels = {k: self.labels[k] for k in sorted(self.labels.keys())}
27
+ d = {"name": self.id_, "labels": sorted_labels}
27
28
  if self.comments:
28
- d.update({"comments": self.comments})
29
+ sorted_comments = {k: self.comments[k] for k in sorted(self.comments.keys())}
30
+ d["comments"] = sorted_comments
29
31
  return d
30
32
 
31
33
 
@@ -45,9 +47,11 @@ class ListRoot:
45
47
  return [nd.to_dict() for nd in self.nodes]
46
48
 
47
49
  def _make_list_root(self) -> dict[str, Any]:
48
- lst = {"name": self.id_, "labels": self.labels}
50
+ sorted_labels = {k: self.labels[k] for k in sorted(self.labels.keys())}
51
+ lst = {"name": self.id_, "labels": sorted_labels}
49
52
  if self.comments:
50
- lst.update({"comments": self.comments})
53
+ sorted_comments = {k: self.comments[k] for k in sorted(self.comments.keys())}
54
+ lst["comments"] = sorted_comments
51
55
  else:
52
- lst.update({"comments": self.labels})
56
+ lst["comments"] = sorted_labels
53
57
  return lst
@@ -5,9 +5,9 @@ from typing import Any
5
5
  import pandas as pd
6
6
  import regex
7
7
 
8
- from dsp_tools.commands.excel2json.new_lists.models.deserialise import ColumnNodes
9
- from dsp_tools.commands.excel2json.new_lists.models.deserialise import Columns
10
- from dsp_tools.models.exceptions import InputError
8
+ from dsp_tools.commands.excel2json.lists.models.deserialise import ColumnNodes
9
+ from dsp_tools.commands.excel2json.lists.models.deserialise import Columns
10
+ from dsp_tools.error.exceptions import InputError
11
11
 
12
12
 
13
13
  def get_lang_string_from_column_name(col_str: str, ending: str = r"(\d+|list|comments)") -> str | None:
@@ -76,6 +76,6 @@ def get_preferred_language_from_columns(columns: pd.Index[str], ending: str = r"
76
76
  return "rm"
77
77
  msg = (
78
78
  f"The columns may only contain the languages: 'en', 'de', 'fr', 'it', 'rm'.\n"
79
- f"The columns are: {" ".join(columns)}"
79
+ f"The columns are: {' '.join(columns)}"
80
80
  )
81
81
  raise InputError(msg)
@@ -2,7 +2,8 @@ from __future__ import annotations
2
2
 
3
3
  from dataclasses import dataclass
4
4
  from typing import Any
5
- from typing import Protocol
5
+
6
+ from dsp_tools.error.problems import Problem
6
7
 
7
8
  separator = "\n "
8
9
  list_separator = "\n - "
@@ -11,15 +12,6 @@ medium_separator = "\n----------------------------\n"
11
12
  grand_separator = "\n\n---------------------------------------\n\n"
12
13
 
13
14
 
14
- class Problem(Protocol):
15
- """Information about input errors."""
16
-
17
- def execute_error_protocol(self) -> str:
18
- """
19
- This function initiates all the steps for successful problem communication with the user.
20
- """
21
-
22
-
23
15
  @dataclass(frozen=True)
24
16
  class PositionInExcel:
25
17
  """This class contains the information about the position of a value in the excel."""
@@ -391,6 +383,34 @@ class PropertyProblem:
391
383
  message for the error
392
384
  """
393
385
  all_problems = [x.execute_error_protocol() for x in self.problems]
386
+ return f"The property '{self.prop_name}' has the following problem(s):\n{medium_separator.join(all_problems)}"
387
+
388
+
389
+ @dataclass(frozen=True)
390
+ class InvalidPermissionsOverrule:
391
+ entity_name: str
392
+ actual_val: str
393
+ allowed_vals: list[str]
394
+
395
+
396
+ @dataclass(frozen=True)
397
+ class InvalidPermissionsOverruleProblem:
398
+ """This class contains information if a "default_permissions_overrule" is invalid."""
399
+
400
+ wrong_vals: list[InvalidPermissionsOverrule]
401
+
402
+ def execute_error_protocol(self) -> str:
403
+ """
404
+ This function initiates all the steps for successful problem communication with the user.
405
+
406
+ Returns:
407
+ message for the error
408
+ """
409
+ report_lines = [
410
+ f"Entity: '{x.entity_name}'. Actual value: '{x.actual_val}'. Allowed values: {', '.join(x.allowed_vals)}."
411
+ for x in self.wrong_vals
412
+ ]
394
413
  return (
395
- f"The property '{self.prop_name}' has the following problem(s):\n" f"{medium_separator.join(all_problems)}"
414
+ f"The following entities have an invalid 'default_permissions_overrule': "
415
+ f"{list_separator}{list_separator.join(report_lines)}"
396
416
  )
@@ -25,6 +25,7 @@ class EmptyJsonHeader(JsonHeader):
25
25
  "longname": "",
26
26
  "descriptions": {"en": ""},
27
27
  "keywords": [""],
28
+ "enabled_licenses": [""],
28
29
  },
29
30
  }
30
31
 
@@ -57,7 +58,9 @@ class Project:
57
58
  longname: str
58
59
  descriptions: Descriptions
59
60
  keywords: Keywords
61
+ licenses: Licenses
60
62
  users: Users | None
63
+ default_permissions: str
61
64
 
62
65
  def to_dict(self) -> dict[str, Any]:
63
66
  proj_dict: dict[str, Any] = {
@@ -66,6 +69,8 @@ class Project:
66
69
  "longname": self.longname,
67
70
  "descriptions": self.descriptions.to_dict(),
68
71
  "keywords": self.keywords.to_dict(),
72
+ "enabled_licenses": self.licenses.to_dict(),
73
+ "default_permissions": self.default_permissions,
69
74
  }
70
75
  if self.users:
71
76
  proj_dict["users"] = self.users.to_dict()
@@ -92,6 +97,14 @@ class Keywords:
92
97
  return sorted(self.keywords)
93
98
 
94
99
 
100
+ @dataclass
101
+ class Licenses:
102
+ licenses: list[str]
103
+
104
+ def to_dict(self) -> list[str]:
105
+ return sorted(self.licenses)
106
+
107
+
95
108
  @dataclass
96
109
  class Users:
97
110
  users: list[User]
@@ -106,12 +119,12 @@ class User:
106
119
  email: str
107
120
  givenName: str
108
121
  familyName: str
109
- password: str
122
+ password: str | None
110
123
  lang: str
111
- role: UserRole
124
+ isProjectAdmin: bool
112
125
 
113
126
  def to_dict(self) -> dict[str, Any]:
114
- usr_dict = {
127
+ usr_dict: dict[str, Any] = {
115
128
  "username": self.username,
116
129
  "email": self.email,
117
130
  "givenName": self.givenName,
@@ -119,19 +132,44 @@ class User:
119
132
  "password": self.password,
120
133
  "lang": self.lang,
121
134
  "status": True,
122
- } | self.role.to_dict()
135
+ }
136
+ if self.isProjectAdmin:
137
+ usr_dict["projects"] = [":admin", ":member"]
138
+ else:
139
+ usr_dict["projects"] = [":member"]
123
140
  return usr_dict
124
141
 
125
142
 
126
143
  @dataclass
127
- class UserRole:
128
- project_admin: bool = False
129
- sys_admin: bool = False
130
-
131
- def to_dict(self) -> dict[str, list[str]]:
132
- if self.sys_admin:
133
- return {"groups": ["SystemAdmin"], "projects": [":admin", ":member"]}
134
- elif self.project_admin:
135
- return {"projects": [":admin", ":member"]}
136
- else:
137
- return {"projects": [":member"]}
144
+ class PermissionsOverrulesUnprefixed:
145
+ """
146
+ Data gathered from the column 'default_permissions_overrule' from 1 resources.xlsx / 1 properties.xlsx,
147
+ not yet enriched with ontology prefixes
148
+ """
149
+
150
+ private: list[str]
151
+ limited_view: list[str]
152
+
153
+
154
+ @dataclass
155
+ class PermissionsOverrulesPrefixed:
156
+ """
157
+ Object to gather 'default_permissions_overrule' infos from several resources.xlsx/properties.xlsx,
158
+ with ontology prefixes.
159
+ """
160
+
161
+ private: list[str]
162
+ limited_view: list[str]
163
+
164
+ def add_overrules(self, new_overrules: PermissionsOverrulesUnprefixed, onto_prefix: str) -> None:
165
+ self.private.extend([f"{onto_prefix}:{p}" for p in new_overrules.private])
166
+ self.limited_view.extend([f"{onto_prefix}:{p}" for p in new_overrules.limited_view])
167
+
168
+ def non_empty(self) -> bool:
169
+ return bool(self.private or self.limited_view)
170
+
171
+ def serialize(self) -> dict[str, list[str]]:
172
+ return {
173
+ "private": self.private,
174
+ "limited_view": self.limited_view,
175
+ }
@@ -64,12 +64,13 @@ class LanguageDict:
64
64
  lang_dict: dict[str, str]
65
65
 
66
66
  def serialise(self) -> dict[str, str]:
67
- return self.lang_dict
67
+ sorted_dict = {k: self.lang_dict[k] for k in sorted(self.lang_dict.keys())}
68
+ return sorted_dict
68
69
 
69
70
 
70
71
  @dataclass
71
72
  class GuiAttributes:
72
- gui_attributes: dict[str, int | str | float]
73
+ gui_attributes: dict[str, str]
73
74
 
74
- def serialise(self) -> dict[str, int | str | float]:
75
+ def serialise(self) -> dict[str, str]:
75
76
  return self.gui_attributes
@@ -2,11 +2,9 @@
2
2
 
3
3
  import importlib.resources
4
4
  import json
5
- from copy import deepcopy
6
5
  from pathlib import Path
7
6
  from typing import Any
8
7
  from typing import Optional
9
- from typing import Union
10
8
  from typing import cast
11
9
 
12
10
  import jsonschema
@@ -17,69 +15,12 @@ from openpyxl.worksheet.worksheet import Worksheet
17
15
 
18
16
  from dsp_tools.commands.excel2json.models.input_error import MoreThanOneSheetProblem
19
17
  from dsp_tools.commands.excel2json.models.list_node_name import ListNodeNames
20
- from dsp_tools.models.exceptions import BaseError
21
- from dsp_tools.models.exceptions import InputError
22
- from dsp_tools.models.exceptions import UserError
23
- from dsp_tools.utils.shared import simplify_name
18
+ from dsp_tools.error.exceptions import InputError
19
+ from dsp_tools.utils.data_formats.shared import simplify_name
20
+ from dsp_tools.utils.json_parsing import parse_json_file
24
21
 
25
22
 
26
- def expand_lists_from_excel(
27
- lists_section: list[dict[str, Union[str, dict[str, Any]]]],
28
- ) -> list[dict[str, Any]]:
29
- """
30
- Checks if the "lists" section of a JSON project file contains references to Excel files.
31
- Expands all Excel files to JSON,
32
- and returns the expanded "lists" section.
33
- If there are no references to Excel files,
34
- the "lists" section is returned as is.
35
-
36
- Args:
37
- lists_section: the "lists" section of a parsed JSON project file.
38
- If this is an empty list, an empty list will be returned.
39
-
40
- Raises:
41
- UserError: if a problem occurred while trying to expand the Excel files
42
-
43
- Returns:
44
- the same "lists" section, but without references to Excel files
45
- """
46
- new_lists: list[dict[str, Any]] = []
47
- for _list in lists_section:
48
- # case 1: this list is a JSON list: return it as it is
49
- if "folder" not in _list["nodes"]:
50
- new_lists.append(_list)
51
- continue
52
-
53
- # case 2: this is a reference to a folder with Excel files
54
- new_lists.append(_read_excel_make_lists(_list))
55
-
56
- return new_lists
57
-
58
-
59
- def _read_excel_make_lists(_list: dict[str, Union[str, dict[str, Any]]]) -> dict[str, Any]:
60
- foldername = _list["nodes"]["folder"] # type: ignore[index] # types are too complex to annotate them correctly
61
- excel_file_paths = _extract_excel_file_paths(foldername)
62
- new_list = deepcopy(_list)
63
- try:
64
- returned_lists_section = _make_json_lists_from_excel(excel_file_paths, verbose=False)
65
- # we only need the "nodes" section of the first element of the returned "lists" section. This "nodes"
66
- # section needs to replace the Excel folder reference. But the rest of the user-defined list element
67
- # needs to stay intact, e.g. the labels and comments.
68
- new_list["nodes"] = returned_lists_section[0]["nodes"]
69
- print(
70
- f" The list '{_list['name']}' contains a reference to the folder '{foldername}'. The Excel "
71
- f"files therein have been temporarily expanded into the 'lists' section of your project."
72
- )
73
- return new_list
74
- except BaseError as err:
75
- raise UserError(
76
- f" WARNING: The list '{_list['name']}' contains a reference to the folder '{foldername}', but a "
77
- f"problem occurred while trying to expand the Excel files therein into the 'lists' section of "
78
- f"your project: {err.message}"
79
- ) from None
80
-
81
-
82
- def excel2lists(
23
+ def old_excel2lists(
83
24
  excelfolder: str,
84
25
  path_to_output_file: Optional[str] = None,
85
26
  verbose: bool = False,
@@ -93,7 +34,7 @@ def excel2lists(
93
34
  verbose: verbose switch
94
35
 
95
36
  Raises:
96
- UserError: if something went wrong
37
+ InputError: if something went wrong
97
38
  BaseError: if something went wrong
98
39
 
99
40
  Returns:
@@ -140,7 +81,7 @@ def _get_values_from_excel(
140
81
  verbose: verbose switch
141
82
 
142
83
  Raises:
143
- UserError: if one of the Excel files contains invalid data
84
+ InputError: if one of the Excel files contains invalid data
144
85
 
145
86
  Returns:
146
87
  int: Row index for the next loop (current row index minus 1)
@@ -149,11 +90,11 @@ def _get_values_from_excel(
149
90
  nodes: list[dict[str, Any]] = []
150
91
  currentnode: dict[str, Any] = {}
151
92
  base_file_ws: Worksheet = next(iter(base_file.values()))
152
- cell: Cell = base_file_ws.cell(column=col, row=row)
93
+ cell: Cell = cast(Cell, base_file_ws.cell(column=col, row=row))
153
94
 
154
95
  for excelfile in excelfiles.values():
155
96
  if any((not excelfile["A1"].value, excelfile["B1"].value)):
156
- raise UserError(
97
+ raise InputError(
157
98
  f"ERROR: Inconsistency in Excel list: The first row must consist of exactly one value, in cell A1. "
158
99
  f"All other cells of row 1 must be empty.\nInstead, found the following:\n"
159
100
  f" - Cell A1: '{excelfile['A1'].value}'\n"
@@ -189,7 +130,7 @@ def _get_values_from_excel(
189
130
 
190
131
  # go one row down and repeat loop if there is a value
191
132
  row += 1
192
- cell = base_file_ws.cell(column=col, row=row)
133
+ cell = cast(Cell, base_file_ws.cell(column=col, row=row))
193
134
 
194
135
  if col > 1:
195
136
  preval.pop()
@@ -205,7 +146,7 @@ def _check_if_predecessors_in_row_are_consistent_with_preval(
205
146
  ) -> None:
206
147
  for idx, val in enumerate(preval[:-1]):
207
148
  if val != str(base_file_ws.cell(column=idx + 1, row=row).value).strip():
208
- raise UserError(
149
+ raise InputError(
209
150
  "ERROR: Inconsistency in Excel list: "
210
151
  f"{val} not equal to {str(base_file_ws.cell(column=idx + 1, row=row).value).strip()}"
211
152
  )
@@ -247,7 +188,7 @@ def _check_if_duplicate_nodes_exist(cell: Cell, list_node_names: ListNodeNames,
247
188
  list_node_names.lists_with_previous_cell_values.count(x) > 1
248
189
  for x in list_node_names.lists_with_previous_cell_values
249
190
  ):
250
- raise UserError(
191
+ raise InputError(
251
192
  f"ERROR: There is at least one duplicate node in the list. "
252
193
  f"Found duplicate in column {cell.column}, row {cell.row}:\n'{str(cell.value).strip()}'"
253
194
  )
@@ -258,7 +199,7 @@ def _get_all_languages_of_node(excelfiles: dict[str, Worksheet], col: int, row:
258
199
  for other_lang, ws_other_lang in excelfiles.items():
259
200
  cell_value = ws_other_lang.cell(column=col, row=row).value
260
201
  if not (isinstance(cell_value, str) and len(cell_value) > 0):
261
- raise UserError(
202
+ raise InputError(
262
203
  "ERROR: Malformed Excel file: The Excel file with the language code "
263
204
  f"'{other_lang}' should have a value in row {row}, column {col}"
264
205
  )
@@ -280,7 +221,7 @@ def _make_json_lists_from_excel(
280
221
  verbose: verbose switch
281
222
 
282
223
  Raises:
283
- UserError: if one of the Excel files contains invalid data
224
+ InputError: if one of the Excel files contains invalid data
284
225
 
285
226
  Returns:
286
227
  The finished "lists" section
@@ -333,57 +274,30 @@ def _read_and_check_workbook(excelpath: Path) -> Worksheet:
333
274
  return all_worksheets[0]
334
275
 
335
276
 
336
- def validate_lists_section_with_schema(
337
- path_to_json_project_file: Optional[str] = None,
338
- lists_section: Optional[list[dict[str, Any]]] = None,
339
- ) -> bool:
340
- """
341
- This function checks if a "lists" section of a JSON project is valid according to the schema. The "lists" section
342
- can be passed as path to the JSON project file, or as Python object. Only one of the two arguments should be passed.
343
-
344
- Args:
345
- path_to_json_project_file: path to the JSON project file that contains the "lists" section to validate
346
- lists_section: the "lists" section as Python object
347
-
348
- Raises:
349
- UserError: if the validation fails
350
- BaseError: if this function is called with invalid parameters
277
+ def validate_lists_section_from_project(project_file: Path) -> bool:
278
+ project = parse_json_file(project_file)
279
+ lists_section = project["project"].get("lists")
280
+ if not lists_section:
281
+ raise InputError(
282
+ f"Cannot validate 'lists' section of {project_file}, because there is no 'lists' section in this file."
283
+ )
284
+ return validate_lists_section_with_schema(lists_section)
351
285
 
352
- Returns:
353
- True if the "lists" section passed validation
354
- """
355
- err_msg = "Validation of the 'lists' section works only if exactly one of the two arguments is given."
356
- match path_to_json_project_file, lists_section:
357
- case None, None:
358
- raise BaseError(err_msg)
359
- case str(), list():
360
- raise BaseError(err_msg)
361
286
 
287
+ def validate_lists_section_with_schema(lists_section: list[dict[str, Any]]) -> bool:
362
288
  with (
363
289
  importlib.resources.files("dsp_tools")
364
290
  .joinpath("resources/schema/lists-only.json")
365
291
  .open(encoding="utf-8") as schema_file
366
292
  ):
367
293
  lists_schema = json.load(schema_file)
368
-
369
- if path_to_json_project_file:
370
- with open(path_to_json_project_file, encoding="utf-8") as f:
371
- project = json.load(f)
372
- lists_section = project["project"].get("lists")
373
- if not lists_section:
374
- raise UserError(
375
- f"Cannot validate 'lists' section of {path_to_json_project_file}, "
376
- "because there is no 'lists' section in this file."
377
- )
378
-
379
294
  try:
380
295
  jsonschema.validate(instance={"lists": lists_section}, schema=lists_schema)
381
296
  except jsonschema.ValidationError as err:
382
- raise UserError(
297
+ raise InputError(
383
298
  f"'lists' section did not pass validation. The error message is: {err.message}\n"
384
299
  f"The error occurred at {err.json_path}"
385
300
  ) from None
386
-
387
301
  return True
388
302
 
389
303
 
@@ -396,19 +310,19 @@ def _extract_excel_file_paths(excelfolder: str) -> list[Path]:
396
310
  excelfolder: path to the folder containing the Excel file(s)
397
311
 
398
312
  Raises:
399
- UserError: if excelfolder is not a directory, or if one of the files in it has an invalid name
313
+ InputError: if excelfolder is not a directory, or if one of the files in it has an invalid name
400
314
 
401
315
  Returns:
402
316
  list of the Excel file paths to process
403
317
  """
404
318
  if not Path(excelfolder).is_dir():
405
- raise UserError(f"ERROR: {excelfolder} is not a directory.")
319
+ raise InputError(f"ERROR: {excelfolder} is not a directory.")
406
320
 
407
321
  supported_files = ["en.xlsx", "de.xlsx", "fr.xlsx", "it.xlsx", "rm.xlsx"]
408
322
  excel_file_paths = [x for x in Path(excelfolder).glob("*.xlsx") if x.is_file() and not x.name.startswith("~$")]
409
323
 
410
324
  for filepath in excel_file_paths:
411
325
  if filepath.name not in supported_files:
412
- raise UserError(f"Invalid file name '{filepath}'. Expected format: 'languagecode.xlsx'")
326
+ raise InputError(f"Invalid file name '{filepath}'. Expected format: 'languagecode.xlsx'")
413
327
 
414
328
  return excel_file_paths