edu-rdm-integration 3.9.1__py3-none-any.whl → 3.10.0__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 (279) hide show
  1. edu_rdm_integration/__init__.py +0 -1
  2. edu_rdm_integration/adapters/apps.py +15 -2
  3. edu_rdm_integration/adapters/caches.py +25 -12
  4. edu_rdm_integration/adapters/errors.py +13 -2
  5. edu_rdm_integration/adapters/functions.py +53 -14
  6. edu_rdm_integration/adapters/helpers.py +34 -8
  7. edu_rdm_integration/adapters/managers.py +41 -5
  8. edu_rdm_integration/adapters/presenters.py +26 -2
  9. edu_rdm_integration/adapters/receivers.py +16 -2
  10. edu_rdm_integration/adapters/results.py +50 -4
  11. edu_rdm_integration/adapters/runners.py +79 -20
  12. edu_rdm_integration/adapters/strategies.py +56 -54
  13. edu_rdm_integration/adapters/validators.py +43 -4
  14. edu_rdm_integration/apps.py +3 -23
  15. edu_rdm_integration/collect_and_export_data/__init__.py +1 -1
  16. edu_rdm_integration/collect_and_export_data/apps.py +1 -0
  17. edu_rdm_integration/collect_and_export_data/migrations/0001_initial.py +107 -17
  18. edu_rdm_integration/collect_and_export_data/migrations/0002_auto_20250204_1413.py +4 -2
  19. edu_rdm_integration/{consts.py → core/consts.py} +0 -11
  20. edu_rdm_integration/{enums.py → core/enums.py} +7 -54
  21. edu_rdm_integration/core/helpers.py +331 -0
  22. edu_rdm_integration/core/operations.py +71 -0
  23. edu_rdm_integration/core/redis_cache.py +20 -0
  24. edu_rdm_integration/{collect_and_export_data → core/registry}/actions.py +6 -12
  25. edu_rdm_integration/core/registry/apps.py +11 -0
  26. edu_rdm_integration/{collect_and_export_data → core/registry}/ui.py +1 -1
  27. edu_rdm_integration/{storages.py → core/storages.py} +8 -17
  28. edu_rdm_integration/{utils.py → core/utils.py} +29 -91
  29. edu_rdm_integration/migrations/0001_initial.py +294 -44
  30. edu_rdm_integration/migrations/0002_init_data_uploadstatus.py +1 -3
  31. edu_rdm_integration/migrations/0003_create_index_file_upload_status.py +0 -1
  32. edu_rdm_integration/migrations/0004_uploaderclientlog.py +1 -2
  33. edu_rdm_integration/migrations/0005_auto_20231204_1224.py +16 -4
  34. edu_rdm_integration/migrations/0006_request_status_data.py +60 -58
  35. edu_rdm_integration/migrations/0007_delete_upload_status.py +0 -1
  36. edu_rdm_integration/migrations/0009_auto_20240522_1619.py +1 -5
  37. edu_rdm_integration/migrations/0010_transferredentity_export_enabled.py +0 -1
  38. edu_rdm_integration/migrations/0011_exportingdatasubstageentity.py +16 -3
  39. edu_rdm_integration/migrations/0012_exportingdatasubstageattachment_attachment_size.py +0 -1
  40. edu_rdm_integration/migrations/0013_set_attachment_size.py +8 -12
  41. edu_rdm_integration/migrations/0014_uploaddatacommand.py +33 -6
  42. edu_rdm_integration/migrations/0015_set_exporting_sub_stage_status.py +1 -5
  43. edu_rdm_integration/migrations/0016_transferredentity_queue_level.py +2 -2
  44. edu_rdm_integration/migrations/0017_delete_uploaddatacommand.py +3 -2
  45. edu_rdm_integration/migrations/__init__.py +1 -0
  46. edu_rdm_integration/{registry → pipelines/transfer}/actions.py +13 -26
  47. edu_rdm_integration/pipelines/transfer/app_meta.py +18 -0
  48. edu_rdm_integration/pipelines/transfer/apps.py +19 -0
  49. edu_rdm_integration/pipelines/transfer/enums.py +34 -0
  50. edu_rdm_integration/pipelines/transfer/migrations/0001_initial.py +57 -0
  51. edu_rdm_integration/{base.py → pipelines/transfer/mixins.py} +29 -53
  52. edu_rdm_integration/pipelines/transfer/models.py +48 -0
  53. edu_rdm_integration/{tasks.py → pipelines/transfer/tasks.py} +51 -150
  54. edu_rdm_integration/{registry → pipelines/transfer}/ui.py +4 -10
  55. edu_rdm_integration/rdm_entities/apps.py +11 -0
  56. edu_rdm_integration/{entities.py → rdm_entities/entities.py} +67 -57
  57. edu_rdm_integration/rdm_entities/migrations/0001_initial.py +44 -0
  58. edu_rdm_integration/{enum_register → rdm_entities}/mixins.py +8 -59
  59. edu_rdm_integration/rdm_entities/models.py +63 -0
  60. edu_rdm_integration/rdm_entities/utils.py +33 -0
  61. edu_rdm_integration/rdm_models/apps.py +16 -0
  62. edu_rdm_integration/rdm_models/migrations/0001_initial.py +40 -0
  63. edu_rdm_integration/rdm_models/mixins.py +67 -0
  64. edu_rdm_integration/rdm_models/models.py +73 -0
  65. edu_rdm_integration/rdm_models/utils.py +23 -0
  66. edu_rdm_integration/stages/collect_data/apps.py +11 -0
  67. edu_rdm_integration/{function_templates → stages/collect_data/function_templates}/function_collect_data_template/functions.py-tpl +2 -2
  68. edu_rdm_integration/{function_templates → stages/collect_data/function_templates}/function_collect_data_template/managers.py-tpl +1 -1
  69. edu_rdm_integration/{function_templates → stages/collect_data/function_templates}/function_collect_data_template/runners.py-tpl +1 -1
  70. edu_rdm_integration/{function_templates → stages/collect_data/function_templates}/function_collect_data_template/tests.py-tpl +2 -1
  71. edu_rdm_integration/{collect_data → stages/collect_data/functions}/base/caches.py +2 -2
  72. edu_rdm_integration/{collect_data → stages/collect_data/functions}/base/functions.py +15 -18
  73. edu_rdm_integration/stages/collect_data/functions/base/helpers.py +20 -0
  74. edu_rdm_integration/{collect_data → stages/collect_data/functions}/base/managers.py +20 -27
  75. edu_rdm_integration/{collect_data → stages/collect_data/functions}/base/mixins.py +38 -55
  76. edu_rdm_integration/{collect_data → stages/collect_data/functions}/base/runners.py +2 -5
  77. edu_rdm_integration/stages/collect_data/functions/calculated/base/__init__.py +0 -0
  78. edu_rdm_integration/{collect_data → stages/collect_data/functions}/calculated/base/caches.py +3 -7
  79. edu_rdm_integration/stages/collect_data/functions/calculated/base/errors.py +7 -0
  80. edu_rdm_integration/{collect_data → stages/collect_data/functions}/calculated/base/functions.py +8 -16
  81. edu_rdm_integration/stages/collect_data/functions/calculated/base/helpers.py +24 -0
  82. edu_rdm_integration/stages/collect_data/functions/calculated/base/managers.py +19 -0
  83. edu_rdm_integration/{collect_data → stages/collect_data/functions}/calculated/base/presenters.py +1 -3
  84. edu_rdm_integration/stages/collect_data/functions/calculated/base/results.py +12 -0
  85. edu_rdm_integration/stages/collect_data/functions/calculated/base/runners.py +28 -0
  86. edu_rdm_integration/stages/collect_data/functions/calculated/base/validators.py +20 -0
  87. edu_rdm_integration/{collect_data → stages/collect_data/functions}/calculated/strategies.py +32 -70
  88. edu_rdm_integration/stages/collect_data/functions/non_calculated/__init__.py +0 -0
  89. edu_rdm_integration/stages/collect_data/functions/non_calculated/base/__init__.py +0 -0
  90. edu_rdm_integration/{collect_data → stages/collect_data/functions}/non_calculated/base/caches.py +13 -22
  91. edu_rdm_integration/stages/collect_data/functions/non_calculated/base/errors.py +7 -0
  92. edu_rdm_integration/{collect_data → stages/collect_data/functions}/non_calculated/base/functions.py +8 -16
  93. edu_rdm_integration/stages/collect_data/functions/non_calculated/base/helpers.py +24 -0
  94. edu_rdm_integration/stages/collect_data/functions/non_calculated/base/managers.py +19 -0
  95. edu_rdm_integration/{collect_data → stages/collect_data/functions}/non_calculated/base/presenters.py +1 -3
  96. edu_rdm_integration/stages/collect_data/functions/non_calculated/base/results.py +12 -0
  97. edu_rdm_integration/stages/collect_data/functions/non_calculated/base/runners.py +28 -0
  98. edu_rdm_integration/stages/collect_data/functions/non_calculated/base/validators.py +20 -0
  99. edu_rdm_integration/{collect_data → stages/collect_data/functions}/non_calculated/strategies.py +32 -70
  100. edu_rdm_integration/{collect_data → stages/collect_data}/generators.py +9 -14
  101. edu_rdm_integration/stages/collect_data/helpers.py +154 -0
  102. edu_rdm_integration/stages/collect_data/management/__init__.py +0 -0
  103. edu_rdm_integration/stages/collect_data/management/base.py +100 -0
  104. edu_rdm_integration/stages/collect_data/management/commands/__init__.py +0 -0
  105. edu_rdm_integration/{management → stages/collect_data/management}/commands/collect_latest_models_data.py +5 -7
  106. edu_rdm_integration/{management → stages/collect_data/management}/commands/collect_models_data.py +5 -7
  107. edu_rdm_integration/stages/collect_data/migrations/0001_initial.py +187 -0
  108. edu_rdm_integration/stages/collect_data/migrations/0002_edurdmcollectdatacommandprogress.py +105 -0
  109. edu_rdm_integration/stages/collect_data/migrations/__init__.py +0 -0
  110. edu_rdm_integration/stages/collect_data/mixins.py +56 -0
  111. edu_rdm_integration/stages/collect_data/models.py +318 -0
  112. edu_rdm_integration/{collect_data/collect.py → stages/collect_data/operations.py} +30 -43
  113. edu_rdm_integration/stages/collect_data/registry/__init__.py +0 -0
  114. edu_rdm_integration/{collect_data → stages/collect_data/registry}/actions.py +17 -20
  115. edu_rdm_integration/stages/collect_data/registry/apps.py +11 -0
  116. edu_rdm_integration/{collect_data → stages/collect_data/registry}/ui.py +8 -15
  117. edu_rdm_integration/{collect_data → stages/collect_data}/tests.py +2 -2
  118. edu_rdm_integration/stages/export_data/__init__.py +0 -0
  119. edu_rdm_integration/stages/export_data/apps.py +11 -0
  120. edu_rdm_integration/stages/export_data/function_templates/__init__.py +0 -0
  121. edu_rdm_integration/{function_templates → stages/export_data/function_templates}/function_export_data_template/functions.py-tpl +2 -2
  122. edu_rdm_integration/{function_templates → stages/export_data/function_templates}/function_export_data_template/managers.py-tpl +2 -2
  123. edu_rdm_integration/{function_templates → stages/export_data/function_templates}/function_export_data_template/runners.py-tpl +2 -2
  124. edu_rdm_integration/stages/export_data/functions/__init__.py +0 -0
  125. edu_rdm_integration/stages/export_data/functions/base/__init__.py +0 -0
  126. edu_rdm_integration/{export_data → stages/export_data/functions}/base/caches.py +3 -8
  127. edu_rdm_integration/stages/export_data/functions/base/errors.py +7 -0
  128. edu_rdm_integration/{export_data → stages/export_data/functions}/base/functions.py +28 -59
  129. edu_rdm_integration/{export_data → stages/export_data/functions}/base/helpers.py +7 -17
  130. edu_rdm_integration/{export_data → stages/export_data/functions}/base/managers.py +19 -28
  131. edu_rdm_integration/stages/export_data/functions/base/presenters.py +11 -0
  132. edu_rdm_integration/{export_data → stages/export_data/functions}/base/requests.py +13 -40
  133. edu_rdm_integration/stages/export_data/functions/base/results.py +12 -0
  134. edu_rdm_integration/{export_data → stages/export_data/functions}/base/runners.py +9 -21
  135. edu_rdm_integration/stages/export_data/functions/base/validators.py +20 -0
  136. edu_rdm_integration/{export_data → stages/export_data}/generators.py +7 -6
  137. edu_rdm_integration/stages/export_data/helpers.py +203 -0
  138. edu_rdm_integration/stages/export_data/management/__init__.py +0 -0
  139. edu_rdm_integration/stages/export_data/management/base.py +101 -0
  140. edu_rdm_integration/stages/export_data/management/commands/__init__.py +0 -0
  141. edu_rdm_integration/{management → stages/export_data/management}/commands/export_entities_data.py +5 -7
  142. edu_rdm_integration/{management → stages/export_data/management}/commands/export_latest_entities_data.py +5 -7
  143. edu_rdm_integration/stages/export_data/migrations/0001_initial.py +324 -0
  144. edu_rdm_integration/stages/export_data/migrations/__init__.py +0 -0
  145. edu_rdm_integration/stages/export_data/mixins.py +50 -0
  146. edu_rdm_integration/stages/export_data/models.py +362 -0
  147. edu_rdm_integration/{export_data/export.py → stages/export_data/operations.py} +30 -192
  148. edu_rdm_integration/stages/export_data/registry/__init__.py +0 -0
  149. edu_rdm_integration/{export_data → stages/export_data/registry}/actions.py +18 -18
  150. edu_rdm_integration/stages/export_data/registry/apps.py +11 -0
  151. edu_rdm_integration/{export_data → stages/export_data/registry}/ui.py +5 -7
  152. edu_rdm_integration/{export_data → stages/export_data}/strategies.py +30 -68
  153. edu_rdm_integration/stages/service/__init__.py +0 -0
  154. edu_rdm_integration/stages/service/apps.py +19 -0
  155. edu_rdm_integration/stages/service/tasks.py +63 -0
  156. edu_rdm_integration/stages/upload_data/__init__.py +0 -0
  157. edu_rdm_integration/stages/upload_data/apps.py +19 -0
  158. edu_rdm_integration/stages/upload_data/consts.py +10 -0
  159. edu_rdm_integration/{export_data → stages/upload_data}/dataclasses.py +1 -0
  160. edu_rdm_integration/stages/upload_data/enums.py +17 -0
  161. edu_rdm_integration/{export_data/export_manager.py → stages/upload_data/export_managers.py} +73 -68
  162. edu_rdm_integration/stages/upload_data/helpers.py +164 -0
  163. edu_rdm_integration/stages/upload_data/management/__init__.py +0 -0
  164. edu_rdm_integration/stages/upload_data/management/base.py +134 -0
  165. edu_rdm_integration/stages/upload_data/management/commands/__init__.py +0 -0
  166. edu_rdm_integration/{management → stages/upload_data/management}/commands/async_fix_attachment_size.py +32 -54
  167. edu_rdm_integration/{management → stages/upload_data/management}/commands/check_upload_status.py +7 -6
  168. edu_rdm_integration/{management → stages/upload_data/management}/commands/datamart_status.py +3 -3
  169. edu_rdm_integration/{management → stages/upload_data/management}/commands/datamart_upload.py +4 -4
  170. edu_rdm_integration/stages/upload_data/migrations/0001_initial.py +161 -0
  171. edu_rdm_integration/stages/upload_data/migrations/__init__.py +0 -0
  172. edu_rdm_integration/stages/upload_data/models.py +175 -0
  173. edu_rdm_integration/stages/upload_data/operations.py +156 -0
  174. edu_rdm_integration/{export_data/queue.py → stages/upload_data/queues.py} +10 -8
  175. edu_rdm_integration/stages/upload_data/tasks.py +103 -0
  176. edu_rdm_integration/stages/upload_data/uploader_log/__init__.py +0 -0
  177. edu_rdm_integration/{uploader_log → stages/upload_data/uploader_log}/actions.py +14 -16
  178. edu_rdm_integration/stages/upload_data/uploader_log/apps.py +11 -0
  179. edu_rdm_integration/{uploader_log → stages/upload_data/uploader_log}/managers.py +15 -30
  180. edu_rdm_integration/stages/upload_data/uploader_log/migrations/0001_initial.py +31 -0
  181. edu_rdm_integration/stages/upload_data/uploader_log/migrations/__init__.py +0 -0
  182. edu_rdm_integration/stages/upload_data/uploader_log/models.py +86 -0
  183. edu_rdm_integration/{uploader_log → stages/upload_data/uploader_log}/ui.py +8 -6
  184. {edu_rdm_integration-3.9.1.dist-info → edu_rdm_integration-3.10.0.dist-info}/METADATA +238 -238
  185. edu_rdm_integration-3.10.0.dist-info/RECORD +255 -0
  186. edu_rdm_integration/app_meta.py +0 -16
  187. edu_rdm_integration/app_settings.py +0 -77
  188. edu_rdm_integration/collect_and_export_data/models.py +0 -67
  189. edu_rdm_integration/collect_and_export_data/utils.py +0 -224
  190. edu_rdm_integration/collect_data/base/helpers.py +0 -26
  191. edu_rdm_integration/collect_data/calculated/base/errors.py +0 -9
  192. edu_rdm_integration/collect_data/calculated/base/helpers.py +0 -32
  193. edu_rdm_integration/collect_data/calculated/base/managers.py +0 -23
  194. edu_rdm_integration/collect_data/calculated/base/results.py +0 -16
  195. edu_rdm_integration/collect_data/calculated/base/runners.py +0 -36
  196. edu_rdm_integration/collect_data/calculated/base/validators.py +0 -28
  197. edu_rdm_integration/collect_data/helpers.py +0 -92
  198. edu_rdm_integration/collect_data/non_calculated/base/errors.py +0 -9
  199. edu_rdm_integration/collect_data/non_calculated/base/helpers.py +0 -32
  200. edu_rdm_integration/collect_data/non_calculated/base/managers.py +0 -23
  201. edu_rdm_integration/collect_data/non_calculated/base/results.py +0 -16
  202. edu_rdm_integration/collect_data/non_calculated/base/runners.py +0 -36
  203. edu_rdm_integration/collect_data/non_calculated/base/validators.py +0 -28
  204. edu_rdm_integration/enum_register/register.py +0 -79
  205. edu_rdm_integration/export_data/base/errors.py +0 -9
  206. edu_rdm_integration/export_data/base/presenters.py +0 -13
  207. edu_rdm_integration/export_data/base/results.py +0 -16
  208. edu_rdm_integration/export_data/base/validators.py +0 -28
  209. edu_rdm_integration/export_data/helpers.py +0 -92
  210. edu_rdm_integration/helpers.py +0 -412
  211. edu_rdm_integration/management/general.py +0 -327
  212. edu_rdm_integration/models.py +0 -982
  213. edu_rdm_integration/redis_cache.py +0 -51
  214. edu_rdm_integration/uploader_log/apps.py +0 -10
  215. edu_rdm_integration-3.9.1.dist-info/RECORD +0 -198
  216. /edu_rdm_integration/{collect_and_export_data/migrations → core}/__init__.py +0 -0
  217. /edu_rdm_integration/{mapping.py → core/mapping.py} +0 -0
  218. /edu_rdm_integration/{collect_data → core/registry}/__init__.py +0 -0
  219. /edu_rdm_integration/{templates → core/registry/templates}/ui-js/start-task.js +0 -0
  220. /edu_rdm_integration/{signals.py → core/signals.py} +0 -0
  221. /edu_rdm_integration/{typing.py → core/typing.py} +0 -0
  222. /edu_rdm_integration/{collect_data/base → pipelines}/__init__.py +0 -0
  223. /edu_rdm_integration/{collect_data/calculated → pipelines/transfer}/__init__.py +0 -0
  224. /edu_rdm_integration/{collect_data/calculated/base → pipelines/transfer/migrations}/__init__.py +0 -0
  225. /edu_rdm_integration/{templates → pipelines/transfer/templates}/ui-js/transferred-entity-list.js +0 -0
  226. /edu_rdm_integration/{collect_data/non_calculated → rdm_entities}/__init__.py +0 -0
  227. /edu_rdm_integration/{collect_data/non_calculated/base → rdm_entities/migrations}/__init__.py +0 -0
  228. /edu_rdm_integration/{enum_register → rdm_models}/__init__.py +0 -0
  229. /edu_rdm_integration/{export_data → rdm_models/migrations}/__init__.py +0 -0
  230. /edu_rdm_integration/{export_data/base → stages}/__init__.py +0 -0
  231. /edu_rdm_integration/{function_templates → stages/collect_data}/__init__.py +0 -0
  232. /edu_rdm_integration/{collect_data/const.py → stages/collect_data/consts.py} +0 -0
  233. /edu_rdm_integration/{management → stages/collect_data/function_templates}/__init__.py +0 -0
  234. /edu_rdm_integration/{function_templates → stages/collect_data/function_templates}/function_collect_data_template/__init__.py-tpl +0 -0
  235. /edu_rdm_integration/{function_templates → stages/collect_data/function_templates}/function_collect_data_template/apps.py-tpl +0 -0
  236. /edu_rdm_integration/{function_templates → stages/collect_data/function_templates}/function_collect_data_template/caches.py-tpl +0 -0
  237. /edu_rdm_integration/{function_templates → stages/collect_data/function_templates}/function_collect_data_template/consts.py-tpl +0 -0
  238. /edu_rdm_integration/{function_templates → stages/collect_data/function_templates}/function_collect_data_template/enums.py-tpl +0 -0
  239. /edu_rdm_integration/{function_templates → stages/collect_data/function_templates}/function_collect_data_template/errors.py-tpl +0 -0
  240. /edu_rdm_integration/{function_templates → stages/collect_data/function_templates}/function_collect_data_template/helpers.py-tpl +0 -0
  241. /edu_rdm_integration/{function_templates → stages/collect_data/function_templates}/function_collect_data_template/presenters.py-tpl +0 -0
  242. /edu_rdm_integration/{function_templates → stages/collect_data/function_templates}/function_collect_data_template/results.py-tpl +0 -0
  243. /edu_rdm_integration/{function_templates → stages/collect_data/function_templates}/function_collect_data_template/strings.py-tpl +0 -0
  244. /edu_rdm_integration/{function_templates → stages/collect_data/function_templates}/function_collect_data_template/validators.py-tpl +0 -0
  245. /edu_rdm_integration/{management/commands → stages/collect_data/functions}/__init__.py +0 -0
  246. /edu_rdm_integration/{registry → stages/collect_data/functions/base}/__init__.py +0 -0
  247. /edu_rdm_integration/{collect_data → stages/collect_data/functions}/base/consts.py +0 -0
  248. /edu_rdm_integration/{uploader_log → stages/collect_data/functions/calculated}/__init__.py +0 -0
  249. /edu_rdm_integration/{collect_data → stages/collect_data/functions}/calculated/base/consts.py +0 -0
  250. /edu_rdm_integration/{collect_data → stages/collect_data/functions}/calculated/base/enums.py +0 -0
  251. /edu_rdm_integration/{collect_data → stages/collect_data/functions}/calculated/base/strings.py +0 -0
  252. /edu_rdm_integration/{collect_data → stages/collect_data/functions}/calculated/base/tests.py +0 -0
  253. /edu_rdm_integration/{collect_data → stages/collect_data/functions}/non_calculated/base/consts.py +0 -0
  254. /edu_rdm_integration/{collect_data → stages/collect_data/functions}/non_calculated/base/enums.py +0 -0
  255. /edu_rdm_integration/{collect_data → stages/collect_data/functions}/non_calculated/base/strings.py +0 -0
  256. /edu_rdm_integration/{collect_data → stages/collect_data/functions}/non_calculated/base/tests.py +0 -0
  257. /edu_rdm_integration/{export_data → stages/export_data}/consts.py +0 -0
  258. /edu_rdm_integration/{function_templates → stages/export_data/function_templates}/function_export_data_template/__init__.py-tpl +0 -0
  259. /edu_rdm_integration/{function_templates → stages/export_data/function_templates}/function_export_data_template/apps.py-tpl +0 -0
  260. /edu_rdm_integration/{function_templates → stages/export_data/function_templates}/function_export_data_template/caches.py-tpl +0 -0
  261. /edu_rdm_integration/{function_templates → stages/export_data/function_templates}/function_export_data_template/consts.py-tpl +0 -0
  262. /edu_rdm_integration/{function_templates → stages/export_data/function_templates}/function_export_data_template/enums.py-tpl +0 -0
  263. /edu_rdm_integration/{function_templates → stages/export_data/function_templates}/function_export_data_template/errors.py-tpl +0 -0
  264. /edu_rdm_integration/{function_templates → stages/export_data/function_templates}/function_export_data_template/helpers.py-tpl +0 -0
  265. /edu_rdm_integration/{function_templates → stages/export_data/function_templates}/function_export_data_template/presenters.py-tpl +0 -0
  266. /edu_rdm_integration/{function_templates → stages/export_data/function_templates}/function_export_data_template/results.py-tpl +0 -0
  267. /edu_rdm_integration/{function_templates → stages/export_data/function_templates}/function_export_data_template/strings.py-tpl +0 -0
  268. /edu_rdm_integration/{function_templates → stages/export_data/function_templates}/function_export_data_template/tests.py-tpl +0 -0
  269. /edu_rdm_integration/{function_templates → stages/export_data/function_templates}/function_export_data_template/validators.py-tpl +0 -0
  270. /edu_rdm_integration/{export_data → stages/export_data/functions}/base/consts.py +0 -0
  271. /edu_rdm_integration/{export_data → stages/export_data/functions}/base/enums.py +0 -0
  272. /edu_rdm_integration/{export_data → stages/export_data/functions}/base/strings.py +0 -0
  273. /edu_rdm_integration/{export_data → stages/export_data/functions}/base/tests.py +0 -0
  274. /edu_rdm_integration/{templates → stages/export_data/registry/templates}/ui-js/stage_for_export.js +0 -0
  275. /edu_rdm_integration/{uploader_log → stages/upload_data/uploader_log}/enums.py +0 -0
  276. /edu_rdm_integration/{uploader_log → stages/upload_data/uploader_log}/templates/ui-js/object-grid-buttons.js +0 -0
  277. {edu_rdm_integration-3.9.1.dist-info → edu_rdm_integration-3.10.0.dist-info}/WHEEL +0 -0
  278. {edu_rdm_integration-3.9.1.dist-info → edu_rdm_integration-3.10.0.dist-info}/licenses/LICENSE +0 -0
  279. {edu_rdm_integration-3.9.1.dist-info → edu_rdm_integration-3.10.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,331 @@
1
+ import heapq
2
+ import os
3
+ from abc import (
4
+ ABC,
5
+ abstractmethod,
6
+ )
7
+ from typing import (
8
+ TYPE_CHECKING,
9
+ Dict,
10
+ Iterable,
11
+ Optional,
12
+ Union,
13
+ )
14
+
15
+ from django.conf import (
16
+ settings,
17
+ )
18
+ from django.utils.html import (
19
+ format_html,
20
+ )
21
+ from django.utils.safestring import (
22
+ mark_safe,
23
+ )
24
+ from redis import (
25
+ Redis,
26
+ ResponseError,
27
+ )
28
+
29
+ from educommon.async_task.exceptions import (
30
+ TaskUniqueException,
31
+ )
32
+ from educommon.async_task.tasks import (
33
+ AsyncTask,
34
+ )
35
+
36
+ from edu_rdm_integration.core.consts import (
37
+ TASK_QUEUE_NAME,
38
+ )
39
+ from edu_rdm_integration.pipelines.transfer.enums import (
40
+ EntityLevelQueueTypeEnum,
41
+ )
42
+ from edu_rdm_integration.stages.collect_data.models import (
43
+ EduRdmCollectDataCommandProgress,
44
+ )
45
+ from edu_rdm_integration.stages.export_data.models import (
46
+ AbstractExportDataCommandProgress,
47
+ )
48
+
49
+
50
+ if TYPE_CHECKING:
51
+ from django.db.models.query import (
52
+ QuerySet,
53
+ )
54
+
55
+
56
+ class BaseTaskProgressUpdater(ABC):
57
+ """Базовый класс, который обновляет данные в таблицах, хранящих команды сбора/экспорта."""
58
+
59
+ @property
60
+ @abstractmethod
61
+ def update_model(self):
62
+ """Основная модель для обновления.
63
+
64
+ Необходимо задать в дочернем классе.
65
+ """
66
+
67
+ @property
68
+ @abstractmethod
69
+ def async_model(self):
70
+ """Модель асинхронных задач.
71
+
72
+ Необходимо задать в дочернем классе.
73
+ """
74
+
75
+ def set_async_task(self, commands_to_update: Dict[EduRdmCollectDataCommandProgress, str]) -> None:
76
+ """Устанавливает ссылку на асинхронную задачу."""
77
+ for command, task_uuid in commands_to_update.items():
78
+ command.task_id = task_uuid
79
+
80
+ self.update_model.objects.bulk_update(
81
+ commands_to_update,
82
+ ['task_id'],
83
+ )
84
+
85
+ def set_stage(self, command_id: int, stage_id: int) -> None:
86
+ """Устанавливает ссылку на stage."""
87
+ self.update_model.objects.filter(
88
+ id=command_id,
89
+ ).update(
90
+ stage_id=stage_id,
91
+ )
92
+
93
+
94
+ class BaseTaskStarter(ABC):
95
+ """Запускает асинхронные задачи."""
96
+
97
+ updater: BaseTaskProgressUpdater = None
98
+ async_task: AsyncTask = None
99
+ model_only_fields: Iterable[str] = ()
100
+
101
+ def run(self, command_ids: Iterable[int], queue_level: Optional[int] = None) -> str:
102
+ """Создает задачи и ставит их в очередь."""
103
+ commands_to_update = {}
104
+ skipped_commands_count = 0
105
+ commands = self._get_commands(command_ids)
106
+ queue_name = None
107
+
108
+ if queue_level:
109
+ queue_name = EntityLevelQueueTypeEnum.get_queue_name(level=queue_level)
110
+
111
+ if not queue_name:
112
+ queue_name = TASK_QUEUE_NAME
113
+
114
+ for command in commands:
115
+ if command.task_id:
116
+ # Повторный запуск команды не допускается
117
+ skipped_commands_count += 1
118
+ continue
119
+
120
+ try:
121
+ async_result = self.async_task().apply_async( # noqa pylint: disable=not-callable
122
+ args=None,
123
+ queue=queue_name,
124
+ routing_key=queue_name,
125
+ kwargs={
126
+ 'command_id': command.id,
127
+ },
128
+ lock_data={
129
+ 'lock_params': {
130
+ 'command_id': f'{self.updater.update_model.__name__}_{command.id}',
131
+ },
132
+ },
133
+ )
134
+ except TaskUniqueException:
135
+ skipped_commands_count += 1
136
+ continue
137
+ else:
138
+ commands_to_update[command] = async_result.task_id
139
+
140
+ if commands_to_update:
141
+ self.updater().set_async_task(commands_to_update) # noqa pylint: disable=not-callable
142
+
143
+ message = f'Поставлено задач в очередь: {len(commands_to_update)} из {len(commands)}.'
144
+ if skipped_commands_count:
145
+ message += (
146
+ f' Кол-во задач, которые были запущены ранее: {skipped_commands_count}. '
147
+ 'Однажды запущенные задачи не могут быть запущены снова!'
148
+ )
149
+
150
+ return message
151
+
152
+ def _get_commands(self, command_ids: Iterable[int]) -> 'QuerySet':
153
+ """Возвращает Queryset команд для создания задач."""
154
+ return self.updater.update_model.objects.filter(
155
+ id__in=command_ids,
156
+ ).only(
157
+ *self.model_only_fields,
158
+ )
159
+
160
+
161
+ class Graph:
162
+ """Граф связей между моделями.
163
+
164
+ Предназначен для поиска кратчайшей связи между моделями и дальнейшего построения lookup`а
165
+ до необходимого поля модели с последующим использованием его в фильтре.
166
+ Вершинами графа выступают наименования моделей. Ребро содержит наименования модели связанной
167
+ с другой моделью и наименования поля, через которое осуществляется связь.
168
+ Вместо наименования поля может быть наименование обратной связи между моделями,
169
+ в случае если данная связь является связью OneToOne.
170
+ """
171
+
172
+ def __init__(self):
173
+ self.vertices: dict[str, dict[str, Optional[str]]] = {}
174
+ """Словарь для хранения данных графа."""
175
+
176
+ def add_vertex(self, vertex: str):
177
+ """Добавление вершины."""
178
+ if vertex not in self.vertices:
179
+ self.vertices[vertex] = {}
180
+
181
+ def add_edge(self, vertex1: str, vertex2: str, edge_name: str):
182
+ """Добавление связи."""
183
+ if vertex1 in self.vertices and vertex2 in self.vertices:
184
+ self.vertices[vertex1][vertex2] = edge_name
185
+ if vertex1 not in self.vertices[vertex2]:
186
+ self.vertices[vertex2][vertex1] = None
187
+
188
+ def remove_vertex(self, vertex: str):
189
+ """Удаление вершины."""
190
+ if vertex in self.vertices:
191
+ del self.vertices[vertex]
192
+
193
+ # Удаляем связанные с удаленной вершиной ребра
194
+ for neighbour in self.vertices:
195
+ if vertex in self.vertices[neighbour]:
196
+ self.vertices[neighbour].pop(vertex)
197
+
198
+ def remove_edge(self, vertex1: str, vertex2: str):
199
+ """Удаление связи."""
200
+ if vertex1 in self.vertices and vertex2 in self.vertices:
201
+ self.vertices[vertex1].pop(vertex2, None)
202
+ self.vertices[vertex2].pop(vertex1, None)
203
+
204
+ def get_vertices(self) -> list[str]:
205
+ """Получение списка всех вершин."""
206
+ return list(self.vertices)
207
+
208
+ def get_edges(self) -> list[tuple[str, str, Optional[str]]]:
209
+ """Получение всех связей."""
210
+ edges = []
211
+
212
+ for vertex, neighbors in self.vertices.items():
213
+ for neighboring_vertex, edge_name in neighbors.items():
214
+ edge = (vertex, neighboring_vertex, edge_name)
215
+ edges.append(edge)
216
+
217
+ return edges
218
+
219
+ def __contains__(self, vertex: str) -> bool:
220
+ return vertex in self.vertices
221
+
222
+ def __iter__(self):
223
+ return iter(self.vertices)
224
+
225
+ def __getitem__(self, vertex: str):
226
+ return self.vertices.get(vertex, {})
227
+
228
+ def get_edges_between_vertices(
229
+ self, from_vertex: str, to_vertex: str, required_edge_name: bool = True
230
+ ) -> list[str]:
231
+ """Получение списка наименований ребер между вершинами."""
232
+ if from_vertex not in self.vertices and to_vertex not in self.vertices:
233
+ return []
234
+
235
+ path = []
236
+ edge_weight = 1
237
+
238
+ # Инициализация расстояния между вершинами
239
+ distances = {vertex: float('inf') for vertex in self}
240
+ distances[from_vertex] = 0
241
+
242
+ priority_queue = [(0, from_vertex)]
243
+
244
+ while priority_queue:
245
+ current_distance, current_vertex = heapq.heappop(priority_queue)
246
+
247
+ # Если достигнута конечная вершина, заканчиваем цикл
248
+ if current_vertex == to_vertex:
249
+ break
250
+
251
+ # Проверяем все смежные вершины и обновляем расстояния, если находим более короткий путь
252
+ for neighbor, edge_name in self[current_vertex].items():
253
+ distance = current_distance + edge_weight
254
+ if distance < distances[neighbor]:
255
+ distances[neighbor] = distance
256
+ heapq.heappush(priority_queue, (distance, neighbor))
257
+
258
+ # Восстанавливаем путь от конечной вершины к начальной
259
+ current_vertex = to_vertex
260
+ while current_vertex != from_vertex:
261
+ previous_vertex = edge_name = None
262
+
263
+ for neighbor in self[current_vertex]:
264
+ if distances[current_vertex] == distances[neighbor] + 1:
265
+ for neighbor_vertex, edge_name in self[neighbor].items():
266
+ if neighbor_vertex == current_vertex:
267
+ break
268
+
269
+ previous_vertex = neighbor
270
+ break
271
+
272
+ if required_edge_name and not edge_name:
273
+ path = []
274
+ break
275
+
276
+ path.append(edge_name)
277
+ current_vertex = previous_vertex
278
+
279
+ # Инвертируем путь и возвращаем его
280
+ path.reverse()
281
+
282
+ return path
283
+
284
+
285
+ def save_command_log_link(command: AbstractExportDataCommandProgress, log_dir: str) -> None:
286
+ """Сохраняет ссылку на лог команды."""
287
+ log_file = os.path.join(settings.MEDIA_ROOT, log_dir, f'{command.id}.log')
288
+ if os.path.exists(log_file):
289
+ command.logs_link = os.path.join(log_dir, f'{command.id}.log')
290
+ command.save()
291
+
292
+
293
+ def make_download_link(fieldfile, text='Cкачать', show_filename=False):
294
+ """Возвращает html ссылку для скачивания файла.
295
+
296
+ Если show_filename == True, использует имя файла как текст ссылки
297
+ """
298
+ link = mark_safe('')
299
+ if fieldfile:
300
+ link_text = os.path.basename(fieldfile.name) if show_filename else text
301
+ link = make_link(fieldfile.url, link_text)
302
+
303
+ return link
304
+
305
+
306
+ def make_link(url, text):
307
+ """Возвращает экаранированную html ссылку файла."""
308
+ return format_html('<a href="{}" target="_blank" download>{}</a>', url, text)
309
+
310
+
311
+ def get_redis_version(connection: 'Redis') -> tuple[int, int, int]:
312
+ """Возвращает кортеж с версией сервера Redis."""
313
+ try:
314
+ version = getattr(connection, '__redis_server_version', None)
315
+ if not version:
316
+ version = tuple([int(n) for n in connection.info('server')['redis_version'].split('.')[:3]])
317
+ setattr(connection, '__redis_server_version', version)
318
+ except ResponseError:
319
+ version = (0, 0, 0)
320
+
321
+ return version
322
+
323
+
324
+ def as_text(v: Union[bytes, str]) -> str:
325
+ """Конвертирует последовательность байт в строку."""
326
+ if isinstance(v, bytes):
327
+ return v.decode('utf-8')
328
+ elif isinstance(v, str):
329
+ return v
330
+ else:
331
+ raise ValueError('Неизвестный тип %r' % type(v))
@@ -0,0 +1,71 @@
1
+ import logging
2
+ from abc import (
3
+ ABC,
4
+ abstractmethod,
5
+ )
6
+ from datetime import (
7
+ date,
8
+ )
9
+ from typing import (
10
+ Optional,
11
+ Union,
12
+ )
13
+
14
+ from django.db.models import (
15
+ DateField,
16
+ Expression,
17
+ F,
18
+ )
19
+ from django.db.models.functions import (
20
+ Cast,
21
+ )
22
+
23
+ from educommon.integration_entities.enums import (
24
+ EntityLogOperation,
25
+ )
26
+
27
+ from edu_rdm_integration.core.utils import (
28
+ make_passed_datetime_from_today,
29
+ )
30
+
31
+
32
+ # Кортеж операций для обновления данных
33
+ UPDATED_OPERATIONS = (EntityLogOperation.CREATE, EntityLogOperation.UPDATE)
34
+ ALL_OPERATIONS = UPDATED_OPERATIONS + (EntityLogOperation.DELETE,)
35
+ TODAY_EXPR: Union[date, Expression, F] = Cast(make_passed_datetime_from_today(), output_field=DateField())
36
+ THREE_YEARS_AGO_DATE_EXPR: Union[date, Expression, F] = Cast(
37
+ make_passed_datetime_from_today(years=3), output_field=DateField()
38
+ )
39
+
40
+
41
+ class BaseOperationData(ABC):
42
+ """Базовый класс операций с данными."""
43
+
44
+ def __init__(self, **kwargs):
45
+ # Идентификатор команды для передачи сигналу manager_created
46
+ self.command_id: Optional[int] = kwargs.get('command_id')
47
+
48
+ self._file_handler: Optional[logging.FileHandler] = None
49
+
50
+ self._add_file_handler()
51
+
52
+ @property
53
+ @abstractmethod
54
+ def _log_file_path(self) -> str:
55
+ """Путь до лог файла."""
56
+
57
+ def _add_file_handler(self) -> None:
58
+ """Добавляет обработчик логов."""
59
+ if self.command_id:
60
+ self._file_handler = logging.FileHandler(self._log_file_path)
61
+
62
+ logging.getLogger('info_logger').addHandler(self._file_handler)
63
+ logging.getLogger('exception_logger').addHandler(self._file_handler)
64
+
65
+ def _remove_file_handler(self) -> None:
66
+ """Удаляет обработчик логов."""
67
+ if self._file_handler:
68
+ logging.getLogger('info_logger').removeHandler(self._file_handler)
69
+ logging.getLogger('exception_logger').removeHandler(self._file_handler)
70
+
71
+ self._file_handler.close()
@@ -0,0 +1,20 @@
1
+ from abc import (
2
+ ABCMeta,
3
+ abstractmethod,
4
+ )
5
+
6
+
7
+ class AbstractCache(metaclass=ABCMeta):
8
+ """Абстрактный интерфейс для кеша отправки."""
9
+
10
+ @abstractmethod
11
+ def get(self, key, default=None, **kwargs):
12
+ """Возвращает значение из кеша по ключу."""
13
+
14
+ @abstractmethod
15
+ def set(self, key, value, timeout=None, **kwargs):
16
+ """Сохраняет значение в кеш по ключу."""
17
+
18
+ @abstractmethod
19
+ def lock(self, name, timeout=None, **kwargs):
20
+ """Захватывает блокировку."""
@@ -16,17 +16,13 @@ from objectpack.filters import (
16
16
  ColumnFilterEngine,
17
17
  )
18
18
 
19
- from edu_rdm_integration.collect_and_export_data.ui import (
20
- CommandQueueSelectWindow,
21
- )
22
- from edu_rdm_integration.collect_and_export_data.utils import (
19
+ from edu_rdm_integration.core.helpers import (
23
20
  BaseTaskStarter,
21
+ make_download_link,
24
22
  )
25
- from edu_rdm_integration.export_data.ui import (
23
+ from edu_rdm_integration.core.registry.ui import (
26
24
  CommandProgressListWindow,
27
- )
28
- from edu_rdm_integration.helpers import (
29
- make_download_link,
25
+ CommandQueueSelectWindow,
30
26
  )
31
27
 
32
28
 
@@ -94,9 +90,7 @@ class BaseCommandProgressPack(ObjectPack):
94
90
 
95
91
 
96
92
  class BaseStartTaskAction(BaseAction):
97
- """
98
- Базовый экшн создания асинхронных задач для выгрузки РВД.
99
- """
93
+ """Базовый экшн создания асинхронных задач для выгрузки РВД."""
100
94
 
101
95
  url: str = None
102
96
 
@@ -114,7 +108,7 @@ class BaseStartTaskAction(BaseAction):
114
108
 
115
109
 
116
110
  class QueueLevelSelectWinAction(BaseWindowAction):
117
- """Экшен окна выбора очереди для запуска ручной команды собра/выгрузки."""
111
+ """Экшен окна выбора очереди для запуска ручной команды сбора/выгрузки."""
118
112
 
119
113
  def create_window(self):
120
114
  """Создание окна."""
@@ -0,0 +1,11 @@
1
+ from django.apps import (
2
+ AppConfig,
3
+ )
4
+
5
+
6
+ class RDMCoreRegistryAppConfig(AppConfig):
7
+ """Приложение с базовым функционалом для создания реестров РВД."""
8
+
9
+ name = 'edu_rdm_integration.core.registry'
10
+ label = 'edu_rdm_integration_core_registry'
11
+ verbose_name = 'Базовая часть реестров РВД'
@@ -21,7 +21,7 @@ from educommon.utils.ui import (
21
21
  append_template_globals,
22
22
  )
23
23
 
24
- from edu_rdm_integration.enums import (
24
+ from edu_rdm_integration.pipelines.transfer.enums import (
25
25
  EntityLevelQueueTypeEnum,
26
26
  )
27
27
 
@@ -15,15 +15,14 @@ from m3_db_utils.models import (
15
15
  ModelEnumValue,
16
16
  )
17
17
 
18
- from edu_rdm_integration.consts import (
18
+ from edu_rdm_integration.core.consts import (
19
19
  REGIONAL_DATA_MART_INTEGRATION_COLLECTING_DATA,
20
20
  REGIONAL_DATA_MART_INTEGRATION_EXPORTING_DATA,
21
21
  )
22
22
 
23
23
 
24
24
  class RegionalDataMartEntityStorage(EntityStorage):
25
- """
26
- Хранилище классов сущностей реализованных в системе.
25
+ """Хранилище классов сущностей реализованных в системе.
27
26
 
28
27
  Собираются только те сущности, типы которых указаны в модели-перечислении
29
28
  function_tools.models.function_tools.models.EntityType. Расширение произведено в связи с необходимостью получения
@@ -35,9 +34,7 @@ class RegionalDataMartEntityStorage(EntityStorage):
35
34
  runner_class: type[BaseRunner],
36
35
  runner_regional_data_mart_integration_entities: list[str],
37
36
  ):
38
- """
39
- Собирает и возвращает список сущностей.
40
- """
37
+ """Собирает и возвращает список сущностей."""
41
38
  for runnable_class in runner_class._prepare_runnable_classes():
42
39
  if hasattr(runnable_class, '_prepare_runnable_classes'):
43
40
  self._collect_runner_regional_data_mart_integration_entities(
@@ -59,9 +56,7 @@ class RegionalDataMartEntityStorage(EntityStorage):
59
56
  *args,
60
57
  **kwargs,
61
58
  ) -> dict[str, type[object]]:
62
- """
63
- Формирование карты соответствия сущности интеграции с "Региональная витрина данных" и сущности function_tools.
64
- """
59
+ """Формирование карты соответствия сущности интеграции с РВД и сущности function_tools."""
65
60
  rdm_integration_function_tools_entities_map: dict[str, type[object]] = {}
66
61
 
67
62
  registered_function_tools_entities_classes = [
@@ -89,8 +84,7 @@ class RegionalDataMartEntityStorage(EntityStorage):
89
84
  return rdm_integration_function_tools_entities_map
90
85
 
91
86
  def prepare_entities_manager_map(self, tags: set[str]) -> dict[str, type[object]]:
92
- """
93
- Формирование карты соответствия сущности интеграции с "Региональная витрина данных" и менеджера Функции.
87
+ """Формирование карты соответствия сущности интеграции с "Региональная витрина данных" и менеджера Функции.
94
88
 
95
89
  Стоит учитывать, что в рамках одной Функции может производиться работа с несколькими сущностями.
96
90
  """
@@ -100,8 +94,7 @@ class RegionalDataMartEntityStorage(EntityStorage):
100
94
  )
101
95
 
102
96
  def prepare_manager_entities_map(self, tags: set[str]) -> dict[type[object], list[str]]:
103
- """
104
- Формирование карты соответствия менеджера Функции и сущности интеграции с "Региональная витрина данных".
97
+ """Формирование карты соответствия менеджера Функции и сущности интеграции с "Региональная витрина данных".
105
98
 
106
99
  Стоит учитывать, что в рамках одной Функции может производиться работа с несколькими сущностями.
107
100
  """
@@ -114,8 +107,7 @@ class RegionalDataMartEntityStorage(EntityStorage):
114
107
  return _manager_entities_map
115
108
 
116
109
  def prepare_entities_functions_map(self, tags: set[str]) -> dict[str, type[object]]:
117
- """
118
- Формирование карты соответствия сущности интеграции с "Региональная витрина данных" и функции.
110
+ """Формирование карты соответствия сущности интеграции с "Региональная витрина данных" и функции.
119
111
 
120
112
  Стоит учитывать, что в рамках одной Функции может производиться работа с несколькими сущностями.
121
113
  """
@@ -125,8 +117,7 @@ class RegionalDataMartEntityStorage(EntityStorage):
125
117
  )
126
118
 
127
119
  def prepare_exporting_collecting_functions_map(self) -> dict[str, str]:
128
- """
129
- Возвращает карту соответствия функций выгрузки и сбора данных.
120
+ """Возвращает карту соответствия функций выгрузки и сбора данных.
130
121
 
131
122
  Returns:
132
123
  Возвращает словарь в качестве ключей и значений используются UUID-ы функций.