udata 9.1.2.dev30355__py2.py3-none-any.whl → 9.1.2.dev30454__py2.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.

Potentially problematic release.


This version of udata might be problematic. Click here for more details.

Files changed (413) hide show
  1. tasks/__init__.py +109 -107
  2. tasks/helpers.py +18 -18
  3. udata/__init__.py +4 -4
  4. udata/admin/views.py +5 -5
  5. udata/api/__init__.py +111 -134
  6. udata/api/commands.py +45 -37
  7. udata/api/errors.py +5 -4
  8. udata/api/fields.py +23 -21
  9. udata/api/oauth2.py +55 -74
  10. udata/api/parsers.py +15 -15
  11. udata/api/signals.py +1 -1
  12. udata/api_fields.py +137 -89
  13. udata/app.py +58 -55
  14. udata/assets.py +5 -5
  15. udata/auth/__init__.py +37 -26
  16. udata/auth/forms.py +23 -15
  17. udata/auth/helpers.py +1 -1
  18. udata/auth/mails.py +3 -3
  19. udata/auth/password_validation.py +19 -15
  20. udata/auth/views.py +94 -68
  21. udata/commands/__init__.py +71 -69
  22. udata/commands/cache.py +7 -7
  23. udata/commands/db.py +201 -140
  24. udata/commands/dcat.py +36 -30
  25. udata/commands/fixtures.py +100 -84
  26. udata/commands/images.py +21 -20
  27. udata/commands/info.py +17 -20
  28. udata/commands/init.py +10 -10
  29. udata/commands/purge.py +12 -13
  30. udata/commands/serve.py +41 -29
  31. udata/commands/static.py +16 -18
  32. udata/commands/test.py +20 -20
  33. udata/commands/tests/fixtures.py +26 -24
  34. udata/commands/worker.py +31 -33
  35. udata/core/__init__.py +12 -12
  36. udata/core/activity/__init__.py +0 -1
  37. udata/core/activity/api.py +59 -49
  38. udata/core/activity/models.py +28 -26
  39. udata/core/activity/signals.py +1 -1
  40. udata/core/activity/tasks.py +16 -10
  41. udata/core/badges/api.py +6 -6
  42. udata/core/badges/commands.py +14 -13
  43. udata/core/badges/fields.py +8 -5
  44. udata/core/badges/forms.py +7 -4
  45. udata/core/badges/models.py +16 -31
  46. udata/core/badges/permissions.py +1 -3
  47. udata/core/badges/signals.py +2 -2
  48. udata/core/badges/tasks.py +3 -2
  49. udata/core/badges/tests/test_commands.py +10 -10
  50. udata/core/badges/tests/test_model.py +24 -31
  51. udata/core/contact_point/api.py +19 -18
  52. udata/core/contact_point/api_fields.py +21 -14
  53. udata/core/contact_point/factories.py +2 -2
  54. udata/core/contact_point/forms.py +7 -6
  55. udata/core/contact_point/models.py +3 -5
  56. udata/core/dataservices/api.py +26 -21
  57. udata/core/dataservices/factories.py +13 -11
  58. udata/core/dataservices/models.py +35 -40
  59. udata/core/dataservices/permissions.py +4 -4
  60. udata/core/dataservices/rdf.py +40 -17
  61. udata/core/dataservices/tasks.py +4 -3
  62. udata/core/dataset/actions.py +10 -10
  63. udata/core/dataset/activities.py +21 -23
  64. udata/core/dataset/api.py +321 -298
  65. udata/core/dataset/api_fields.py +443 -271
  66. udata/core/dataset/apiv2.py +305 -229
  67. udata/core/dataset/commands.py +38 -36
  68. udata/core/dataset/constants.py +61 -54
  69. udata/core/dataset/csv.py +70 -74
  70. udata/core/dataset/events.py +39 -32
  71. udata/core/dataset/exceptions.py +8 -4
  72. udata/core/dataset/factories.py +57 -65
  73. udata/core/dataset/forms.py +87 -63
  74. udata/core/dataset/models.py +336 -280
  75. udata/core/dataset/permissions.py +9 -6
  76. udata/core/dataset/preview.py +15 -17
  77. udata/core/dataset/rdf.py +156 -122
  78. udata/core/dataset/search.py +92 -77
  79. udata/core/dataset/signals.py +1 -1
  80. udata/core/dataset/tasks.py +63 -54
  81. udata/core/discussions/actions.py +5 -5
  82. udata/core/discussions/api.py +124 -120
  83. udata/core/discussions/factories.py +2 -2
  84. udata/core/discussions/forms.py +9 -7
  85. udata/core/discussions/metrics.py +1 -3
  86. udata/core/discussions/models.py +25 -24
  87. udata/core/discussions/notifications.py +18 -14
  88. udata/core/discussions/permissions.py +3 -3
  89. udata/core/discussions/signals.py +4 -4
  90. udata/core/discussions/tasks.py +24 -28
  91. udata/core/followers/api.py +32 -33
  92. udata/core/followers/models.py +9 -9
  93. udata/core/followers/signals.py +3 -3
  94. udata/core/jobs/actions.py +7 -7
  95. udata/core/jobs/api.py +99 -92
  96. udata/core/jobs/commands.py +48 -49
  97. udata/core/jobs/forms.py +11 -11
  98. udata/core/jobs/models.py +6 -6
  99. udata/core/metrics/__init__.py +2 -2
  100. udata/core/metrics/commands.py +34 -30
  101. udata/core/metrics/models.py +2 -4
  102. udata/core/metrics/signals.py +1 -1
  103. udata/core/metrics/tasks.py +3 -3
  104. udata/core/organization/activities.py +12 -15
  105. udata/core/organization/api.py +167 -174
  106. udata/core/organization/api_fields.py +183 -124
  107. udata/core/organization/apiv2.py +32 -32
  108. udata/core/organization/commands.py +20 -22
  109. udata/core/organization/constants.py +11 -11
  110. udata/core/organization/csv.py +17 -15
  111. udata/core/organization/factories.py +8 -11
  112. udata/core/organization/forms.py +32 -26
  113. udata/core/organization/metrics.py +2 -1
  114. udata/core/organization/models.py +87 -67
  115. udata/core/organization/notifications.py +18 -14
  116. udata/core/organization/permissions.py +10 -11
  117. udata/core/organization/rdf.py +14 -14
  118. udata/core/organization/search.py +30 -28
  119. udata/core/organization/signals.py +7 -7
  120. udata/core/organization/tasks.py +42 -61
  121. udata/core/owned.py +38 -27
  122. udata/core/post/api.py +82 -81
  123. udata/core/post/constants.py +8 -5
  124. udata/core/post/factories.py +4 -4
  125. udata/core/post/forms.py +13 -14
  126. udata/core/post/models.py +20 -22
  127. udata/core/post/tests/test_api.py +30 -32
  128. udata/core/reports/api.py +8 -7
  129. udata/core/reports/constants.py +1 -3
  130. udata/core/reports/models.py +10 -10
  131. udata/core/reuse/activities.py +15 -19
  132. udata/core/reuse/api.py +123 -126
  133. udata/core/reuse/api_fields.py +120 -85
  134. udata/core/reuse/apiv2.py +11 -10
  135. udata/core/reuse/constants.py +23 -23
  136. udata/core/reuse/csv.py +18 -18
  137. udata/core/reuse/factories.py +5 -9
  138. udata/core/reuse/forms.py +24 -21
  139. udata/core/reuse/models.py +55 -51
  140. udata/core/reuse/permissions.py +2 -2
  141. udata/core/reuse/search.py +49 -46
  142. udata/core/reuse/signals.py +1 -1
  143. udata/core/reuse/tasks.py +4 -5
  144. udata/core/site/api.py +47 -50
  145. udata/core/site/factories.py +2 -2
  146. udata/core/site/forms.py +4 -5
  147. udata/core/site/models.py +94 -63
  148. udata/core/site/rdf.py +14 -14
  149. udata/core/spam/api.py +16 -9
  150. udata/core/spam/constants.py +4 -4
  151. udata/core/spam/fields.py +13 -7
  152. udata/core/spam/models.py +27 -20
  153. udata/core/spam/signals.py +1 -1
  154. udata/core/spam/tests/test_spam.py +6 -5
  155. udata/core/spatial/api.py +72 -80
  156. udata/core/spatial/api_fields.py +73 -58
  157. udata/core/spatial/commands.py +67 -64
  158. udata/core/spatial/constants.py +3 -3
  159. udata/core/spatial/factories.py +37 -54
  160. udata/core/spatial/forms.py +27 -26
  161. udata/core/spatial/geoids.py +17 -17
  162. udata/core/spatial/models.py +43 -47
  163. udata/core/spatial/tasks.py +2 -1
  164. udata/core/spatial/tests/test_api.py +115 -130
  165. udata/core/spatial/tests/test_fields.py +74 -77
  166. udata/core/spatial/tests/test_geoid.py +22 -22
  167. udata/core/spatial/tests/test_models.py +5 -7
  168. udata/core/spatial/translations.py +16 -16
  169. udata/core/storages/__init__.py +16 -18
  170. udata/core/storages/api.py +66 -64
  171. udata/core/storages/tasks.py +7 -7
  172. udata/core/storages/utils.py +15 -15
  173. udata/core/storages/views.py +5 -6
  174. udata/core/tags/api.py +17 -14
  175. udata/core/tags/csv.py +4 -4
  176. udata/core/tags/models.py +8 -5
  177. udata/core/tags/tasks.py +11 -13
  178. udata/core/tags/views.py +4 -4
  179. udata/core/topic/api.py +84 -73
  180. udata/core/topic/apiv2.py +157 -127
  181. udata/core/topic/factories.py +3 -4
  182. udata/core/topic/forms.py +12 -14
  183. udata/core/topic/models.py +14 -19
  184. udata/core/topic/parsers.py +26 -26
  185. udata/core/user/activities.py +30 -29
  186. udata/core/user/api.py +151 -152
  187. udata/core/user/api_fields.py +132 -100
  188. udata/core/user/apiv2.py +7 -7
  189. udata/core/user/commands.py +38 -38
  190. udata/core/user/factories.py +8 -9
  191. udata/core/user/forms.py +14 -11
  192. udata/core/user/metrics.py +2 -2
  193. udata/core/user/models.py +68 -69
  194. udata/core/user/permissions.py +4 -5
  195. udata/core/user/rdf.py +7 -8
  196. udata/core/user/tasks.py +2 -2
  197. udata/core/user/tests/test_user_model.py +24 -16
  198. udata/cors.py +99 -0
  199. udata/db/tasks.py +2 -1
  200. udata/entrypoints.py +35 -31
  201. udata/errors.py +2 -1
  202. udata/event/values.py +6 -6
  203. udata/factories.py +2 -2
  204. udata/features/identicon/api.py +5 -6
  205. udata/features/identicon/backends.py +48 -55
  206. udata/features/identicon/tests/test_backends.py +4 -5
  207. udata/features/notifications/__init__.py +0 -1
  208. udata/features/notifications/actions.py +9 -9
  209. udata/features/notifications/api.py +17 -13
  210. udata/features/territories/__init__.py +12 -10
  211. udata/features/territories/api.py +14 -15
  212. udata/features/territories/models.py +23 -28
  213. udata/features/transfer/actions.py +8 -11
  214. udata/features/transfer/api.py +84 -77
  215. udata/features/transfer/factories.py +2 -1
  216. udata/features/transfer/models.py +11 -12
  217. udata/features/transfer/notifications.py +19 -15
  218. udata/features/transfer/permissions.py +5 -5
  219. udata/forms/__init__.py +5 -2
  220. udata/forms/fields.py +164 -172
  221. udata/forms/validators.py +19 -22
  222. udata/forms/widgets.py +9 -13
  223. udata/frontend/__init__.py +31 -26
  224. udata/frontend/csv.py +68 -58
  225. udata/frontend/markdown.py +40 -44
  226. udata/harvest/actions.py +89 -77
  227. udata/harvest/api.py +294 -238
  228. udata/harvest/backends/__init__.py +4 -4
  229. udata/harvest/backends/base.py +128 -111
  230. udata/harvest/backends/dcat.py +80 -66
  231. udata/harvest/commands.py +56 -60
  232. udata/harvest/csv.py +8 -8
  233. udata/harvest/exceptions.py +6 -3
  234. udata/harvest/filters.py +24 -23
  235. udata/harvest/forms.py +27 -28
  236. udata/harvest/models.py +88 -80
  237. udata/harvest/notifications.py +15 -10
  238. udata/harvest/signals.py +13 -13
  239. udata/harvest/tasks.py +11 -10
  240. udata/harvest/tests/factories.py +23 -24
  241. udata/harvest/tests/test_actions.py +136 -166
  242. udata/harvest/tests/test_api.py +220 -214
  243. udata/harvest/tests/test_base_backend.py +117 -112
  244. udata/harvest/tests/test_dcat_backend.py +380 -308
  245. udata/harvest/tests/test_filters.py +33 -22
  246. udata/harvest/tests/test_models.py +11 -14
  247. udata/harvest/tests/test_notifications.py +6 -7
  248. udata/harvest/tests/test_tasks.py +7 -6
  249. udata/i18n.py +237 -78
  250. udata/linkchecker/backends.py +5 -11
  251. udata/linkchecker/checker.py +23 -22
  252. udata/linkchecker/commands.py +4 -6
  253. udata/linkchecker/models.py +6 -6
  254. udata/linkchecker/tasks.py +18 -20
  255. udata/mail.py +21 -21
  256. udata/migrations/2020-07-24-remove-s-from-scope-oauth.py +9 -8
  257. udata/migrations/2020-08-24-add-fs-filename.py +9 -8
  258. udata/migrations/2020-09-28-update-reuses-datasets-metrics.py +5 -4
  259. udata/migrations/2020-10-16-migrate-ods-resources.py +9 -10
  260. udata/migrations/2021-04-08-update-schema-with-new-structure.py +8 -7
  261. udata/migrations/2021-05-27-fix-default-schema-name.py +7 -6
  262. udata/migrations/2021-07-05-remove-unused-badges.py +17 -15
  263. udata/migrations/2021-07-07-update-schema-for-community-resources.py +7 -6
  264. udata/migrations/2021-08-17-follow-integrity.py +5 -4
  265. udata/migrations/2021-08-17-harvest-integrity.py +13 -12
  266. udata/migrations/2021-08-17-oauth2client-integrity.py +5 -4
  267. udata/migrations/2021-08-17-transfer-integrity.py +5 -4
  268. udata/migrations/2021-08-17-users-integrity.py +9 -8
  269. udata/migrations/2021-12-14-reuse-topics.py +7 -6
  270. udata/migrations/2022-04-21-improve-extension-detection.py +8 -7
  271. udata/migrations/2022-09-22-clean-inactive-harvest-datasets.py +16 -14
  272. udata/migrations/2022-10-10-add-fs_uniquifier-to-user-model.py +6 -6
  273. udata/migrations/2022-10-10-migrate-harvest-extras.py +36 -26
  274. udata/migrations/2023-02-08-rename-internal-dates.py +46 -28
  275. udata/migrations/2024-01-29-fix-reuse-and-dataset-with-private-None.py +10 -8
  276. udata/migrations/2024-03-22-migrate-activity-kwargs-to-extras.py +6 -4
  277. udata/migrations/2024-06-11-fix-reuse-datasets-references.py +7 -6
  278. udata/migrations/__init__.py +123 -105
  279. udata/models/__init__.py +4 -4
  280. udata/mongo/__init__.py +13 -11
  281. udata/mongo/badges_field.py +3 -2
  282. udata/mongo/datetime_fields.py +13 -12
  283. udata/mongo/document.py +17 -16
  284. udata/mongo/engine.py +15 -16
  285. udata/mongo/errors.py +2 -1
  286. udata/mongo/extras_fields.py +30 -20
  287. udata/mongo/queryset.py +12 -12
  288. udata/mongo/slug_fields.py +38 -28
  289. udata/mongo/taglist_field.py +1 -2
  290. udata/mongo/url_field.py +5 -5
  291. udata/mongo/uuid_fields.py +4 -3
  292. udata/notifications/__init__.py +1 -1
  293. udata/notifications/mattermost.py +10 -9
  294. udata/rdf.py +167 -188
  295. udata/routing.py +40 -45
  296. udata/search/__init__.py +18 -19
  297. udata/search/adapter.py +17 -16
  298. udata/search/commands.py +44 -51
  299. udata/search/fields.py +13 -20
  300. udata/search/query.py +23 -18
  301. udata/search/result.py +9 -10
  302. udata/sentry.py +21 -19
  303. udata/settings.py +262 -198
  304. udata/sitemap.py +8 -6
  305. udata/storage/s3.py +20 -13
  306. udata/tags.py +4 -5
  307. udata/tasks.py +43 -42
  308. udata/tests/__init__.py +9 -6
  309. udata/tests/api/__init__.py +8 -6
  310. udata/tests/api/test_auth_api.py +395 -321
  311. udata/tests/api/test_base_api.py +33 -35
  312. udata/tests/api/test_contact_points.py +7 -9
  313. udata/tests/api/test_dataservices_api.py +211 -158
  314. udata/tests/api/test_datasets_api.py +823 -812
  315. udata/tests/api/test_follow_api.py +13 -15
  316. udata/tests/api/test_me_api.py +95 -112
  317. udata/tests/api/test_organizations_api.py +301 -339
  318. udata/tests/api/test_reports_api.py +35 -25
  319. udata/tests/api/test_reuses_api.py +134 -139
  320. udata/tests/api/test_swagger.py +5 -5
  321. udata/tests/api/test_tags_api.py +18 -25
  322. udata/tests/api/test_topics_api.py +94 -94
  323. udata/tests/api/test_transfer_api.py +53 -48
  324. udata/tests/api/test_user_api.py +128 -141
  325. udata/tests/apiv2/test_datasets.py +290 -198
  326. udata/tests/apiv2/test_me_api.py +10 -11
  327. udata/tests/apiv2/test_organizations.py +56 -74
  328. udata/tests/apiv2/test_swagger.py +5 -5
  329. udata/tests/apiv2/test_topics.py +69 -87
  330. udata/tests/cli/test_cli_base.py +8 -8
  331. udata/tests/cli/test_db_cli.py +21 -19
  332. udata/tests/dataservice/test_dataservice_tasks.py +8 -12
  333. udata/tests/dataset/test_csv_adapter.py +44 -35
  334. udata/tests/dataset/test_dataset_actions.py +2 -3
  335. udata/tests/dataset/test_dataset_commands.py +7 -8
  336. udata/tests/dataset/test_dataset_events.py +36 -29
  337. udata/tests/dataset/test_dataset_model.py +224 -217
  338. udata/tests/dataset/test_dataset_rdf.py +142 -131
  339. udata/tests/dataset/test_dataset_tasks.py +15 -15
  340. udata/tests/dataset/test_resource_preview.py +10 -13
  341. udata/tests/features/territories/__init__.py +9 -13
  342. udata/tests/features/territories/test_territories_api.py +71 -91
  343. udata/tests/forms/test_basic_fields.py +7 -7
  344. udata/tests/forms/test_current_user_field.py +39 -66
  345. udata/tests/forms/test_daterange_field.py +31 -39
  346. udata/tests/forms/test_dict_field.py +28 -26
  347. udata/tests/forms/test_extras_fields.py +102 -76
  348. udata/tests/forms/test_form_field.py +8 -8
  349. udata/tests/forms/test_image_field.py +33 -26
  350. udata/tests/forms/test_model_field.py +134 -123
  351. udata/tests/forms/test_model_list_field.py +7 -7
  352. udata/tests/forms/test_nested_model_list_field.py +117 -79
  353. udata/tests/forms/test_publish_as_field.py +36 -65
  354. udata/tests/forms/test_reference_field.py +34 -53
  355. udata/tests/forms/test_user_forms.py +23 -21
  356. udata/tests/forms/test_uuid_field.py +6 -10
  357. udata/tests/frontend/__init__.py +9 -6
  358. udata/tests/frontend/test_auth.py +7 -6
  359. udata/tests/frontend/test_csv.py +81 -96
  360. udata/tests/frontend/test_hooks.py +43 -43
  361. udata/tests/frontend/test_markdown.py +211 -191
  362. udata/tests/helpers.py +32 -37
  363. udata/tests/models.py +2 -2
  364. udata/tests/organization/test_csv_adapter.py +21 -16
  365. udata/tests/organization/test_notifications.py +11 -18
  366. udata/tests/organization/test_organization_model.py +13 -13
  367. udata/tests/organization/test_organization_rdf.py +29 -22
  368. udata/tests/organization/test_organization_tasks.py +16 -17
  369. udata/tests/plugin.py +79 -73
  370. udata/tests/reuse/test_reuse_model.py +21 -21
  371. udata/tests/reuse/test_reuse_task.py +11 -13
  372. udata/tests/search/__init__.py +11 -12
  373. udata/tests/search/test_adapter.py +60 -70
  374. udata/tests/search/test_query.py +16 -16
  375. udata/tests/search/test_results.py +10 -7
  376. udata/tests/site/test_site_api.py +11 -16
  377. udata/tests/site/test_site_metrics.py +20 -30
  378. udata/tests/site/test_site_model.py +4 -5
  379. udata/tests/site/test_site_rdf.py +94 -78
  380. udata/tests/test_activity.py +17 -17
  381. udata/tests/test_cors.py +62 -0
  382. udata/tests/test_discussions.py +292 -299
  383. udata/tests/test_i18n.py +37 -40
  384. udata/tests/test_linkchecker.py +91 -85
  385. udata/tests/test_mail.py +13 -17
  386. udata/tests/test_migrations.py +219 -180
  387. udata/tests/test_model.py +164 -157
  388. udata/tests/test_notifications.py +17 -17
  389. udata/tests/test_owned.py +14 -14
  390. udata/tests/test_rdf.py +25 -23
  391. udata/tests/test_routing.py +89 -93
  392. udata/tests/test_storages.py +137 -128
  393. udata/tests/test_tags.py +44 -46
  394. udata/tests/test_topics.py +7 -7
  395. udata/tests/test_transfer.py +42 -49
  396. udata/tests/test_uris.py +160 -161
  397. udata/tests/test_utils.py +79 -71
  398. udata/tests/user/test_user_rdf.py +5 -9
  399. udata/tests/workers/test_jobs_commands.py +57 -58
  400. udata/tests/workers/test_tasks_routing.py +23 -29
  401. udata/tests/workers/test_workers_api.py +125 -131
  402. udata/tests/workers/test_workers_helpers.py +6 -6
  403. udata/tracking.py +4 -6
  404. udata/uris.py +45 -46
  405. udata/utils.py +68 -66
  406. udata/wsgi.py +1 -1
  407. {udata-9.1.2.dev30355.dist-info → udata-9.1.2.dev30454.dist-info}/METADATA +7 -3
  408. udata-9.1.2.dev30454.dist-info/RECORD +706 -0
  409. udata-9.1.2.dev30355.dist-info/RECORD +0 -704
  410. {udata-9.1.2.dev30355.dist-info → udata-9.1.2.dev30454.dist-info}/LICENSE +0 -0
  411. {udata-9.1.2.dev30355.dist-info → udata-9.1.2.dev30454.dist-info}/WHEEL +0 -0
  412. {udata-9.1.2.dev30355.dist-info → udata-9.1.2.dev30454.dist-info}/entry_points.txt +0 -0
  413. {udata-9.1.2.dev30355.dist-info → udata-9.1.2.dev30454.dist-info}/top_level.txt +0 -0
