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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (348) hide show
  1. dsp_tools/__init__.py +5 -0
  2. dsp_tools/cli/args.py +47 -0
  3. dsp_tools/cli/call_action.py +85 -0
  4. dsp_tools/cli/call_action_files_only.py +101 -0
  5. dsp_tools/cli/call_action_with_network.py +207 -0
  6. dsp_tools/cli/create_parsers.py +479 -0
  7. dsp_tools/cli/entry_point.py +322 -0
  8. dsp_tools/cli/utils.py +87 -0
  9. dsp_tools/clients/CLAUDE.md +420 -0
  10. dsp_tools/clients/authentication_client.py +14 -0
  11. dsp_tools/clients/authentication_client_live.py +66 -0
  12. dsp_tools/clients/connection.py +35 -0
  13. dsp_tools/clients/connection_live.py +233 -0
  14. dsp_tools/clients/fuseki_metrics.py +60 -0
  15. dsp_tools/clients/group_user_clients.py +35 -0
  16. dsp_tools/clients/group_user_clients_live.py +181 -0
  17. dsp_tools/clients/legal_info_client.py +23 -0
  18. dsp_tools/clients/legal_info_client_live.py +132 -0
  19. dsp_tools/clients/list_client.py +49 -0
  20. dsp_tools/clients/list_client_live.py +166 -0
  21. dsp_tools/clients/metadata_client.py +24 -0
  22. dsp_tools/clients/metadata_client_live.py +47 -0
  23. dsp_tools/clients/ontology_clients.py +49 -0
  24. dsp_tools/clients/ontology_create_client_live.py +166 -0
  25. dsp_tools/clients/ontology_get_client_live.py +80 -0
  26. dsp_tools/clients/permissions_client.py +68 -0
  27. dsp_tools/clients/project_client.py +16 -0
  28. dsp_tools/clients/project_client_live.py +66 -0
  29. dsp_tools/commands/create/communicate_problems.py +24 -0
  30. dsp_tools/commands/create/create.py +134 -0
  31. dsp_tools/commands/create/create_on_server/cardinalities.py +111 -0
  32. dsp_tools/commands/create/create_on_server/classes.py +99 -0
  33. dsp_tools/commands/create/create_on_server/complete_ontologies.py +116 -0
  34. dsp_tools/commands/create/create_on_server/default_permissions.py +134 -0
  35. dsp_tools/commands/create/create_on_server/group_users.py +165 -0
  36. dsp_tools/commands/create/create_on_server/lists.py +163 -0
  37. dsp_tools/commands/create/create_on_server/mappers.py +12 -0
  38. dsp_tools/commands/create/create_on_server/onto_utils.py +74 -0
  39. dsp_tools/commands/create/create_on_server/ontology.py +52 -0
  40. dsp_tools/commands/create/create_on_server/project.py +68 -0
  41. dsp_tools/commands/create/create_on_server/properties.py +119 -0
  42. dsp_tools/commands/create/exceptions.py +29 -0
  43. dsp_tools/commands/create/lists_only.py +66 -0
  44. dsp_tools/commands/create/models/create_problems.py +87 -0
  45. dsp_tools/commands/create/models/parsed_ontology.py +88 -0
  46. dsp_tools/commands/create/models/parsed_project.py +81 -0
  47. dsp_tools/commands/create/models/rdf_ontology.py +12 -0
  48. dsp_tools/commands/create/models/server_project_info.py +100 -0
  49. dsp_tools/commands/create/parsing/parse_lists.py +45 -0
  50. dsp_tools/commands/create/parsing/parse_ontology.py +243 -0
  51. dsp_tools/commands/create/parsing/parse_project.py +149 -0
  52. dsp_tools/commands/create/parsing/parsing_utils.py +40 -0
  53. dsp_tools/commands/create/project_validate.py +595 -0
  54. dsp_tools/commands/create/serialisation/ontology.py +119 -0
  55. dsp_tools/commands/create/serialisation/project.py +44 -0
  56. dsp_tools/commands/excel2json/CLAUDE.md +101 -0
  57. dsp_tools/commands/excel2json/json_header.py +321 -0
  58. dsp_tools/commands/excel2json/lists/__init__.py +0 -0
  59. dsp_tools/commands/excel2json/lists/compliance_checks.py +292 -0
  60. dsp_tools/commands/excel2json/lists/make_lists.py +247 -0
  61. dsp_tools/commands/excel2json/lists/models/__init__.py +0 -0
  62. dsp_tools/commands/excel2json/lists/models/deserialise.py +30 -0
  63. dsp_tools/commands/excel2json/lists/models/input_error.py +216 -0
  64. dsp_tools/commands/excel2json/lists/models/serialise.py +57 -0
  65. dsp_tools/commands/excel2json/lists/utils.py +81 -0
  66. dsp_tools/commands/excel2json/models/__init__.py +0 -0
  67. dsp_tools/commands/excel2json/models/input_error.py +416 -0
  68. dsp_tools/commands/excel2json/models/json_header.py +175 -0
  69. dsp_tools/commands/excel2json/models/list_node_name.py +16 -0
  70. dsp_tools/commands/excel2json/models/ontology.py +76 -0
  71. dsp_tools/commands/excel2json/old_lists.py +328 -0
  72. dsp_tools/commands/excel2json/project.py +280 -0
  73. dsp_tools/commands/excel2json/properties.py +370 -0
  74. dsp_tools/commands/excel2json/resources.py +336 -0
  75. dsp_tools/commands/excel2json/utils.py +352 -0
  76. dsp_tools/commands/excel2xml/__init__.py +7 -0
  77. dsp_tools/commands/excel2xml/excel2xml_cli.py +523 -0
  78. dsp_tools/commands/excel2xml/excel2xml_lib.py +1953 -0
  79. dsp_tools/commands/excel2xml/propertyelement.py +47 -0
  80. dsp_tools/commands/get/__init__.py +0 -0
  81. dsp_tools/commands/get/get.py +166 -0
  82. dsp_tools/commands/get/get_permissions.py +257 -0
  83. dsp_tools/commands/get/get_permissions_legacy.py +89 -0
  84. dsp_tools/commands/get/legacy_models/__init__.py +0 -0
  85. dsp_tools/commands/get/legacy_models/context.py +318 -0
  86. dsp_tools/commands/get/legacy_models/group.py +241 -0
  87. dsp_tools/commands/get/legacy_models/helpers.py +47 -0
  88. dsp_tools/commands/get/legacy_models/listnode.py +390 -0
  89. dsp_tools/commands/get/legacy_models/model.py +12 -0
  90. dsp_tools/commands/get/legacy_models/ontology.py +324 -0
  91. dsp_tools/commands/get/legacy_models/project.py +366 -0
  92. dsp_tools/commands/get/legacy_models/propertyclass.py +417 -0
  93. dsp_tools/commands/get/legacy_models/resourceclass.py +676 -0
  94. dsp_tools/commands/get/legacy_models/user.py +438 -0
  95. dsp_tools/commands/get/models/__init__.py +0 -0
  96. dsp_tools/commands/get/models/permissions_models.py +10 -0
  97. dsp_tools/commands/id2iri.py +258 -0
  98. dsp_tools/commands/ingest_xmlupload/__init__.py +0 -0
  99. dsp_tools/commands/ingest_xmlupload/bulk_ingest_client.py +178 -0
  100. dsp_tools/commands/ingest_xmlupload/create_resources/__init__.py +0 -0
  101. dsp_tools/commands/ingest_xmlupload/create_resources/apply_ingest_id.py +69 -0
  102. dsp_tools/commands/ingest_xmlupload/create_resources/upload_xml.py +166 -0
  103. dsp_tools/commands/ingest_xmlupload/create_resources/user_information.py +121 -0
  104. dsp_tools/commands/ingest_xmlupload/ingest_files/__init__.py +0 -0
  105. dsp_tools/commands/ingest_xmlupload/ingest_files/ingest_files.py +64 -0
  106. dsp_tools/commands/ingest_xmlupload/upload_files/__init__.py +0 -0
  107. dsp_tools/commands/ingest_xmlupload/upload_files/filechecker.py +20 -0
  108. dsp_tools/commands/ingest_xmlupload/upload_files/input_error.py +57 -0
  109. dsp_tools/commands/ingest_xmlupload/upload_files/upload_failures.py +66 -0
  110. dsp_tools/commands/ingest_xmlupload/upload_files/upload_files.py +67 -0
  111. dsp_tools/commands/resume_xmlupload/__init__.py +0 -0
  112. dsp_tools/commands/resume_xmlupload/resume_xmlupload.py +96 -0
  113. dsp_tools/commands/start_stack.py +428 -0
  114. dsp_tools/commands/update_legal/CLAUDE.md +344 -0
  115. dsp_tools/commands/update_legal/__init__.py +0 -0
  116. dsp_tools/commands/update_legal/core.py +182 -0
  117. dsp_tools/commands/update_legal/csv_operations.py +135 -0
  118. dsp_tools/commands/update_legal/models.py +87 -0
  119. dsp_tools/commands/update_legal/xml_operations.py +247 -0
  120. dsp_tools/commands/validate_data/CLAUDE.md +159 -0
  121. dsp_tools/commands/validate_data/__init__.py +0 -0
  122. dsp_tools/commands/validate_data/constants.py +59 -0
  123. dsp_tools/commands/validate_data/mappers.py +143 -0
  124. dsp_tools/commands/validate_data/models/__init__.py +0 -0
  125. dsp_tools/commands/validate_data/models/api_responses.py +45 -0
  126. dsp_tools/commands/validate_data/models/input_problems.py +119 -0
  127. dsp_tools/commands/validate_data/models/rdf_like_data.py +117 -0
  128. dsp_tools/commands/validate_data/models/validation.py +106 -0
  129. dsp_tools/commands/validate_data/prepare_data/__init__.py +0 -0
  130. dsp_tools/commands/validate_data/prepare_data/get_rdf_like_data.py +296 -0
  131. dsp_tools/commands/validate_data/prepare_data/make_data_graph.py +91 -0
  132. dsp_tools/commands/validate_data/prepare_data/prepare_data.py +184 -0
  133. dsp_tools/commands/validate_data/process_validation_report/__init__.py +0 -0
  134. dsp_tools/commands/validate_data/process_validation_report/get_user_validation_message.py +358 -0
  135. dsp_tools/commands/validate_data/process_validation_report/query_validation_result.py +507 -0
  136. dsp_tools/commands/validate_data/process_validation_report/reformat_validation_results.py +150 -0
  137. dsp_tools/commands/validate_data/shacl_cli_validator.py +70 -0
  138. dsp_tools/commands/validate_data/sparql/__init__.py +0 -0
  139. dsp_tools/commands/validate_data/sparql/cardinality_shacl.py +209 -0
  140. dsp_tools/commands/validate_data/sparql/construct_shacl.py +92 -0
  141. dsp_tools/commands/validate_data/sparql/legal_info_shacl.py +36 -0
  142. dsp_tools/commands/validate_data/sparql/value_shacl.py +357 -0
  143. dsp_tools/commands/validate_data/utils.py +59 -0
  144. dsp_tools/commands/validate_data/validate_data.py +283 -0
  145. dsp_tools/commands/validate_data/validation/__init__.py +0 -0
  146. dsp_tools/commands/validate_data/validation/check_duplicate_files.py +55 -0
  147. dsp_tools/commands/validate_data/validation/check_for_unknown_classes.py +67 -0
  148. dsp_tools/commands/validate_data/validation/get_validation_report.py +94 -0
  149. dsp_tools/commands/validate_data/validation/validate_ontology.py +107 -0
  150. dsp_tools/commands/xmlupload/CLAUDE.md +292 -0
  151. dsp_tools/commands/xmlupload/__init__.py +0 -0
  152. dsp_tools/commands/xmlupload/iri_resolver.py +21 -0
  153. dsp_tools/commands/xmlupload/make_rdf_graph/__init__.py +0 -0
  154. dsp_tools/commands/xmlupload/make_rdf_graph/constants.py +63 -0
  155. dsp_tools/commands/xmlupload/make_rdf_graph/jsonld_utils.py +44 -0
  156. dsp_tools/commands/xmlupload/make_rdf_graph/make_file_value.py +77 -0
  157. dsp_tools/commands/xmlupload/make_rdf_graph/make_resource_and_values.py +114 -0
  158. dsp_tools/commands/xmlupload/make_rdf_graph/make_values.py +262 -0
  159. dsp_tools/commands/xmlupload/models/__init__.py +0 -0
  160. dsp_tools/commands/xmlupload/models/bitstream_info.py +18 -0
  161. dsp_tools/commands/xmlupload/models/formatted_text_value.py +10 -0
  162. dsp_tools/commands/xmlupload/models/ingest.py +143 -0
  163. dsp_tools/commands/xmlupload/models/input_problems.py +58 -0
  164. dsp_tools/commands/xmlupload/models/lookup_models.py +21 -0
  165. dsp_tools/commands/xmlupload/models/permission.py +45 -0
  166. dsp_tools/commands/xmlupload/models/permissions_parsed.py +93 -0
  167. dsp_tools/commands/xmlupload/models/processed/__init__.py +0 -0
  168. dsp_tools/commands/xmlupload/models/processed/file_values.py +29 -0
  169. dsp_tools/commands/xmlupload/models/processed/res.py +27 -0
  170. dsp_tools/commands/xmlupload/models/processed/values.py +101 -0
  171. dsp_tools/commands/xmlupload/models/rdf_models.py +26 -0
  172. dsp_tools/commands/xmlupload/models/upload_clients.py +14 -0
  173. dsp_tools/commands/xmlupload/models/upload_state.py +20 -0
  174. dsp_tools/commands/xmlupload/prepare_xml_input/__init__.py +0 -0
  175. dsp_tools/commands/xmlupload/prepare_xml_input/ark2iri.py +55 -0
  176. dsp_tools/commands/xmlupload/prepare_xml_input/get_processed_resources.py +252 -0
  177. dsp_tools/commands/xmlupload/prepare_xml_input/iiif_uri_validator.py +50 -0
  178. dsp_tools/commands/xmlupload/prepare_xml_input/list_client.py +120 -0
  179. dsp_tools/commands/xmlupload/prepare_xml_input/prepare_xml_input.py +67 -0
  180. dsp_tools/commands/xmlupload/prepare_xml_input/read_validate_xml_file.py +58 -0
  181. dsp_tools/commands/xmlupload/prepare_xml_input/transform_input_values.py +118 -0
  182. dsp_tools/commands/xmlupload/resource_create_client.py +25 -0
  183. dsp_tools/commands/xmlupload/richtext_id2iri.py +37 -0
  184. dsp_tools/commands/xmlupload/stash/__init__.py +0 -0
  185. dsp_tools/commands/xmlupload/stash/analyse_circular_reference_graph.py +236 -0
  186. dsp_tools/commands/xmlupload/stash/create_info_for_graph.py +53 -0
  187. dsp_tools/commands/xmlupload/stash/graph_models.py +87 -0
  188. dsp_tools/commands/xmlupload/stash/stash_circular_references.py +68 -0
  189. dsp_tools/commands/xmlupload/stash/stash_models.py +109 -0
  190. dsp_tools/commands/xmlupload/stash/upload_stashed_resptr_props.py +106 -0
  191. dsp_tools/commands/xmlupload/stash/upload_stashed_xml_texts.py +196 -0
  192. dsp_tools/commands/xmlupload/upload_config.py +76 -0
  193. dsp_tools/commands/xmlupload/write_diagnostic_info.py +27 -0
  194. dsp_tools/commands/xmlupload/xmlupload.py +516 -0
  195. dsp_tools/config/__init__.py +0 -0
  196. dsp_tools/config/logger_config.py +69 -0
  197. dsp_tools/config/warnings_config.py +32 -0
  198. dsp_tools/error/__init__.py +0 -0
  199. dsp_tools/error/custom_warnings.py +39 -0
  200. dsp_tools/error/exceptions.py +204 -0
  201. dsp_tools/error/problems.py +10 -0
  202. dsp_tools/error/xmllib_errors.py +20 -0
  203. dsp_tools/error/xmllib_warnings.py +54 -0
  204. dsp_tools/error/xmllib_warnings_util.py +159 -0
  205. dsp_tools/error/xsd_validation_error_msg.py +19 -0
  206. dsp_tools/legacy_models/__init__.py +0 -0
  207. dsp_tools/legacy_models/datetimestamp.py +81 -0
  208. dsp_tools/legacy_models/langstring.py +253 -0
  209. dsp_tools/legacy_models/projectContext.py +49 -0
  210. dsp_tools/py.typed +0 -0
  211. dsp_tools/resources/schema/data.xsd +648 -0
  212. dsp_tools/resources/schema/lists-only.json +72 -0
  213. dsp_tools/resources/schema/project.json +1258 -0
  214. dsp_tools/resources/schema/properties-only.json +874 -0
  215. dsp_tools/resources/schema/resources-only.json +140 -0
  216. dsp_tools/resources/start-stack/docker-compose.override-host.j2 +11 -0
  217. dsp_tools/resources/start-stack/docker-compose.override.yml +11 -0
  218. dsp_tools/resources/start-stack/docker-compose.yml +88 -0
  219. dsp_tools/resources/start-stack/dsp-app-config.json +45 -0
  220. dsp_tools/resources/start-stack/dsp-app-config.override-host.j2 +26 -0
  221. dsp_tools/resources/validate_data/api-shapes-resource-cardinalities.ttl +191 -0
  222. dsp_tools/resources/validate_data/api-shapes.ttl +804 -0
  223. dsp_tools/resources/validate_data/shacl-cli-image.yml +4 -0
  224. dsp_tools/resources/validate_data/validate-ontology.ttl +99 -0
  225. dsp_tools/utils/__init__.py +0 -0
  226. dsp_tools/utils/ansi_colors.py +32 -0
  227. dsp_tools/utils/data_formats/__init__.py +0 -0
  228. dsp_tools/utils/data_formats/date_util.py +166 -0
  229. dsp_tools/utils/data_formats/iri_util.py +30 -0
  230. dsp_tools/utils/data_formats/shared.py +81 -0
  231. dsp_tools/utils/data_formats/uri_util.py +76 -0
  232. dsp_tools/utils/fuseki_bloating.py +63 -0
  233. dsp_tools/utils/json_parsing.py +22 -0
  234. dsp_tools/utils/rdf_constants.py +42 -0
  235. dsp_tools/utils/rdflib_utils.py +10 -0
  236. dsp_tools/utils/replace_id_with_iri.py +66 -0
  237. dsp_tools/utils/request_utils.py +238 -0
  238. dsp_tools/utils/xml_parsing/__init__.py +0 -0
  239. dsp_tools/utils/xml_parsing/get_lookups.py +32 -0
  240. dsp_tools/utils/xml_parsing/get_parsed_resources.py +325 -0
  241. dsp_tools/utils/xml_parsing/models/__init__.py +0 -0
  242. dsp_tools/utils/xml_parsing/models/parsed_resource.py +76 -0
  243. dsp_tools/utils/xml_parsing/parse_clean_validate_xml.py +137 -0
  244. dsp_tools/xmllib/CLAUDE.md +302 -0
  245. dsp_tools/xmllib/__init__.py +49 -0
  246. dsp_tools/xmllib/general_functions.py +877 -0
  247. dsp_tools/xmllib/internal/__init__.py +0 -0
  248. dsp_tools/xmllib/internal/checkers.py +162 -0
  249. dsp_tools/xmllib/internal/circumvent_circular_imports.py +36 -0
  250. dsp_tools/xmllib/internal/constants.py +46 -0
  251. dsp_tools/xmllib/internal/input_converters.py +155 -0
  252. dsp_tools/xmllib/internal/serialise_file_value.py +57 -0
  253. dsp_tools/xmllib/internal/serialise_resource.py +177 -0
  254. dsp_tools/xmllib/internal/serialise_values.py +152 -0
  255. dsp_tools/xmllib/internal/type_aliases.py +11 -0
  256. dsp_tools/xmllib/models/__init__.py +0 -0
  257. dsp_tools/xmllib/models/config_options.py +28 -0
  258. dsp_tools/xmllib/models/date_formats.py +48 -0
  259. dsp_tools/xmllib/models/dsp_base_resources.py +1542 -0
  260. dsp_tools/xmllib/models/internal/__init__.py +0 -0
  261. dsp_tools/xmllib/models/internal/file_values.py +172 -0
  262. dsp_tools/xmllib/models/internal/geometry.py +162 -0
  263. dsp_tools/xmllib/models/internal/migration_metadata.py +55 -0
  264. dsp_tools/xmllib/models/internal/serialise_permissions.py +66 -0
  265. dsp_tools/xmllib/models/internal/values.py +342 -0
  266. dsp_tools/xmllib/models/licenses/__init__.py +0 -0
  267. dsp_tools/xmllib/models/licenses/other.py +59 -0
  268. dsp_tools/xmllib/models/licenses/recommended.py +107 -0
  269. dsp_tools/xmllib/models/permissions.py +41 -0
  270. dsp_tools/xmllib/models/res.py +1782 -0
  271. dsp_tools/xmllib/models/root.py +348 -0
  272. dsp_tools/xmllib/value_checkers.py +434 -0
  273. dsp_tools/xmllib/value_converters.py +777 -0
  274. dsp_tools-18.3.0.post13.dist-info/METADATA +90 -0
  275. dsp_tools-18.3.0.post13.dist-info/RECORD +286 -0
  276. dsp_tools-18.3.0.post13.dist-info/WHEEL +4 -0
  277. dsp_tools-18.3.0.post13.dist-info/entry_points.txt +3 -0
  278. dsp_tools-0.9.13.dist-info/LICENSE +0 -674
  279. dsp_tools-0.9.13.dist-info/METADATA +0 -144
  280. dsp_tools-0.9.13.dist-info/RECORD +0 -71
  281. dsp_tools-0.9.13.dist-info/WHEEL +0 -5
  282. dsp_tools-0.9.13.dist-info/entry_points.txt +0 -3
  283. dsp_tools-0.9.13.dist-info/top_level.txt +0 -1
  284. dsplib/models/connection.py +0 -272
  285. dsplib/models/group.py +0 -296
  286. dsplib/models/helpers.py +0 -505
  287. dsplib/models/langstring.py +0 -277
  288. dsplib/models/listnode.py +0 -578
  289. dsplib/models/model.py +0 -20
  290. dsplib/models/ontology.py +0 -448
  291. dsplib/models/permission.py +0 -112
  292. dsplib/models/project.py +0 -547
  293. dsplib/models/propertyclass.py +0 -505
  294. dsplib/models/resource.py +0 -366
  295. dsplib/models/resourceclass.py +0 -810
  296. dsplib/models/sipi.py +0 -30
  297. dsplib/models/user.py +0 -731
  298. dsplib/models/value.py +0 -1000
  299. dsplib/utils/knora-data-schema.xsd +0 -454
  300. dsplib/utils/knora-schema-lists.json +0 -83
  301. dsplib/utils/knora-schema.json +0 -434
  302. dsplib/utils/onto_commons.py +0 -24
  303. dsplib/utils/onto_create_lists.py +0 -73
  304. dsplib/utils/onto_create_ontology.py +0 -442
  305. dsplib/utils/onto_get.py +0 -58
  306. dsplib/utils/onto_validate.py +0 -33
  307. dsplib/utils/xml_upload.py +0 -539
  308. dsplib/widgets/doublepassword.py +0 -80
  309. knora/MLS-import-libraries.py +0 -84
  310. knora/dsp_tools.py +0 -96
  311. knora/dsplib/models/connection.py +0 -272
  312. knora/dsplib/models/group.py +0 -296
  313. knora/dsplib/models/helpers.py +0 -506
  314. knora/dsplib/models/langstring.py +0 -277
  315. knora/dsplib/models/listnode.py +0 -578
  316. knora/dsplib/models/model.py +0 -20
  317. knora/dsplib/models/ontology.py +0 -448
  318. knora/dsplib/models/permission.py +0 -112
  319. knora/dsplib/models/project.py +0 -583
  320. knora/dsplib/models/propertyclass.py +0 -505
  321. knora/dsplib/models/resource.py +0 -416
  322. knora/dsplib/models/resourceclass.py +0 -811
  323. knora/dsplib/models/sipi.py +0 -35
  324. knora/dsplib/models/user.py +0 -731
  325. knora/dsplib/models/value.py +0 -1000
  326. knora/dsplib/utils/knora-data-schema.xsd +0 -464
  327. knora/dsplib/utils/knora-schema-lists.json +0 -83
  328. knora/dsplib/utils/knora-schema.json +0 -444
  329. knora/dsplib/utils/onto_commons.py +0 -24
  330. knora/dsplib/utils/onto_create_lists.py +0 -73
  331. knora/dsplib/utils/onto_create_ontology.py +0 -451
  332. knora/dsplib/utils/onto_get.py +0 -58
  333. knora/dsplib/utils/onto_validate.py +0 -33
  334. knora/dsplib/utils/xml_upload.py +0 -540
  335. knora/dsplib/widgets/doublepassword.py +0 -80
  336. knora/knora.py +0 -2108
  337. knora/test.py +0 -99
  338. knora/testit.py +0 -76
  339. knora/xml2knora.py +0 -633
  340. {dsplib → dsp_tools/cli}/__init__.py +0 -0
  341. {dsplib/models → dsp_tools/clients}/__init__.py +0 -0
  342. {dsplib/utils → dsp_tools/commands}/__init__.py +0 -0
  343. {dsplib/widgets → dsp_tools/commands/create}/__init__.py +0 -0
  344. {knora → dsp_tools/commands/create/create_on_server}/__init__.py +0 -0
  345. {knora/dsplib → dsp_tools/commands/create/models}/__init__.py +0 -0
  346. {knora/dsplib/models → dsp_tools/commands/create/parsing}/__init__.py +0 -0
  347. {knora/dsplib/utils → dsp_tools/commands/create/serialisation}/__init__.py +0 -0
  348. {knora/dsplib/widgets → dsp_tools/commands/excel2json}/__init__.py +0 -0
