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
@@ -1,24 +1,102 @@
1
- import json
2
1
  from typing import Any
3
2
 
4
3
  import pandas as pd
5
4
  import regex
6
5
 
6
+ from dsp_tools.error.xmllib_warnings import MessageInfo
7
+ from dsp_tools.error.xmllib_warnings_util import emit_xmllib_input_warning
8
+ from dsp_tools.xmllib.internal.circumvent_circular_imports import parse_richtext_as_xml
9
+
10
+
11
+ def is_nonempty_value(value: Any) -> bool:
12
+ """
13
+ Check if a value is not None-like
14
+ or that its string representation contains at least one of the following characters:
15
+
16
+ - ``\\p{S}`` = symbols and special characters
17
+ - ``\\p{P}`` = punctuation
18
+ - ``\\w`` = all Unicode letters, numbers, and _
19
+
20
+ If the value is a collection (i.e. list, tuple, set or dictionary)
21
+ all the elements must be non-empty to return True.
22
+
23
+ Args:
24
+ value: value of any type
25
+
26
+ Returns:
27
+ True if the value is not None-like and contains at least one of the above-mentioned characters
28
+
29
+ Examples:
30
+ ```python
31
+ # True values:
32
+ assert xmllib.is_nonempty_value("word") == True
33
+ assert xmllib.is_nonempty_value(["word"]) == True
34
+ assert xmllib.is_nonempty_value("None") == True
35
+ assert xmllib.is_nonempty_value("-") == True
36
+ assert xmllib.is_nonempty_value(0) == True
37
+ assert xmllib.is_nonempty_value(1) == True
38
+ assert xmllib.is_nonempty_value("0") == True
39
+ assert xmllib.is_nonempty_value("1") == True
40
+ assert xmllib.is_nonempty_value(True) == True
41
+ assert xmllib.is_nonempty_value(False) == True
42
+ assert xmllib.is_nonempty_value("עִבְרִית") == True
43
+
44
+ # False values:
45
+ assert xmllib.is_nonempty_value(pd.NA) == False
46
+ assert xmllib.is_nonempty_value(None) == False
47
+ assert xmllib.is_nonempty_value("") == False
48
+ assert xmllib.is_nonempty_value(["", "some-content"]) == False
49
+ assert xmllib.is_nonempty_value({"dict-key": ""}) == False
50
+ assert xmllib.is_nonempty_value(" ") == False
51
+ assert xmllib.is_nonempty_value("\\n") == False
52
+ ```
53
+ """
54
+ if isinstance(value, (tuple, list, set)):
55
+ all_vals = [is_nonempty_value(v) for v in value]
56
+ return all(all_vals)
57
+ if isinstance(value, dict):
58
+ all_vals = []
59
+ for k, v in value.items():
60
+ all_vals.append(is_nonempty_value(k))
61
+ all_vals.append(is_nonempty_value(v))
62
+ return all(all_vals)
63
+ if pd.isna(value):
64
+ return False
65
+ if regex.search(r"[\p{S}\p{P}\w]", str(value), flags=regex.UNICODE):
66
+ return True
67
+ return False
68
+
7
69
 
8
70
  def is_bool_like(value: Any) -> bool:
9
71
  """
10
72
  Checks if a value is a bool or can be converted into a bool.
73
+ It is case-insensitive, meaning that the words can also be capitalised.
74
+
75
+ Accepted values:
76
+ - `false`, `0`, `0.0`, `no`, `non`, `nein` -> `False`
77
+ - `true`, `1`, `1.0`, `yes`, `oui`, `ja` -> `True`
11
78
 
12
79
  Args:
13
80
  value: value to check
14
81
 
15
82
  Returns:
16
83
  True if it conforms
84
+
85
+ Examples:
86
+ ```python
87
+ result = xmllib.is_bool_like("yes")
88
+ # result == True
89
+ ```
90
+
91
+ ```python
92
+ result = xmllib.is_bool_like("not like a bool")
93
+ # result == False
94
+ ```
17
95
  """
18
96
  value = str(value).lower().strip()
19
- if value in ("false", "0", "0.0", "no"):
97
+ if value in ("false", "0", "0.0", "no", "non", "nein"):
20
98
  return True