udata/mongo/engine.py CHANGED
@@ -1,24 +1,24 @@
1
- from bson import ObjectId, DBRef
1
+ from bson import DBRef, ObjectId
2
2
  from flask_mongoengine import MongoEngine, MongoEngineSessionInterface
3
+ from flask_storage.mongo import FileField, ImageField
3
4
  from mongoengine.base import TopLevelDocumentMetaclass, get_document
4
5
  from mongoengine.errors import ValidationError
5
- from mongoengine.signals import pre_save, post_save
6
-
7
- from flask_storage.mongo import FileField, ImageField
6
+ from mongoengine.signals import post_save, pre_save
8
7
 
9
8
  from .badges_field import BadgesField
10
- from .taglist_field import TagListField
11
9
  from .datetime_fields import DateField, DateRange, Datetimed
10
+ from .document import DomainModel, UDataDocument
12
11
  from .extras_fields import ExtrasField, OrganizationExtrasField
12
+ from .queryset import UDataQuerySet
13
13
  from .slug_fields import SlugField
14
+ from .taglist_field import TagListField
14
15
  from .url_field import URLField
15
16
  from .uuid_fields import AutoUUIDField
16
- from .queryset import UDataQuerySet
17
- from .document import UDataDocument, DomainModel
18
17
 