@@ -0,0 +1,121 @@
1
+ from dataclasses import dataclass
2
+ from dataclasses import field
3
+ from pathlib import Path
4
+
5
+ import pandas as pd
6
+
7
+ separator = "\n "
8
+ list_separator = "\n - "
9
+
10
+
11
+ @dataclass(frozen=True)
12
+ class IngestInformation:
13
+ """
14
+ This class stores the information about the mapping of ids provided by the dsp-ingest service
15
+ and the filepaths used in the XML file.
16
+ """
17
+
18
+ unused_mediafiles: list[str]
19
+ mediafiles_no_id: list[tuple[str, str]]
20
+ maximum_prints: int = 20
21
+ csv_directory_path: Path = field(default=Path.cwd())
22
+ unused_mediafiles_csv: str = "UnusedMediaUploaded.csv"
23
+ mediafiles_no_id_csv: str = "FilesNotUploaded.csv"
24
+
25
+ def ok_msg(self) -> str | None:
26
+ """
27
+ This function checks if no media was unused or not uploaded.
28
+ If that is the case it returns the message,
29
+ if not, it ends without an effect.
30
+
31
+ Returns:
32
+ Message if all went well.
33
+ """
34
+ if not self.unused_mediafiles and not self.mediafiles_no_id:
35
+ return (
36
+ "All multimedia files referenced in the XML file were uploaded through dsp-ingest.\n"
37
+ "All multimedia files uploaded through dsp-ingest were referenced in the XML file."
38
+ )
39
+ return None
40
+
41
+ def execute_error_protocol(self) -> str:
42
+ """
43
+ This function generates the user message and saves a file with the information
44
+ if a lot of resources are affected.
45
+
46
+ Returns:
47
+ User message
48
+ """
49
+ self._save_csv_if_applicable()
50
+ return self._get_error_msg()
51
+
52
+ def _get_error_msg(self) -> str:
53
+ msg_list = [
54
+ "The upload cannot continue as there are problems with the multimedia files referenced in the XML.",
55
+ ]
56
+ if has_msg := self._get_unused_mediafiles_msg():
57
+ msg_list.append(has_msg)
58
+ if has_msg := self._get_mediafiles_no_id_msg():
59
+ msg_list.append(has_msg)
60
+ return separator.join(msg_list)
61
+
62
+ def _get_mediafiles_no_id_msg(self) -> str | None:
63
+ if 0 < len(self.mediafiles_no_id) <= self.maximum_prints:
64
+ return (
65
+ "The data XML file contains references to the following multimedia files "
66
+ "which were not previously uploaded through dsp-ingest:"
67
+ + list_separator
68
+ + list_separator.join([f"Resource ID: '{x[0]}' | Filepath: '{x[1]}'" for x in self.mediafiles_no_id])
69
+ )
70
+ elif len(self.mediafiles_no_id) > self.maximum_prints:
71
+ return (
72
+ "The data XML file contains references to multimedia files "
73
+ "which were not previously uploaded through dsp-ingest:\n"
74
+ f" The file with the resource IDs and problematic filenames was saved at "
75
+ f"'{Path(self.csv_directory_path / self.mediafiles_no_id_csv)}'."
76
+ )
77
+ return None
78
+
79
+ def _get_unused_mediafiles_msg(self) -> str | None:
80
+ if 0 < len(self.unused_mediafiles) <= self.maximum_prints:
81
+ return (
82
+ "The data XML file does not reference the following multimedia files which were previously "
83
+ "uploaded through dsp-ingest:" + list_separator + list_separator.join(self.unused_mediafiles)
84
+ )
85
+ elif len(self.unused_mediafiles) > self.maximum_prints:
86
+ return (
87
+ "The data XML file does not reference all the multimedia files which were previously "
88
+ "uploaded through dsp-ingest.\n"
89
+ f" The file with the unused filenames was saved at "
90
+ f"'{Path(self.csv_directory_path / self.unused_mediafiles_csv)}'."
91
+ )
92
+ return None
93
+
94
+ def _save_csv_if_applicable(self) -> None:
95
+ if (unused_mediafiles_df := self._unused_mediafiles_to_df()) is not None:
96
+ _save_as_csv(unused_mediafiles_df, self.csv_directory_path, self.unused_mediafiles_csv)
97
+ if (no_id_df := self._mediafiles_no_id_to_df()) is not None:
98
+ _save_as_csv(no_id_df, self.csv_directory_path, self.mediafiles_no_id_csv)
99
+
100
+ def _unused_mediafiles_to_df(self) -> pd.DataFrame | None:
101
+ return (
102
+ pd.DataFrame({"Multimedia Filenames": self.unused_mediafiles})
103
+ if len(self.unused_mediafiles) > self.maximum_prints
104
+ else None
105
+ )
106
+
107
+ def _mediafiles_no_id_to_df(self) -> pd.DataFrame | None:
108
+ return (
109
+ pd.DataFrame(
110
+ {
111
+ "Resource ID": [x[0] for x in self.mediafiles_no_id],
112
+ "Filepath": [x[1] for x in self.mediafiles_no_id],
113
+ }
114
+ )
115
+ if len(self.mediafiles_no_id) > self.maximum_prints
116
+ else None
117
+ )
118
+
119
+
120
+ def _save_as_csv(df: pd.DataFrame, directory_path: Path, filename: str) -> None:
121
+ df.to_csv(Path(directory_path, filename), index=False)
@@ -0,0 +1,64 @@
1
+ from pathlib import Path
2
+ from time import sleep
3
+ from typing import cast
4
+
5
+ from loguru import logger
6
+ from tqdm import tqdm
7
+
8
+ from dsp_tools.cli.args import ServerCredentials
9
+ from dsp_tools.clients.authentication_client_live import AuthenticationClientLive
10
+ from dsp_tools.commands.ingest_xmlupload.bulk_ingest_client import BulkIngestClient
11
+
12
+
13
+ def ingest_files(creds: ServerCredentials, shortcode: str) -> bool:
14
+ """
15
+ Kick off the ingest process on the server, and wait until it has finished.
16
+ Then, retrieve the mapping CSV from the server and save it in the CWD.
17
+
18
+ Args:
19
+ creds: credentials to log in on the server
20
+ shortcode: shortcode of the project
21
+
22
+ Returns:
23
+ success status
24
+ """
25
+ auth = AuthenticationClientLive(creds.server, creds.user, creds.password)
26
+ bulk_ingest_client = BulkIngestClient(creds.dsp_ingest_url, auth, shortcode)
27
+ bulk_ingest_client.trigger_ingest_process()
28
+ sleep(5)
29
+ mapping = _retrieve_mapping(bulk_ingest_client)
30
+ _save_mapping(mapping, shortcode)
31
+ return True
32
+
33
+
34
+ def _retrieve_mapping(bulk_ingest_client: BulkIngestClient) -> str:
35
+ sleeping_time = 60
36
+ desc = f"Wait until mapping CSV is ready. Ask server every {sleeping_time} seconds "
37
+ progress_bar = tqdm(
38
+ bulk_ingest_client.retrieve_mapping_generator(), desc=desc, bar_format="{desc}{elapsed}", dynamic_ncols=True
39
+ )
40
+ num_of_attempts = 0
41
+ num_of_server_errors = 0
42
+ for result in progress_bar:
43
+ if result is False:
44
+ num_of_attempts += 1
45
+ num_of_server_errors += 1
46
+ elif result is True:
47
+ num_of_attempts += 1
48
+ elif isinstance(result, str):
49
+ break
50
+ progress_bar.set_description(f"{desc}(attempts: {num_of_attempts}, server errors: {num_of_server_errors})")
51
+ sleep(sleeping_time)
52
+ return cast(str, result)
53
+
54
+
55
+ def _save_mapping(mapping: str, shortcode: str) -> None:
56
+ filepath = Path(f"mapping-{shortcode}.csv")
57
+ if filepath.exists():
58
+ i = 1
59
+ while (new_name_for_existing := Path(f"mapping-{shortcode}-{i}.csv")).exists():
60
+ i += 1
61
+ filepath.rename(new_name_for_existing)
62
+ filepath.write_text(mapping, encoding="utf-8")
63
+ print(f"Saved mapping CSV to '{filepath}'")
64
+ logger.info(f"Saved mapping CSV to '{filepath}'")
@@ -0,0 +1,20 @@
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import Iterable
4
+ from pathlib import Path
5
+
6
+ from dsp_tools.commands.ingest_xmlupload.upload_files.input_error import FileProblems
7
+
8
+ SUPPORTED_EXTENSIONS = (
9
+ "zip,tar,gz,z,tgz,gzip,7z,mp3,wav,pdf,doc,docx,xls,xlsx,ppt,pptx,epub,"
10
+ "mp4,jpg,jpeg,jp2,json,png,tif,tiff,odd,rng,txt,xml,htm,html,xsd,xsl,csv"
11
+ ).split(",")
12
+
13
+
14
+ def check_files(files: Iterable[Path]) -> FileProblems | None:
15
+ """Check if the files exist and have supported extensions."""
16
+ unsupported_files = [file for file in files if file.suffix[1:].casefold() not in SUPPORTED_EXTENSIONS]
17
+ non_existing_files = [file for file in files if not file.exists() and file not in unsupported_files]
18
+ if non_existing_files or unsupported_files:
19
+ return FileProblems(non_existing_files, unsupported_files)
20
+ return None
@@ -0,0 +1,57 @@
1
+ from dataclasses import dataclass
2
+ from pathlib import Path
3
+
4
+ import pandas as pd
5
+
6
+ from dsp_tools.error.problems import Problem
7
+
8
+ separator = "\n\n"
9
+ list_separator = "\n - "
10
+
11
+
12
+ @dataclass(frozen=True)
13
+ class FileProblems(Problem):
14
+ """Handle the error communication to the user in case that some files don't exist or are unsupported."""
15
+
16
+ non_existing_files: list[Path]
17
+ unsupported_files: list[Path]
18
+ maximum_prints: int = 50
19
+
20
+ def __post_init__(self) -> None:
21
+ if not self.non_existing_files and not self.unsupported_files:
22
+ raise ValueError("It's not possible to create a FileProblems object without any problems.")
23
+
24
+ def execute_error_protocol(self) -> str:
25
+ """
26
+ Generate the error message to communicate the problems to the user.
27
+ If there are too many problems, save them to a file.
28
+
29
+ Returns:
30
+ error message
31
+ """
32
+ msg = "Some files referenced in the <bitstream> tags of your XML file cannot be uploaded to the server."
33
+ if len(self.non_existing_files) + len(self.unsupported_files) > self.maximum_prints:
34
+ output_file = Path("file_problems.csv")
35
+ self._save_to_csv(output_file)
36
+ msg += f" The full list of files with problems has been saved to '{output_file}'."
37
+ return msg
38
+ if self.non_existing_files:
39
+ msg += separator
40
+ msg += "The following files don't exist on your computer:"
41
+ msg += list_separator + list_separator.join([str(file) for file in self.non_existing_files])
42
+ if self.unsupported_files:
43
+ msg += separator
44
+ msg += "The following files have unsupported extensions:"
45
+ msg += list_separator + list_separator.join([str(file) for file in self.unsupported_files])
46
+ return msg
47
+
48
+ def _save_to_csv(self, output_file: Path) -> None:
49
+ problems = ["File doesn't exist"] * len(self.non_existing_files) + ["Extension not supported"] * len(
50
+ self.unsupported_files
51
+ )
52
+ data = {
53
+ "File": self.non_existing_files + self.unsupported_files,
54
+ "Problem": problems,
55
+ }
56
+ df = pd.DataFrame(data)
57
+ df.to_csv(output_file, index=False)
@@ -0,0 +1,66 @@
1
+ from dataclasses import dataclass
2
+ from pathlib import Path
3
+
4
+ import pandas as pd
5
+ import regex
6
+
7
+ separator = "\n\n"
8
+ list_separator = "\n- "
9
+ list_separator_indented = "\n - "
10
+
11
+
12
+ @dataclass(frozen=True)
13
+ class UploadFailure:
14
+ """Information on why the upload of a file to the ingest server failed."""
15
+
16
+ filepath: Path
17
+ reason: str
18
+ status_code: int | None = None
19
+ response_text: str | None = None
20
+
21
+
22
+ @dataclass(frozen=True)
23
+ class UploadFailures:
24
+ """Aggregated information of all failed uploads."""
25
+
26
+ failures: list[UploadFailure]
27
+ num_of_initial_files: int
28
+ shortcode: str
29
+ dsp_ingest_url: str
30
+ maximum_prints: int = 50
31
+
32
+ def execute_error_protocol(self) -> str:
33
+ """
34
+ Generate the error message to communicate the problems to the user.
35
+ If there are too many problems, save them to a file.
36
+
37
+ Returns:
38
+ error message
39
+ """
40
+ ratio = f"{self.num_of_initial_files - len(self.failures)}/{self.num_of_initial_files}"
41
+ msg = f"Uploaded {ratio} files onto server {self.dsp_ingest_url}. "
42
+ if len(self.failures) > self.maximum_prints:
43
+ url = regex.sub(r"https?://", "", self.dsp_ingest_url)
44
+ output_file = Path(f"upload_failures_{self.shortcode}_{url}.csv")
45
+ self._save_to_csv(output_file)
46
+ msg += f"Failed to upload {len(self.failures)} files. "
47
+ msg += f"The full list of failed files has been saved to '{output_file}'."
48
+ else:
49
+ msg += f"Failed to upload the following {len(self.failures)} files:"
50
+ for f in self.failures:
51
+ msg += list_separator + f"{f.filepath}: {f.reason}"
52
+ if f.status_code:
53
+ msg += list_separator_indented + f"Status code: {f.status_code}"
54
+ if f.response_text:
55
+ msg += list_separator_indented + f"Response text: {f.response_text}"
56
+ return msg
57
+
58
+ def _save_to_csv(self, output_file: Path) -> None:
59
+ data = {
60
+ "Filepath": [failure.filepath for failure in self.failures],
61
+ "Reason": [failure.reason for failure in self.failures],
62
+ "Status code": [failure.status_code for failure in self.failures],
63
+ "Response text": [failure.response_text for failure in self.failures],
64
+ }
65
+ df = pd.DataFrame(data)
66
+ df.to_csv(output_file, index=False)
@@ -0,0 +1,67 @@
1
+ from pathlib import Path
2
+
3
+ from loguru import logger
4
+ from lxml import etree
5
+ from tqdm import tqdm
6
+
7
+ from dsp_tools.cli.args import ServerCredentials
8
+ from dsp_tools.clients.authentication_client_live import AuthenticationClientLive
9
+ from dsp_tools.commands.ingest_xmlupload.bulk_ingest_client import BulkIngestClient
10
+ from dsp_tools.commands.ingest_xmlupload.upload_files.filechecker import check_files
11
+ from dsp_tools.commands.ingest_xmlupload.upload_files.upload_failures import UploadFailure
12
+ from dsp_tools.commands.ingest_xmlupload.upload_files.upload_failures import UploadFailures
13
+ from dsp_tools.error.exceptions import InputError
14
+ from dsp_tools.utils.xml_parsing.parse_clean_validate_xml import parse_and_clean_xml_file
15
+
16
+
17
+ def upload_files(
18
+ xml_file: Path,
19
+ creds: ServerCredentials,
20
+ imgdir: Path = Path.cwd(),
21
+ ) -> bool:
22
+ """
23
+ Upload all files referenced in an XML file to the ingest server.
24
+ This involves no processing/ingesting of the files, just uploading them.
25
+
26
+ Args:
27
+ xml_file: XML file containing the resources and the references to the files to upload
28
+ creds: credentials to connect to the ingest server
29
+ imgdir: the bitstreams in the XML file are relative to this directory
30
+
31
+ Returns:
32
+ success status
33
+ """
34
+ root = parse_and_clean_xml_file(xml_file)
35
+ shortcode = root.attrib["shortcode"]
36
+ paths = _get_validated_paths(root)
37
+ print(f"Found {len(paths)} files to upload onto server {creds.dsp_ingest_url}.")
38
+ logger.info(f"Found {len(paths)} files to upload onto server {creds.dsp_ingest_url}.")
39
+
40
+ auth = AuthenticationClientLive(creds.server, creds.user, creds.password)
41
+ ingest_client = BulkIngestClient(creds.dsp_ingest_url, auth, shortcode, imgdir)
42
+
43
+ failures: list[UploadFailure] = []
44
+ progress_bar = tqdm(paths, desc="Uploading files", unit="file(s)", dynamic_ncols=True)
45
+ for path in progress_bar:
46
+ if res := ingest_client.upload_file(path):
47
+ failures.append(res)
48
+ progress_bar.set_description(f"Uploading files (failed: {len(failures)})")
49
+ if failures:
50
+ aggregated_failures = UploadFailures(failures, len(paths), shortcode, creds.dsp_ingest_url)
51
+ msg = aggregated_failures.execute_error_protocol()
52
+ logger.error(msg)
53
+ print(msg)
54
+ return False
55
+ else:
56
+ msg = f"Uploaded all {len(paths)} files onto server {creds.dsp_ingest_url}."
57
+ logger.info(msg)
58
+ print(msg)
59
+ return True
60
+
61
+
62
+ def _get_validated_paths(root: etree._Element) -> set[Path]:
63
+ paths = {Path(x.text.strip()) for x in root.xpath("//bitstream")}
64
+ if problems := check_files(paths):
65
+ msg = problems.execute_error_protocol()
66
+ raise InputError(msg)
67
+ return paths
File without changes
@@ -0,0 +1,96 @@
1
+ import pickle
2
+ import sys
3
+
4
+ from loguru import logger
5
+
6
+ from dsp_tools.cli.args import ServerCredentials
7
+ from dsp_tools.clients.authentication_client_live import AuthenticationClientLive
8
+ from dsp_tools.clients.connection_live import ConnectionLive
9
+ from dsp_tools.clients.legal_info_client import LegalInfoClient
10
+ from dsp_tools.clients.legal_info_client_live import LegalInfoClientLive
11
+ from dsp_tools.clients.project_client import ProjectClient
12
+ from dsp_tools.clients.project_client_live import ProjectClientLive
13
+ from dsp_tools.commands.xmlupload.models.ingest import AssetClient
14
+ from dsp_tools.commands.xmlupload.models.ingest import BulkIngestedAssetClient
15
+ from dsp_tools.commands.xmlupload.models.ingest import DspIngestClientLive
16
+ from dsp_tools.commands.xmlupload.models.upload_clients import UploadClients
17
+ from dsp_tools.commands.xmlupload.models.upload_state import UploadState
18
+ from dsp_tools.commands.xmlupload.prepare_xml_input.list_client import ListClient
19
+ from dsp_tools.commands.xmlupload.prepare_xml_input.list_client import ListClientLive
20
+ from dsp_tools.commands.xmlupload.upload_config import UploadConfig
21
+ from dsp_tools.commands.xmlupload.xmlupload import execute_upload
22
+ from dsp_tools.utils.ansi_colors import RED
23
+ from dsp_tools.utils.ansi_colors import RESET_TO_DEFAULT
24
+
25
+
26
+ def resume_xmlupload(creds: ServerCredentials, skip_first_resource: bool = False) -> bool:
27
+ """
28
+ Resume an interrupted xmlupload.
29
+
30
+ Args:
31
+ creds: credentials to access the DSP server
32
+ skip_first_resource: if this flag is set, the first resource of the pending resources is removed
33
+
34
+ Returns:
35
+ True if all resources could be uploaded without errors; False if one of the resources could not be
36
+ uploaded because there is an error in it
37
+ """
38
+ server = creds.server
39
+ upload_state = _read_upload_state_from_disk(server)
40
+ if skip_first_resource:
41
+ _skip_first_resource(upload_state)
42
+
43
+ _print_and_log(upload_state, server)
44
+
45
+ auth = AuthenticationClientLive(server, creds.user, creds.password)
46
+ con = ConnectionLive(server, auth)
47
+
48
+ ingest_client: AssetClient
49
+ if upload_state.config.media_previously_uploaded:
50
+ ingest_client = BulkIngestedAssetClient()
51
+ else:
52
+ ingest_client = DspIngestClientLive(creds.dsp_ingest_url, auth, upload_state.config.shortcode, ".")
53
+
54
+ project_client: ProjectClient = ProjectClientLive(auth.server, auth)
55
+ list_client: ListClient = ListClientLive(con, project_client.get_project_iri(upload_state.config.shortcode))
56
+ legal_info_client: LegalInfoClient = LegalInfoClientLive(server, upload_state.config.shortcode, auth)
57
+ clients = UploadClients(ingest_client, list_client, legal_info_client)
58
+
59
+ return execute_upload(clients, upload_state)
60
+
61
+
62
+ def _read_upload_state_from_disk(server: str) -> UploadState:
63
+ save_location = UploadConfig().with_server_info(server, "foo").diagnostics.save_location
64
+ with open(save_location, "rb") as f:
65
+ saved_state: UploadState = pickle.load(f) # noqa: S301 (deserialization of untrusted data)
66
+ return saved_state
67
+
68
+
69
+ def _skip_first_resource(upload_state: UploadState) -> None:
70
+ if len(upload_state.pending_resources) > 0:
71
+ upload_state.pending_resources.pop(0)
72
+ else:
73
+ msg = (
74
+ "The list of pending resources is empty.\n"
75
+ "It is not yet possible to skip the first item of the stashed properties.\n"
76
+ "Do you want to continue with the upload of the stashed properties anyway? [y/n]"
77
+ )
78
+ resp = None
79
+ while resp not in ["y", "n"]:
80
+ resp = input(RED + msg + RESET_TO_DEFAULT)
81
+ if resp == "n":
82
+ sys.exit(1)
83
+
84
+
85
+ def _print_and_log(upload_state: UploadState, server: str) -> None:
86
+ previous_successful = len(upload_state.iri_resolver.lookup)
87
+ previous_failed = len(upload_state.failed_uploads)
88
+ previous_total = previous_successful + previous_failed
89
+ msg = (
90
+ f"Resuming upload for project {upload_state.config.shortcode} on server {server}. "
91
+ f"Number of resources uploaded until now: {previous_total}"
92
+ )
93
+ if previous_failed:
94
+ msg += f" ({previous_failed} of them failed)"
95
+ logger.info(msg)
96
+ print("\n==========================\n" + msg + "\n==========================\n")