21
- elif value in ("true", "1", "1.0", "yes"):
99
+ elif value in ("true", "1", "1.0", "yes", "oui", "ja"):
22
100
  return True
23
101
  return False
24
102
 
@@ -32,8 +110,18 @@ def is_color(value: Any) -> bool:
32
110
 
33
111
  Returns:
34
112
  True if it conforms
35
- """
36
113
 
114
+ Examples:
115
+ ```python
116
+ result = xmllib.is_color("#00ff66")
117
+ # result == True
118
+ ```
119
+
120
+ ```python
121
+ result = xmllib.is_color("not a color")
122
+ # result == False
123
+ ```
124
+ """
37
125
  return bool(regex.search(r"^#[0-9a-f]{6}$", str(value).strip(), flags=regex.IGNORECASE))
38
126
 
39
127
 
@@ -46,18 +134,34 @@ def is_date(value: Any) -> bool:
46
134
 
47
135
  Returns:
48
136
  True if it conforms
49
- """
50
137
 
51
- calendar_optional = r"((GREGORIAN|JULIAN|ISLAMIC):)?"
52
- first_era_optional = r"((CE|BCE|BC|AD):)?"
53
- second_area_optional = r"(:(CE|BCE|BC|AD))?"
138
+ Examples:
139
+ ```python
140
+ result = xmllib.is_date("GREGORIAN:CE:2014-01-31:CE:2014-01-31")
141
+ # result == True
142
+ ```
143
+
144
+ ```python
145
+ result = xmllib.is_date("not a date")
146
+ # result == False
147
+ ```
148
+ """
149
+ calendar_optional = r"(?:(GREGORIAN|JULIAN|ISLAMIC):)?"
150
+ first_era_optional = r"(?:(CE|BCE|BC|AD):)?"
151
+ second_area_optional = r"(?::(CE|BCE|BC|AD))?"
54
152
  date = r"\d{1,4}(?:-\d{1,2}){0,2}"
55
153
  date_mandatory = rf"({date})"
56
154
  date_optional = rf"(:{date})?"
57
155
  full_date_pattern = (
58
156
  rf"^{calendar_optional}{first_era_optional}{date_mandatory}{second_area_optional}{date_optional}$"
59
157
  )
60
- return bool(regex.search(full_date_pattern, str(value)))
158
+ found = regex.search(full_date_pattern, str(value))
159
+ if not found:
160
+ return False
161
+ if found.group(1) == "ISLAMIC" and (found.group(2) or found.group(4)):
162
+ # eras are not supported yet for the islamic calendar
163
+ return False
164
+ return True
61
165
 
62
166
 
63
167
  def is_geoname(value: Any) -> bool:
@@ -69,6 +173,17 @@ def is_geoname(value: Any) -> bool:
69
173
 
70
174
  Returns:
71
175
  True if it conforms
176
+
177
+ Examples:
178
+ ```python
179
+ result = xmllib.is_geoname("8879000")
180
+ # result == True
181
+ ```
182
+
183
+ ```python
184
+ result = xmllib.is_geoname("not a geoname code")
185
+ # result == False
186
+ ```
72
187
  """
73
188
  return is_integer(value)
74
189
 
@@ -82,13 +197,38 @@ def is_decimal(value: Any) -> bool:
82
197
 
83
198
  Returns:
84
199
  True if conforms to the above-mentioned criteria.
200
+
201
+ Examples:
202
+ ```python
203
+ result = xmllib.is_decimal("0.1")
204
+ # result == True
205
+ ```
206
+
207
+ ```python
208
+ # because this is equivalent to 9.0 it is accepted
209
+
210
+ result = xmllib.is_decimal(9)
211
+ # result == True
212
+ ```
213
+
214
+ ```python
215
+ result = xmllib.is_decimal("not a decimal")
216
+ # result == False
217
+ ```
85
218
  """
86
- if isinstance(value, str):
87
- if regex.search(r"^\d+(\.\d+)?$", value):
219
+ if pd.isna(value):
220
+ return False
221
+
222
+ match value:
223
+ case bool():
224
+ return False
225
+ case int() | float():
88
226
  return True
89
- elif isinstance(value, int) or isinstance(value, float):
227
+ try:
228
+ float(value)
90
229
  return True