19
18
 
20
19
  class UDataMongoEngine(MongoEngine):
21
- '''Customized mongoengine with extra fields types and helpers'''
20
+ """Customized mongoengine with extra fields types and helpers"""
21
+
22
22
  def __init__(self, app=None):
23
23
  super(UDataMongoEngine, self).__init__(app)
24
24
  self.BadgesField = BadgesField
@@ -44,19 +44,19 @@ class UDataMongoEngine(MongoEngine):
44
44
  self.pre_save = pre_save
45
45
 
46
46
  def resolve_model(self, model):
47
- '''
47
+ """
48
48
  Resolve a model given a name or dict with `class` entry.
49
49
 
50
50
  :raises ValueError: model specification is wrong or does not exists
51
- '''
51
+ """
52
52
  if not model:
53
- raise ValueError('Unsupported model specifications')
53
+ raise ValueError("Unsupported model specifications")
54
54
  if isinstance(model, str):
55
55
  classname = model
56
- elif isinstance(model, dict) and 'class' in model:
57
- classname = model['class']
56
+ elif isinstance(model, dict) and "class" in model:
57
+ classname = model["class"]
58
58
  else:
59
- raise ValueError('Unsupported model specifications')
59
+ raise ValueError("Unsupported model specifications")
60
60
 
61
61
  try:
62
62
  return get_document(classname)
@@ -65,6 +65,5 @@ class UDataMongoEngine(MongoEngine):
65
65
  raise ValueError(message)
66
66
 
67
67
 
68
-
69
68
  db = UDataMongoEngine()
70
- session_interface = MongoEngineSessionInterface(db)
69
+ session_interface = MongoEngineSessionInterface(db)
udata/mongo/errors.py CHANGED
@@ -1,8 +1,9 @@
1
1
  from mongoengine.errors import ValidationError
2
2
 
3
+
3
4
  class FieldValidationError(ValidationError):
4
5
  field: str
5
6
 
6
7
  def __init__(self, *args, field: str, **kwargs):
7
8
  self.field = field
8
- super().__init__(*args, **kwargs)
9
+ super().__init__(*args, **kwargs)
@@ -1,9 +1,8 @@
1
1
  import logging
2
-
3
2
  from datetime import date, datetime
4
3
 
5
4
  from mongoengine import EmbeddedDocument
6
- from mongoengine.fields import DictField, BaseField
5
+ from mongoengine.fields import BaseField, DictField
7
6
 
8
7
  log = logging.getLogger(__name__)
9
8
 
@@ -17,9 +16,9 @@ class ExtrasField(DictField):
17
16
  super(ExtrasField, self).__init__()
18
17
 
19
18
  def register(self, key, dbtype):
20
- '''Register a DB type to add constraint on a given extra key'''
19
+ """Register a DB type to add constraint on a given extra key"""
21
20
  if not issubclass(dbtype, (BaseField, EmbeddedDocument)):
22
- msg = 'ExtrasField can only register MongoEngine fields'
21
+ msg = "ExtrasField can only register MongoEngine fields"
23
22
  raise TypeError(msg)
24
23
  self.registered[key] = dbtype
25
24
 
@@ -32,28 +31,31 @@ class ExtrasField(DictField):
32
31
 
33
32
  if not extra_cls:
34
33
  if not isinstance(value, ALLOWED_TYPES):
35
- types = ', '.join(t.__name__ for t in ALLOWED_TYPES)
36
- msg = 'Value should be an instance of: {types}'
34
+ types = ", ".join(t.__name__ for t in ALLOWED_TYPES)
35
+ msg = "Value should be an instance of: {types}"
37
36
  errors[key] = msg.format(types=types)
38
37
  continue
39
38
 
40
39
  try:
41
40
  if issubclass(extra_cls, EmbeddedDocument):
42
- (value.validate()
43
- if isinstance(value, extra_cls)
44
- else extra_cls(**value).validate())
41
+ (
42
+ value.validate()
43
+ if isinstance(value, extra_cls)
44
+ else extra_cls(**value).validate()
45
+ )
45
46
  else:
46
47
  extra_cls().validate(value)
47
48
  except Exception as e:
48
- errors[key] = getattr(e, 'message', str(e))
49
+ errors[key] = getattr(e, "message", str(e))
49
50
 
50
51
  if errors:
51
- self.error('Unsupported types', errors=errors)
52
+ self.error("Unsupported types", errors=errors)
52
53
 
53
54
  def __call__(self, key):
54
55
  def inner(cls):
55
56
  self.register(key, cls)
56
57
  return cls
58
+
57
59
  return inner
58
60
 
59
61
  def to_python(self, value):
@@ -75,29 +77,37 @@ class OrganizationExtrasField(ExtrasField):
75
77
  optional_keys = ["choices"]
76
78
  valid_types = ["str", "int", "float", "bool", "datetime", "date", "choice"]
77
79
 
78
- for elem in values.get('custom', []):
80
+ for elem in values.get("custom", []):
79
81
  # Check if all mandatory keys are in the dictionary
80
82
  if not all(key in elem for key in mandatory_keys):
81
- errors['custom'] = 'The dictionary does not contain the mandatory keys: \'title\', \'description\', \'type\'.'
83
+ errors["custom"] = (
84
+ "The dictionary does not contain the mandatory keys: 'title', 'description', 'type'."
85
+ )
82
86
 
83
87
  # Check if the dictionary contains only keys that are either mandatory or optional
84
88
  if not all(key in mandatory_keys + optional_keys for key in elem):
85
- errors['custom'] = 'The dictionary does contains extra keys than allowed ones.'
89
+ errors["custom"] = "The dictionary does contains extra keys than allowed ones."
86
90
 
87
91
  # Check if the "type" value is one of the valid types
88
92
  if elem.get("type") not in valid_types:
89
- errors['type'] = ('Type \'{type}\' of \'{title}\' should be one of: {types}'
90
- .format(type=elem.get("type"), title=elem.get("title"), types=valid_types))
93
+ errors["type"] = "Type '{type}' of '{title}' should be one of: {types}".format(
94
+ type=elem.get("type"), title=elem.get("title"), types=valid_types
95
+ )
91
96
 
92
97
  # Check if the "choices" key is present only if the type is "choice" and it's not an empty list
93
98
  is_choices_valid = True
94
99
  if elem.get("type") == "choice":
95
- is_choices_valid = "choices" in elem and isinstance(elem["choices"], list) and len(
96
- elem["choices"]) > 0
100
+ is_choices_valid = (
101
+ "choices" in elem
102
+ and isinstance(elem["choices"], list)
103
+ and len(elem["choices"]) > 0
104
+ )
97
105
  elif "choices" in elem:
98
106
  is_choices_valid = False
99
107
  if not is_choices_valid:
100
- errors['choices'] = 'The \'choices\' key must be an non empty list and can only be present when type \'choice\' is selected.'
108
+ errors["choices"] = (
109
+ "The 'choices' key must be an non empty list and can only be present when type 'choice' is selected."
110
+ )
101
111
 
102
112
  if errors:
103
- self.error('Custom extras error', errors=errors)
113
+ self.error("Custom extras error", errors=errors)
udata/mongo/queryset.py CHANGED
@@ -1,6 +1,6 @@
1
1
  import logging
2
2
 
3
- from bson import ObjectId, DBRef
3
+ from bson import DBRef, ObjectId
4
4
  from flask_mongoengine import BaseQuerySet
5
5
 
6
6
  from udata.utils import Paginable
@@ -9,7 +9,8 @@ log = logging.getLogger(__name__)
9
9
 
10
10
 
11
11
  class DBPaginator(Paginable):
12
- '''A simple paginable implementation'''
12
+ """A simple paginable implementation"""
13
+
13
14
  def __init__(self, queryset):
14
15
  self.queryset = queryset
15
16
 
@@ -45,8 +46,7 @@ class UDataQuerySet(BaseQuerySet):
45
46
  data = self.in_bulk(ids)
46
47
  return [data[id] for id in ids]
47
48
 
48
- def get_or_create(self, write_concern=None, auto_save=True,
49
- *q_objs, **query):
49
+ def get_or_create(self, write_concern=None, auto_save=True, *q_objs, **query):
50
50
  """Retrieve unique object or create, if it doesn't exist.