91
- return False
230
+ except ValueError:
231
+ return False
92
232
 
93
233
 
94
234
  def is_integer(value: Any) -> bool:
@@ -100,28 +240,104 @@ def is_integer(value: Any) -> bool:
100
240
 
101
241
  Returns:
102
242
  True if conforms to the above-mentioned criteria.
243
+
244
+ Examples:
245
+ ```python
246
+ result = xmllib.is_integer("1")
247
+ # result == True
248
+ ```
249
+
250
+ ```python
251
+ result = xmllib.is_integer(9.1)
252
+ # result == False
253
+ ```
254
+
255
+ ```python
256
+ result = xmllib.is_integer("not an integer")
257
+ # result == False
258
+ ```
103
259
  """
104
- if isinstance(value, str):
105
- return bool(regex.search(r"^\d+$", value))
106
- return isinstance(value, int)
260
+ match value:
261
+ case bool():
262
+ return False
263
+ case int():
264
+ return True
265
+ case str():
266
+ return bool(regex.search(r"^\d+$", value))
267
+ case _:
268
+ return False
107
269
 
108
270
 
109
- def is_string_like(value: Any) -> bool:
271
+ def is_link_value(value: Any) -> bool:
110
272
  """
111
- Checks if a value is a string.
273
+ Check if a value is a valid internal ID of a resource (xsd:ID) or a valid internal DSP IRI.
274
+ Both of these values are allowed in LinkValues.
112
275
 
113
276
  Args:
114
- value: value to check
277
+ value: the target ID of a LinkValue
115
278
 
116
279
  Returns:
117
- True if it is a string
280
+ True if it is a permissible value.
281
+
282
+ Examples:
283
+ ```python
284
+ result = xmllib.is_link_value("1_must_not_start_with_number")
285
+ # result == False
286
+ ```
287
+
288
+ ```python
289
+ result = xmllib.is_link_value("characters|not|allowed")
290
+ # result == False
291
+ ```
292
+
293
+ ```python
294
+ result = xmllib.is_link_value("resource_id_1")
295
+ # result == True
296
+ ```
297
+
298
+ ```python
299
+ result = xmllib.is_link_value("http://rdfh.ch/4123/54SYvWF0QUW6a")
300
+ # result == True
301
+ ```
118
302
  """
119
- if pd.isna(value):
120
- return False
121
- value = str(value).strip()
122
- if len(value) == 0:
123
- return False
124
- return bool(regex.search(r"\S", value, flags=regex.UNICODE))
303
+ if is_valid_resource_id(value):
304
+ return True
305
+ return is_dsp_iri(value)
306
+
307
+
308
+ def is_valid_resource_id(value: Any) -> bool:
309
+ """
310
+ Check if a value is a valid internal ID of a resource (xsd:ID).
311
+
312
+ Args:
313
+ value: the ID of a Resource
314
+
315
+ Returns:
316
+ True if it is a permissible value.
317
+
318
+ Examples:
319
+ ```python
320
+ result = xmllib.is_valid_resource_id("1_must_not_start_with_number")
321
+ # result == False
322
+ ```
323
+
324
+ ```python
325
+ result = xmllib.is_valid_resource_id("characters|not|allowed")
326
+ # result == False
327
+ ```
328
+
329
+ ```python
330
+ result = xmllib.is_valid_resource_id("resource_id_1")
331
+ # result == True
332
+ ```
333
+ """
334
+ allowed_letters = "a-zA-Zàáâäèéêëìíîïòóôöùúûüçñß_"
335
+ if is_nonempty_value(value):
336
+ # None, etc. would not be recognised as invalid since it is converted into a string.
337
+ return bool(
338
+ regex.search(rf"^[{allowed_letters}][{allowed_letters}\d.\-]*$", str(value)),
339
+ )
340
+ return False
125
341
 
126
342
 
127
343
  def is_timestamp(value: Any) -> bool:
@@ -133,39 +349,86 @@ def is_timestamp(value: Any) -> bool:
133
349
 
134
350
  Returns:
135
351
  True if it conforms
352
+
353
+ Examples:
354
+ ```python
355
+ result = xmllib.is_timestamp("2019-10-23T13:45:12Z")
356
+ # result == True
357
+ ```
358
+
359
+ ```python
360
+ result = xmllib.is_timestamp("not a time stamp")
361
+ # result == False
362
+ ```
136
363
  """