51
51
 
52
52
  Returns a tuple of ``(object, created)``, where ``object`` is
@@ -58,7 +58,7 @@ class UDataQuerySet(BaseQuerySet):
58
58
  https://github.com/MongoEngine/mongoengine/
59
59
  pull/1029/files#diff-05c70acbd0634d6d05e4a6e3a9b7d66b
60
60
  """
61
- defaults = query.pop('defaults', {})
61
+ defaults = query.pop("defaults", {})
62
62
  try:
63
63
  doc = self.get(*q_objs, **query)
64
64
  return doc, False
@@ -71,7 +71,7 @@ class UDataQuerySet(BaseQuerySet):
71
71
  return doc, True
72
72
 
73
73
  def generic_in(self, **kwargs):
74
- '''Bypass buggy GenericReferenceField querying issue'''
74
+ """Bypass buggy GenericReferenceField querying issue"""
75
75
  query = {}
76
76
  for key, value in kwargs.items():
77
77
  if not value:
@@ -82,15 +82,15 @@ class UDataQuerySet(BaseQuerySet):
82
82
  if isinstance(value, (list, tuple)):
83
83
  if all(isinstance(v, str) for v in value):
84
84
  ids = [ObjectId(v) for v in value]
85
- query['{0}._ref.$id'.format(key)] = {'$in': ids}
85
+ query["{0}._ref.$id".format(key)] = {"$in": ids}
86
86
  elif all(isinstance(v, DBRef) for v in value):
87
- query['{0}._ref'.format(key)] = {'$in': value}
87
+ query["{0}._ref".format(key)] = {"$in": value}
88
88
  elif all(isinstance(v, ObjectId) for v in value):
89
- query['{0}._ref.$id'.format(key)] = {'$in': value}
89
+ query["{0}._ref.$id".format(key)] = {"$in": value}
90
90
  elif isinstance(value, ObjectId):
91
- query['{0}._ref.$id'.format(key)] = value
91
+ query["{0}._ref.$id".format(key)] = value
92
92
  elif isinstance(value, str):
93
- query['{0}._ref.$id'.format(key)] = ObjectId(value)
93
+ query["{0}._ref.$id".format(key)] = ObjectId(value)
94
94
  else:
95
- self.error('expect a list of string, ObjectId or DBRef')
95
+ self.error("expect a list of string, ObjectId or DBRef")
96
96
  return self(__raw__=query)
@@ -1,27 +1,36 @@
1
1
  import logging
2
- import slugify
3
2
 
3
+ import slugify
4
4
  from flask_mongoengine import Document
5
5
  from mongoengine.fields import StringField
6
- from mongoengine.signals import pre_save, post_delete
6
+ from mongoengine.signals import post_delete, pre_save
7
7
 
8
- from .queryset import UDataQuerySet
9
8
  from udata.utils import is_uuid
10
9
 
10
+ from .queryset import UDataQuerySet
11
+
11
12
  log = logging.getLogger(__name__)
12
13
 
13
14
 
14
15
  class SlugField(StringField):
15
- '''
16
+ """
16
17
  A field that that produces a slug from the inputs and auto-