137
- validation_regex = r"^\d{4}-[0-1]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d(.\d{1,12})?(Z|[+-][0-1]\d:[0-5]\d)$"
364
+ validation_regex = r"^\d{4}-[0-1]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d(\.\d{1,12})?(Z|[+-][0-1]\d:[0-5]\d)$"
138
365
  return bool(regex.search(validation_regex, str(value)))
139
366
 
140
367
 
141
- def find_geometry_problem(value: Any) -> str:
368
+ def is_dsp_iri(value: Any) -> bool:
142
369
  """
143
- Validates if a value is a valid geometry object.
370
+ Check if a value is a valid internal DSP IRI.
144
371
 
145
372
  Args:
146
- value: geometry object
373
+ value: IRI
147
374
 
148
375
  Returns:
149
- string with the validation message if it fails
376
+ True if it is valid, else false
377
+
378
+ Examples:
379
+ ```python
380
+ result = xmllib.is_dsp_iri("http://rdfh.ch/4123/54SYvWF0QUW6a")
381
+ # result == True
382
+ ```
383
+
384
+ ```python
385
+ result = xmllib.is_dsp_iri("http://dbpedia.org/resource/Internationalized_Resource_Identifier")
386
+ # result == False
387
+ ```
150
388
  """
151
- msg = ""
152
- try:
153
- value_as_dict = json.loads(str(value))
154
- if value_as_dict["type"] not in ["rectangle", "circle", "polygon"]:
155
- msg += "\nThe 'type' of the JSON geometry object must be 'rectangle', 'circle', or 'polygon'."
156
-
157
- if not isinstance(value_as_dict["points"], list):
158
- msg += "\nThe 'points' of the JSON geometry object must be a list of points."
159
- except (json.JSONDecodeError, TypeError, IndexError, KeyError, AssertionError):
160
- msg += f"\n'{value}' is not a valid JSON geometry object."
161
- return msg
389
+ return bool(regex.search(r"^http://rdfh\.ch/[\dA-F]{4}/", str(value)))
162
390
 
163
391
 
164
- def is_dsp_iri(value: Any) -> bool:
165
- """Checks if a value is a valid internal dsp IRI"""
166
- return bool(regex.search(r"^http://rdfh\.ch/\d{4}/", str(value)))
392
+ def is_dsp_ark(value: Any) -> bool:
393
+ """
394
+ Checks if a value is a valid ARK.
167
395
 
396
+ Args:
397
+ value: ARK
168
398
 
169
- def is_dsp_ark(value: Any) -> bool:
170
- """Checks if a value is a valid ARK"""
399
+ Returns:
400
+ True if it is valid, else false
401
+
402
+ Examples:
403
+ ```python
404
+ result = xmllib.is_dsp_ark("ark:/72163/4123-31ec6eab334-a.2022829")
405
+ # result == True
406
+ ```
407
+
408
+ ```python
409
+ result = xmllib.is_dsp_ark("http://rdfh.ch/4123/54SYvWF0QUW6a")
410
+ # result == False
411
+ ```
412
+ """
171
413
  return bool(regex.search(r"^ark:/", str(value)))
414
+
415
+
416
+ def check_richtext_syntax(richtext: str) -> None:
417
+ """
418
+ DSP richtexts must be convertible into valid XML.
419
+ This checker escapes the reserved characters `<`, `>` and `&`,
420
+ but only if they are not part of a standard standoff tag or escape sequence.
421
+ Then, it tries to parse the resulting XML.
422
+
423
+ Note: Only DSP standard standoff tags are allowed in richtexts. They are documented
424
+ [here](https://docs.dasch.swiss/latest/DSP-API/03-endpoints/api-v2/text/standard-standoff/).
425
+
426
+ Args:
427
+ richtext: richtext to check
428
+
429
+ Warns:
430
+ XmllibInputWarning: if the input contains XML syntax problems
431
+ """
432
+ result = parse_richtext_as_xml(richtext)
433
+ if isinstance(result, MessageInfo):
434
+ emit_xmllib_input_warning(result)