17
18
  increments the slug if the value already exists.
18
- '''
19
+ """
20
+
19
21
  # Do not remove, this is required to trigger field population
20
22
  _auto_gen = True
21
23
 
22
- def __init__(self, populate_from=None, update=False, lower_case=True,
23
- separator='-', follow=False, **kwargs):
24
- kwargs.setdefault('unique', True)
24
+ def __init__(
25
+ self,
26
+ populate_from=None,
27
+ update=False,
28
+ lower_case=True,
29
+ separator="-",
30
+ follow=False,
31
+ **kwargs,
32
+ ):
33
+ kwargs.setdefault("unique", True)
25
34
  self.populate_from = populate_from
26
35
  self.update = update
27
36
  self.lower_case = lower_case
@@ -33,7 +42,7 @@ class SlugField(StringField):
33
42
  def __get__(self, instance, owner):
34
43
  # mongoengine calls this after document initialization
35
44
  # We register signals handlers here to have a owner reference
36
- if not hasattr(self, 'owner'):
45
+ if not hasattr(self, "owner"):
37
46
  self.owner = owner
38
47
  pre_save.connect(self.populate_on_pre_save, sender=owner)
39
48
  if self.follow:
@@ -51,20 +60,20 @@ class SlugField(StringField):
51
60
  pass
52
61
 
53
62
  def slugify(self, value):
54
- '''
63
+ """
55
64
  Apply slugification according to specified field rules
56
- '''
65
+ """
57
66
  if value is None:
58
67
  return
59
68
 
60
- return slugify.slugify(value, max_length=self.max_length,
61
- separator=self.separator,
62
- to_lower=self.lower_case)
69
+ return slugify.slugify(
70
+ value, max_length=self.max_length, separator=self.separator, to_lower=self.lower_case
71
+ )
63
72
 
64
73
  def latest(self, value):
65
- '''
74
+ """
66
75
  Get the latest object for a given old slug
67
- '''
76
+ """
68
77
  namespace = self.owner_document.__name__
69
78
  follow = SlugFollow.objects(namespace=namespace, old_slug=value).first()
70
79
  if follow:
@@ -72,9 +81,9 @@ class SlugField(StringField):
72
81
  return None
73
82
 
74
83
  def cleanup_on_delete(self, sender, document, **kwargs):
75
- '''
84
+ """
76
85
  Clean up slug redirections on object deletion
77
- '''
86
+ """
78
87
  if not self.follow or sender is not self.owner_document:
79
88
  return
80
89
  slug = getattr(document, self.db_field)
@@ -88,30 +97,31 @@ class SlugField(StringField):
88
97
 
89
98
 
90
99
  class SlugFollow(Document):
91
- '''
100
+ """
92
101
  Keeps track of slug changes for a given namespace/class.
93
102
  Fields are:
94
103
  * namespace - A namespace under which this slug falls
95
104
  (e.g. match, team, user etc)
96
105
  * old_slug - Before change slug.
97
106
  * new_slug - After change slug
98
- '''
107
+ """
108
+
99
109
  namespace = StringField(required=True)
100
110
  old_slug = StringField(required=True)
101
111
  new_slug = StringField(required=True)
102
112
 
103
113
  meta = {
104
- 'indexes': [
105
- ('namespace', 'old_slug'),
114
+ "indexes": [
115
+ ("namespace", "old_slug"),
106
116
  ],
107
- 'queryset_class': UDataQuerySet,
117
+ "queryset_class": UDataQuerySet,
108
118
  }
109
119
 
110
120
 
111
121
  def populate_slug(instance, field):
112
- '''
122
+ """
113
123
  Populate a slug field if needed.
114
- '''
124
+ """
115
125
  value = getattr(instance, field.db_field)
116
126
 
117
127
  try:
@@ -164,14 +174,14 @@ def populate_slug(instance, field):
164
174
 
165
175
  while exists(slug):
166
176
  # keep space for index suffix, trim slug if needed
167
- slug_overflow = len('{0}-{1}'.format(base_slug, index)) - field.max_length
177
+ slug_overflow = len("{0}-{1}".format(base_slug, index)) - field.max_length
168
178
  if slug_overflow >= 1:
169
179
  base_slug = base_slug[:-slug_overflow]
170
- slug = '{0}-{1}'.format(base_slug, index)
180
+ slug = "{0}-{1}".format(base_slug, index)
171
181
  index += 1
172
182
 
173
183
  if is_uuid(slug):
174
- slug = '{0}-uuid'.format(slug)
184
+ slug = "{0}-uuid".format(slug)
175
185
 
176
186
  # Track old slugs for this class
177
187
  if field.follow and old_slug != slug:
@@ -1,6 +1,5 @@
1
- from slugify import slugify
2
-
3
1
  from mongoengine.fields import ListField, StringField
2
+ from slugify import slugify
4
3
 
5
4
 
6
5
  class TagListField(ListField):
udata/mongo/url_field.py CHANGED
@@ -4,7 +4,7 @@ from udata import uris
4
4
 
5
5
 
6
6
  class URLField(StringField):
7
- '''
7
+ """
8
8
  An URL field using the udata URL normalization and validation rules.
9
9
 
10
10
  The URL spaces are automatically stripped.
@@ -18,9 +18,9 @@ class URLField(StringField):
18
18
  :params list schemes: List of allowed schemes
19
19
  :params list tlds: List of allowed TLDs
20
20
 
21
- '''
22
- def __init__(self, private=None, local=None, schemes=None, tlds=None,
23
- **kwargs):
21
+ """
22
+
23
+ def __init__(self, private=None, local=None, schemes=None, tlds=None, **kwargs):
24
24
  super(URLField, self).__init__(**kwargs)
25
25
  self.private = private
26
26
  self.local = local
@@ -36,7 +36,7 @@ class URLField(StringField):
36
36
  super(URLField, self).validate(value)
37
37
  kwargs = {
38
38
  a: getattr(self, a)
39
- for a in ('private', 'local', 'schemes', 'tlds')
39
+ for a in ("private", "local", "schemes", "tlds")
40
40
  if getattr(self, a) is not None
41
41
  }
42
42
  try:
@@ -7,11 +7,12 @@ log = logging.getLogger(__name__)
7
7
 
8
8
 
9
9
  class AutoUUIDField(UUIDField):
10
- '''
10
+ """
11
11
  An autopopulated UUID field.
12
- '''
12
+ """
13
+
13
14
  def __init__(self, **kwargs):
14
- kwargs.setdefault('binary', False)
15
+ kwargs.setdefault("binary", False)
15
16
  super(AutoUUIDField, self).__init__(**kwargs)
16
17
 
17
18
  def __set__(self, instance, value):
@@ -1 +1 @@
1
- from .mattermost import notify_potential_spam #noqa
1
+ from .mattermost import notify_potential_spam # noqa
@@ -1,21 +1,22 @@
1
1
  import requests
2
- from udata.core.spam.signals import on_new_potential_spam
3
2
  from flask import current_app
4
3
 
4
+ from udata.core.spam.signals import on_new_potential_spam
5
+
5
6
 
6
7
  @on_new_potential_spam.connect
7
8
  def notify_potential_spam(sender, **kwargs):
8
- message = kwargs.get('message')
9
- reason = kwargs.get('reason')
10
- text = kwargs.get('text')
9
+ message = kwargs.get("message")
10
+ reason = kwargs.get("reason")
11
+ text = kwargs.get("text")
11
12
 
12
- message = f':warning: @all {message}'
13
+ message = f":warning: @all {message}"
13
14
 
14
15
  if reason:
15
- message += f' ({reason})'
16
+ message += f" ({reason})"
16
17
 
17
18
  if text:
18
- message += f'\n\n> {text}'
19
+ message += f"\n\n> {text}"
19
20
 
20
21
  send_message(message)
21
22
 
@@ -26,11 +27,11 @@ def send_message(text: str):
26
27
  Args:
27
28
  text (str): Text to send to a channel
28
29
  """
29
- webhook = current_app.config.get('MATTERMOST_WEBHOOK')
30
+ webhook = current_app.config.get("MATTERMOST_WEBHOOK")
30
31
  if not webhook:
31
32
  return
32
33
 
33
- data = {'text': text}
34
+ data = {"text": text}
34
35
 
35
36
  r = requests.post(webhook, json=data)
36
37
  r.raise_for_status()