udata 9.1.2.dev30355__py2.py3-none-any.whl → 9.1.2.dev30382__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 (425) 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 +135 -124
  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 +56 -54
  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/db/tasks.py +2 -1
  199. udata/entrypoints.py +35 -31
  200. udata/errors.py +2 -1
  201. udata/event/values.py +6 -6
  202. udata/factories.py +2 -2
  203. udata/features/identicon/api.py +5 -6
  204. udata/features/identicon/backends.py +48 -55
  205. udata/features/identicon/tests/test_backends.py +4 -5
  206. udata/features/notifications/__init__.py +0 -1
  207. udata/features/notifications/actions.py +9 -9
  208. udata/features/notifications/api.py +17 -13
  209. udata/features/territories/__init__.py +12 -10
  210. udata/features/territories/api.py +14 -15
  211. udata/features/territories/models.py +23 -28
  212. udata/features/transfer/actions.py +8 -11
  213. udata/features/transfer/api.py +84 -77
  214. udata/features/transfer/factories.py +2 -1
  215. udata/features/transfer/models.py +11 -12
  216. udata/features/transfer/notifications.py +19 -15
  217. udata/features/transfer/permissions.py +5 -5
  218. udata/forms/__init__.py +5 -2
  219. udata/forms/fields.py +164 -172
  220. udata/forms/validators.py +19 -22
  221. udata/forms/widgets.py +9 -13
  222. udata/frontend/__init__.py +31 -26
  223. udata/frontend/csv.py +68 -58
  224. udata/frontend/markdown.py +40 -44
  225. udata/harvest/actions.py +89 -77
  226. udata/harvest/api.py +294 -238
  227. udata/harvest/backends/__init__.py +4 -4
  228. udata/harvest/backends/base.py +128 -111
  229. udata/harvest/backends/dcat.py +80 -66
  230. udata/harvest/commands.py +56 -60
  231. udata/harvest/csv.py +8 -8
  232. udata/harvest/exceptions.py +6 -3
  233. udata/harvest/filters.py +24 -23
  234. udata/harvest/forms.py +27 -28
  235. udata/harvest/models.py +88 -80
  236. udata/harvest/notifications.py +15 -10
  237. udata/harvest/signals.py +13 -13
  238. udata/harvest/tasks.py +11 -10
  239. udata/harvest/tests/factories.py +23 -24
  240. udata/harvest/tests/test_actions.py +136 -166
  241. udata/harvest/tests/test_api.py +220 -214
  242. udata/harvest/tests/test_base_backend.py +117 -112
  243. udata/harvest/tests/test_dcat_backend.py +380 -308
  244. udata/harvest/tests/test_filters.py +33 -22
  245. udata/harvest/tests/test_models.py +11 -14
  246. udata/harvest/tests/test_notifications.py +6 -7
  247. udata/harvest/tests/test_tasks.py +7 -6
  248. udata/i18n.py +237 -78
  249. udata/linkchecker/backends.py +5 -11
  250. udata/linkchecker/checker.py +23 -22
  251. udata/linkchecker/commands.py +4 -6
  252. udata/linkchecker/models.py +6 -6
  253. udata/linkchecker/tasks.py +18 -20
  254. udata/mail.py +21 -21
  255. udata/migrations/2020-07-24-remove-s-from-scope-oauth.py +9 -8
  256. udata/migrations/2020-08-24-add-fs-filename.py +9 -8
  257. udata/migrations/2020-09-28-update-reuses-datasets-metrics.py +5 -4
  258. udata/migrations/2020-10-16-migrate-ods-resources.py +9 -10
  259. udata/migrations/2021-04-08-update-schema-with-new-structure.py +8 -7
  260. udata/migrations/2021-05-27-fix-default-schema-name.py +7 -6
  261. udata/migrations/2021-07-05-remove-unused-badges.py +17 -15
  262. udata/migrations/2021-07-07-update-schema-for-community-resources.py +7 -6
  263. udata/migrations/2021-08-17-follow-integrity.py +5 -4
  264. udata/migrations/2021-08-17-harvest-integrity.py +13 -12
  265. udata/migrations/2021-08-17-oauth2client-integrity.py +5 -4
  266. udata/migrations/2021-08-17-transfer-integrity.py +5 -4
  267. udata/migrations/2021-08-17-users-integrity.py +9 -8
  268. udata/migrations/2021-12-14-reuse-topics.py +7 -6
  269. udata/migrations/2022-04-21-improve-extension-detection.py +8 -7
  270. udata/migrations/2022-09-22-clean-inactive-harvest-datasets.py +16 -14
  271. udata/migrations/2022-10-10-add-fs_uniquifier-to-user-model.py +6 -6
  272. udata/migrations/2022-10-10-migrate-harvest-extras.py +36 -26
  273. udata/migrations/2023-02-08-rename-internal-dates.py +46 -28
  274. udata/migrations/2024-01-29-fix-reuse-and-dataset-with-private-None.py +10 -8
  275. udata/migrations/2024-03-22-migrate-activity-kwargs-to-extras.py +6 -4
  276. udata/migrations/2024-06-11-fix-reuse-datasets-references.py +7 -6
  277. udata/migrations/__init__.py +123 -105
  278. udata/models/__init__.py +4 -4
  279. udata/mongo/__init__.py +13 -11
  280. udata/mongo/badges_field.py +3 -2
  281. udata/mongo/datetime_fields.py +13 -12
  282. udata/mongo/document.py +17 -16
  283. udata/mongo/engine.py +15 -16
  284. udata/mongo/errors.py +2 -1
  285. udata/mongo/extras_fields.py +30 -20
  286. udata/mongo/queryset.py +12 -12
  287. udata/mongo/slug_fields.py +38 -28
  288. udata/mongo/taglist_field.py +1 -2
  289. udata/mongo/url_field.py +5 -5
  290. udata/mongo/uuid_fields.py +4 -3
  291. udata/notifications/__init__.py +1 -1
  292. udata/notifications/mattermost.py +10 -9
  293. udata/rdf.py +167 -188
  294. udata/routing.py +40 -45
  295. udata/search/__init__.py +18 -19
  296. udata/search/adapter.py +17 -16
  297. udata/search/commands.py +44 -51
  298. udata/search/fields.py +13 -20
  299. udata/search/query.py +23 -18
  300. udata/search/result.py +9 -10
  301. udata/sentry.py +21 -19
  302. udata/settings.py +262 -198
  303. udata/sitemap.py +8 -6
  304. udata/static/chunks/{11.e9b9ca1f3e03d4020377.js → 11.52e531c19f8de80c00cf.js} +3 -3
  305. udata/static/chunks/{11.e9b9ca1f3e03d4020377.js.map → 11.52e531c19f8de80c00cf.js.map} +1 -1
  306. udata/static/chunks/{13.038c0d9aa0dfa0181c4b.js → 13.c3343a7f1070061c0e10.js} +2 -2
  307. udata/static/chunks/{13.038c0d9aa0dfa0181c4b.js.map → 13.c3343a7f1070061c0e10.js.map} +1 -1
  308. udata/static/chunks/{16.0baa2b64a74a2dcde25c.js → 16.8fa42440ad75ca172e6d.js} +2 -2
  309. udata/static/chunks/{16.0baa2b64a74a2dcde25c.js.map → 16.8fa42440ad75ca172e6d.js.map} +1 -1
  310. udata/static/chunks/{19.350a9f150b074b4ecefa.js → 19.9c6c8412729cd6d59cfa.js} +3 -3
  311. udata/static/chunks/{19.350a9f150b074b4ecefa.js.map → 19.9c6c8412729cd6d59cfa.js.map} +1 -1
  312. udata/static/chunks/{5.6ebbce2b9b3e696d3da5.js → 5.71d15c2e4f21feee2a9a.js} +3 -3
  313. udata/static/chunks/{5.6ebbce2b9b3e696d3da5.js.map → 5.71d15c2e4f21feee2a9a.js.map} +1 -1
  314. udata/static/chunks/{6.d8a5f7b017bcbd083641.js → 6.9139dc098b8ea640b890.js} +3 -3
  315. udata/static/chunks/{6.d8a5f7b017bcbd083641.js.map → 6.9139dc098b8ea640b890.js.map} +1 -1
  316. udata/static/common.js +1 -1
  317. udata/static/common.js.map +1 -1
  318. udata/storage/s3.py +20 -13
  319. udata/tags.py +4 -5
  320. udata/tasks.py +43 -42
  321. udata/tests/__init__.py +9 -6
  322. udata/tests/api/__init__.py +5 -6
  323. udata/tests/api/test_auth_api.py +395 -321
  324. udata/tests/api/test_base_api.py +31 -33
  325. udata/tests/api/test_contact_points.py +7 -9
  326. udata/tests/api/test_dataservices_api.py +211 -158
  327. udata/tests/api/test_datasets_api.py +823 -812
  328. udata/tests/api/test_follow_api.py +13 -15
  329. udata/tests/api/test_me_api.py +95 -112
  330. udata/tests/api/test_organizations_api.py +301 -339
  331. udata/tests/api/test_reports_api.py +35 -25
  332. udata/tests/api/test_reuses_api.py +134 -139
  333. udata/tests/api/test_swagger.py +5 -5
  334. udata/tests/api/test_tags_api.py +18 -25
  335. udata/tests/api/test_topics_api.py +94 -94
  336. udata/tests/api/test_transfer_api.py +53 -48
  337. udata/tests/api/test_user_api.py +128 -141
  338. udata/tests/apiv2/test_datasets.py +290 -198
  339. udata/tests/apiv2/test_me_api.py +10 -11
  340. udata/tests/apiv2/test_organizations.py +56 -74
  341. udata/tests/apiv2/test_swagger.py +5 -5
  342. udata/tests/apiv2/test_topics.py +69 -87
  343. udata/tests/cli/test_cli_base.py +8 -8
  344. udata/tests/cli/test_db_cli.py +21 -19
  345. udata/tests/dataservice/test_dataservice_tasks.py +8 -12
  346. udata/tests/dataset/test_csv_adapter.py +44 -35
  347. udata/tests/dataset/test_dataset_actions.py +2 -3
  348. udata/tests/dataset/test_dataset_commands.py +7 -8
  349. udata/tests/dataset/test_dataset_events.py +36 -29
  350. udata/tests/dataset/test_dataset_model.py +224 -217
  351. udata/tests/dataset/test_dataset_rdf.py +142 -131
  352. udata/tests/dataset/test_dataset_tasks.py +15 -15
  353. udata/tests/dataset/test_resource_preview.py +10 -13
  354. udata/tests/features/territories/__init__.py +9 -13
  355. udata/tests/features/territories/test_territories_api.py +71 -91
  356. udata/tests/forms/test_basic_fields.py +7 -7
  357. udata/tests/forms/test_current_user_field.py +39 -66
  358. udata/tests/forms/test_daterange_field.py +31 -39
  359. udata/tests/forms/test_dict_field.py +28 -26
  360. udata/tests/forms/test_extras_fields.py +102 -76
  361. udata/tests/forms/test_form_field.py +8 -8
  362. udata/tests/forms/test_image_field.py +33 -26
  363. udata/tests/forms/test_model_field.py +134 -123
  364. udata/tests/forms/test_model_list_field.py +7 -7
  365. udata/tests/forms/test_nested_model_list_field.py +117 -79
  366. udata/tests/forms/test_publish_as_field.py +36 -65
  367. udata/tests/forms/test_reference_field.py +34 -53
  368. udata/tests/forms/test_user_forms.py +23 -21
  369. udata/tests/forms/test_uuid_field.py +6 -10
  370. udata/tests/frontend/__init__.py +9 -6
  371. udata/tests/frontend/test_auth.py +7 -6
  372. udata/tests/frontend/test_csv.py +81 -96
  373. udata/tests/frontend/test_hooks.py +43 -43
  374. udata/tests/frontend/test_markdown.py +211 -191
  375. udata/tests/helpers.py +32 -37
  376. udata/tests/models.py +2 -2
  377. udata/tests/organization/test_csv_adapter.py +21 -16
  378. udata/tests/organization/test_notifications.py +11 -18
  379. udata/tests/organization/test_organization_model.py +13 -13
  380. udata/tests/organization/test_organization_rdf.py +29 -22
  381. udata/tests/organization/test_organization_tasks.py +16 -17
  382. udata/tests/plugin.py +76 -73
  383. udata/tests/reuse/test_reuse_model.py +21 -21
  384. udata/tests/reuse/test_reuse_task.py +11 -13
  385. udata/tests/search/__init__.py +11 -12
  386. udata/tests/search/test_adapter.py +60 -70
  387. udata/tests/search/test_query.py +16 -16
  388. udata/tests/search/test_results.py +10 -7
  389. udata/tests/site/test_site_api.py +11 -16
  390. udata/tests/site/test_site_metrics.py +20 -30
  391. udata/tests/site/test_site_model.py +4 -5
  392. udata/tests/site/test_site_rdf.py +94 -78
  393. udata/tests/test_activity.py +17 -17
  394. udata/tests/test_discussions.py +292 -299
  395. udata/tests/test_i18n.py +37 -40
  396. udata/tests/test_linkchecker.py +91 -85
  397. udata/tests/test_mail.py +13 -17
  398. udata/tests/test_migrations.py +219 -180
  399. udata/tests/test_model.py +164 -157
  400. udata/tests/test_notifications.py +17 -17
  401. udata/tests/test_owned.py +14 -14
  402. udata/tests/test_rdf.py +25 -23
  403. udata/tests/test_routing.py +89 -93
  404. udata/tests/test_storages.py +137 -128
  405. udata/tests/test_tags.py +44 -46
  406. udata/tests/test_topics.py +7 -7
  407. udata/tests/test_transfer.py +42 -49
  408. udata/tests/test_uris.py +160 -161
  409. udata/tests/test_utils.py +79 -71
  410. udata/tests/user/test_user_rdf.py +5 -9
  411. udata/tests/workers/test_jobs_commands.py +57 -58
  412. udata/tests/workers/test_tasks_routing.py +23 -29
  413. udata/tests/workers/test_workers_api.py +125 -131
  414. udata/tests/workers/test_workers_helpers.py +6 -6
  415. udata/tracking.py +4 -6
  416. udata/uris.py +45 -46
  417. udata/utils.py +68 -66
  418. udata/wsgi.py +1 -1
  419. {udata-9.1.2.dev30355.dist-info → udata-9.1.2.dev30382.dist-info}/METADATA +3 -2
  420. udata-9.1.2.dev30382.dist-info/RECORD +704 -0
  421. udata-9.1.2.dev30355.dist-info/RECORD +0 -704
  422. {udata-9.1.2.dev30355.dist-info → udata-9.1.2.dev30382.dist-info}/LICENSE +0 -0
  423. {udata-9.1.2.dev30355.dist-info → udata-9.1.2.dev30382.dist-info}/WHEEL +0 -0
  424. {udata-9.1.2.dev30355.dist-info → udata-9.1.2.dev30382.dist-info}/entry_points.txt +0 -0
  425. {udata-9.1.2.dev30355.dist-info → udata-9.1.2.dev30382.dist-info}/top_level.txt +0 -0
@@ -5,288 +5,282 @@ from flask import url_for
5
5
  from udata.core.jobs.models import PeriodicTask
6
6
  from udata.core.user.factories import AdminFactory
7
7
  from udata.tasks import celery, job
8
- from udata.utils import faker
9
-
10
8
  from udata.tests.api import APITestCase
9
+ from udata.utils import faker
11
10
 
12
11
 
13
12
  class JobsAPITest(APITestCase):
14
13
  def test_schedulable_jobs_list(self):
15
- @celery.task(name='a-schedulable-job', schedulable=True)
14
+ @celery.task(name="a-schedulable-job", schedulable=True)
16
15
  def test_job():
17
16
  pass
18
17
 
19
- response = self.get(url_for('api.schedulable_jobs'))
18
+ response = self.get(url_for("api.schedulable_jobs"))
20
19
  self.assert200(response)
21
- self.assertIn('a-schedulable-job', response.json)
20
+ self.assertIn("a-schedulable-job", response.json)
22
21
 
23
22
  def test_schedulable_jobs_list_with_decorator(self):
24
- @job('a-job')
23
+ @job("a-job")
25
24
  def test_job():
26
25
  pass
27
26
 
28
- response = self.get(url_for('api.schedulable_jobs'))
27
+ response = self.get(url_for("api.schedulable_jobs"))
29
28
  self.assert200(response)
30
- self.assertIn('a-job', response.json)
29
+ self.assertIn("a-job", response.json)
31
30
 
32
31
  def test_scheduled_jobs_list(self):
33
- @job('a-job')
32
+ @job("a-job")
34
33
  def test_job():
35
34
  pass
36
35
 
37
36
  for i in range(6):
38
- params = {
39
- 'name': faker.name(),
40
- 'description': faker.sentence(),
41
- 'task': 'a-job'
42
- }
37
+ params = {"name": faker.name(), "description": faker.sentence(), "task": "a-job"}
43
38
  if i % 2:
44
- params['crontab'] = PeriodicTask.Crontab(minute=str(i))
39
+ params["crontab"] = PeriodicTask.Crontab(minute=str(i))
45
40
  else:
46
- params['interval'] = PeriodicTask.Interval(every=i,
47
- period='minutes')
41
+ params["interval"] = PeriodicTask.Interval(every=i, period="minutes")
48
42
  PeriodicTask.objects.create(**params)
49
43
 
50
- response = self.get(url_for('api.jobs'))
44
+ response = self.get(url_for("api.jobs"))
51
45
  self.assert200(response)
52
46
 
53
47
  def test_create_job_need_admin(self):
54
- @job('a-job')
48
+ @job("a-job")
55
49
  def test_job():
56
50
  pass
57
51
 
58
52
  data = {
59
- 'name': 'A crontab job',
60
- 'description': 'A simple crontab job doing nothing',
61
- 'task': 'a-job',
53
+ "name": "A crontab job",
54
+ "description": "A simple crontab job doing nothing",
55
+ "task": "a-job",
62
56
  }
63
57
 
64
58
  self.login()
65
- response = self.post(url_for('api.jobs'), data)
59
+ response = self.post(url_for("api.jobs"), data)
66
60
  self.assert403(response)
67
61
 
68
62
  def test_create_crontab_job(self):
69
- @job('a-job')
63
+ @job("a-job")
70
64
  def test_job():
71
65
  pass
72
66
 
73
67
  data = {
74
- 'name': 'A crontab job',
75
- 'description': 'A simple crontab job doing nothing',
76
- 'task': 'a-job',
77
- 'crontab': {
78
- 'minute': '0',
79
- 'hour': '0'
80
- }
68
+ "name": "A crontab job",
69
+ "description": "A simple crontab job doing nothing",
70
+ "task": "a-job",
71
+ "crontab": {"minute": "0", "hour": "0"},
81
72
  }
82
73
 
83
74
  self.login(AdminFactory())
84
- response = self.post(url_for('api.jobs'), data)
75
+ response = self.post(url_for("api.jobs"), data)
85
76
  self.assert201(response)
86
77
 
87
- self.assertEqual(response.json['name'], data['name'])
88
- self.assertEqual(response.json['description'], data['description'])
89
- self.assertEqual(response.json['task'], data['task'])
90
- self.assertEqual(response.json['crontab'], {
91
- 'minute': '0',
92
- 'hour': '0',
93
- 'day_of_week': '*',
94
- 'day_of_month': '*',
95
- 'month_of_year': '*',
96
- })
78
+ self.assertEqual(response.json["name"], data["name"])
79
+ self.assertEqual(response.json["description"], data["description"])
80
+ self.assertEqual(response.json["task"], data["task"])
81
+ self.assertEqual(
82
+ response.json["crontab"],
83
+ {
84
+ "minute": "0",
85
+ "hour": "0",
86
+ "day_of_week": "*",
87
+ "day_of_month": "*",
88
+ "month_of_year": "*",
89
+ },
90
+ )
97
91
 
98
92
  def test_create_interval_job(self):
99
- @job('a-job')
93
+ @job("a-job")
100
94
  def test_job():
101
95
  pass
102
96
 
103
97
  data = {
104
- 'name': 'An interval job',
105
- 'description': 'A simple interval job doing nothing',
106
- 'task': 'a-job',
107
- 'interval': {
108
- 'every': 5,
109
- 'period': 'minutes'
110
- }
98
+ "name": "An interval job",
99
+ "description": "A simple interval job doing nothing",
100
+ "task": "a-job",
101
+ "interval": {"every": 5, "period": "minutes"},
111
102
  }
112
103
 
113
104
  self.login(AdminFactory())
114
- response = self.post(url_for('api.jobs'), data)
105
+ response = self.post(url_for("api.jobs"), data)
115
106
  self.assert201(response)
116
107
 
117
- self.assertEqual(response.json['name'], data['name'])
118
- self.assertEqual(response.json['description'], data['description'])
119
- self.assertEqual(response.json['task'], data['task'])
120
- self.assertEqual(response.json['interval'], data['interval'])
108
+ self.assertEqual(response.json["name"], data["name"])
109
+ self.assertEqual(response.json["description"], data["description"])
110
+ self.assertEqual(response.json["task"], data["task"])
111
+ self.assertEqual(response.json["interval"], data["interval"])
121
112
 
122
113
  def test_fail_on_create_with_both_crontab_and_interval(self):
123
- @job('a-job')
114
+ @job("a-job")
124
115
  def test_job():
125
116
  pass
126
117
 
127
118
  data = {
128
- 'name': 'A mixed job',
129
- 'description': 'A simple crontab job doing nothing',
130
- 'task': 'a-job',
131
- 'crontab': {
132
- 'minute': '0',
133
- 'hour': '0'
134
- },
135
- 'interval': {
136
- 'every': 5,
137
- 'period': 'minutes'
138
- }
119
+ "name": "A mixed job",
120
+ "description": "A simple crontab job doing nothing",
121
+ "task": "a-job",
122
+ "crontab": {"minute": "0", "hour": "0"},
123
+ "interval": {"every": 5, "period": "minutes"},
139
124
  }
140
125
 
141
126
  self.login(AdminFactory())
142
- response = self.post(url_for('api.jobs'), data)
127
+ response = self.post(url_for("api.jobs"), data)
143
128
  self.assertStatus(response, 400)
144
129
 
145
130
  def test_create_manual_job(self):
146
131
  pass
147
132
 
148
133
  def test_get_job(self):
149
- @job('a-job')
134
+ @job("a-job")
150
135
  def test_job():
151
136
  pass
152
137
 
153
138
  task = PeriodicTask.objects.create(
154
139
  name=faker.name(),
155
140
  description=faker.sentence(),
156
- task='a-job',
157
- crontab=PeriodicTask.Crontab(minute='5')
141
+ task="a-job",
142
+ crontab=PeriodicTask.Crontab(minute="5"),
158
143
  )
159
144
 
160
- response = self.get(url_for('api.job', id=task.id))
145
+ response = self.get(url_for("api.job", id=task.id))
161
146
  self.assert200(response)
162
- self.assertEqual(response.json['id'], str(task.id))
163
- self.assertEqual(response.json['name'], task.name)
164
- self.assertEqual(response.json['description'], task.description)
165
- self.assertEqual(response.json['task'], task.task)
147
+ self.assertEqual(response.json["id"], str(task.id))
148
+ self.assertEqual(response.json["name"], task.name)
149
+ self.assertEqual(response.json["description"], task.description)
150
+ self.assertEqual(response.json["task"], task.task)
166
151
 
167
152
  def test_update_job_need_admin(self):
168
- @job('a-job')
153
+ @job("a-job")
169
154
  def test_job():
170
155
  pass
171
156
 
172
157
  task = PeriodicTask.objects.create(
173
158
  name=faker.name(),
174
159
  description=faker.sentence(),
175
- task='a-job',
176
- crontab=PeriodicTask.Crontab(minute='5')
160
+ task="a-job",
161
+ crontab=PeriodicTask.Crontab(minute="5"),
177
162
  )
178
163
 
179
164
  self.login()
180
- response = self.put(url_for('api.job', id=task.id), {
181
- 'name': task.name,
182
- 'description': 'New description',
183
- 'task': task.task,
184
- 'crontab': task.crontab.to_json()
185
- })
165
+ response = self.put(
166
+ url_for("api.job", id=task.id),
167
+ {
168
+ "name": task.name,
169
+ "description": "New description",
170
+ "task": task.task,
171
+ "crontab": task.crontab.to_json(),
172
+ },
173
+ )
186
174
  self.assert403(response)
187
175
 
188
176
  def test_update_job(self):
189
- @job('a-job')
177
+ @job("a-job")
190
178
  def test_job():
191
179
  pass
192
180
 
193
181
  task = PeriodicTask.objects.create(
194
182
  name=faker.name(),
195
183
  description=faker.sentence(),
196
- task='a-job',
197
- crontab=PeriodicTask.Crontab(minute='5')
184
+ task="a-job",
185
+ crontab=PeriodicTask.Crontab(minute="5"),
198
186
  )
199
187
 
200
188
  self.login(AdminFactory())
201
- response = self.put(url_for('api.job', id=task.id), {
202
- 'name': task.name,
203
- 'description': 'New description',
204
- 'task': task.task,
205
- 'crontab': task.crontab.to_json()
206
- })
189
+ response = self.put(
190
+ url_for("api.job", id=task.id),
191
+ {
192
+ "name": task.name,
193
+ "description": "New description",
194
+ "task": task.task,
195
+ "crontab": task.crontab.to_json(),
196
+ },
197
+ )
207
198
  self.assert200(response)
208
199
 
209
- self.assertEqual(response.json['id'], str(task.id))
210
- self.assertEqual(response.json['name'], task.name)
211
- self.assertEqual(response.json['task'], task.task)
212
- self.assertEqual(response.json['description'], 'New description')
213
- self.assertIsNotNone(response.json['crontab'])
214
- self.assertIsNone(response.json['interval'])
200
+ self.assertEqual(response.json["id"], str(task.id))
201
+ self.assertEqual(response.json["name"], task.name)
202
+ self.assertEqual(response.json["task"], task.task)
203
+ self.assertEqual(response.json["description"], "New description")
204
+ self.assertIsNotNone(response.json["crontab"])
205
+ self.assertIsNone(response.json["interval"])
215
206
 
216
207
  def test_update_job_change_type(self):
217
- @job('a-job')
208
+ @job("a-job")
218
209
  def test_job():
219
210
  pass
220
211
 
221
212
  task = PeriodicTask.objects.create(
222
213
  name=faker.name(),
223
214
  description=faker.sentence(),
224
- task='a-job',
225
- crontab=PeriodicTask.Crontab(minute='5')
215
+ task="a-job",
216
+ crontab=PeriodicTask.Crontab(minute="5"),
226
217
  )
227
218
 
228
219
  self.login(AdminFactory())
229
- response = self.put(url_for('api.job', id=task.id), {
230
- 'name': task.name,
231
- 'description': task.description,
232
- 'task': task.task,
233
- 'interval': {
234
- 'every': 5,
235
- 'period': 'minutes',
236
- }
237
- })
220
+ response = self.put(
221
+ url_for("api.job", id=task.id),
222
+ {
223
+ "name": task.name,
224
+ "description": task.description,
225
+ "task": task.task,
226
+ "interval": {
227
+ "every": 5,
228
+ "period": "minutes",
229
+ },
230
+ },
231
+ )
238
232
  self.assert200(response)
239
233
 
240
- self.assertEqual(response.json['id'], str(task.id))
241
- self.assertEqual(response.json['name'], task.name)
242
- self.assertEqual(response.json['task'], task.task)
243
- self.assertEqual(response.json['description'], task.description)
244
- self.assertEqual(response.json['interval']['every'], 5)
245
- self.assertEqual(response.json['interval']['period'], 'minutes')
246
- self.assertIsNone(response.json['crontab'])
234
+ self.assertEqual(response.json["id"], str(task.id))
235
+ self.assertEqual(response.json["name"], task.name)
236
+ self.assertEqual(response.json["task"], task.task)
237
+ self.assertEqual(response.json["description"], task.description)
238
+ self.assertEqual(response.json["interval"]["every"], 5)
239
+ self.assertEqual(response.json["interval"]["period"], "minutes")
240
+ self.assertIsNone(response.json["crontab"])
247
241
 
248
242
  def test_delete_job_need_admin(self):
249
- @job('a-job')
243
+ @job("a-job")
250
244
  def test_job():
251
245
  pass
252
246
 
253
247
  task = PeriodicTask.objects.create(
254
248
  name=faker.name(),
255
249
  description=faker.sentence(),
256
- task='a-job',
257
- crontab=PeriodicTask.Crontab(minute='5')
250
+ task="a-job",
251
+ crontab=PeriodicTask.Crontab(minute="5"),
258
252
  )
259
253
 
260
254
  self.login()
261
- response = self.delete(url_for('api.job', id=task.id))
255
+ response = self.delete(url_for("api.job", id=task.id))
262
256
  self.assert403(response)
263
257
 
264
258
  def test_delete_job(self):
265
- @job('a-job')
259
+ @job("a-job")
266
260
  def test_job():
267
261
  pass
268
262
 
269
263
  task = PeriodicTask.objects.create(
270
264
  name=faker.name(),
271
265
  description=faker.sentence(),
272
- task='a-job',
273
- crontab=PeriodicTask.Crontab(minute='5')
266
+ task="a-job",
267
+ crontab=PeriodicTask.Crontab(minute="5"),
274
268
  )
275
269
 
276
270
  self.login(AdminFactory())
277
- response = self.delete(url_for('api.job', id=task.id))
271
+ response = self.delete(url_for("api.job", id=task.id))
278
272
  self.assert204(response)
279
273
 
280
274
  self.assertIsNone(PeriodicTask.objects(id=task.id).first())
281
275
 
282
- @skip('Need to be mocked and more details')
276
+ @skip("Need to be mocked and more details")
283
277
  def test_get_task(self):
284
278
  @celery.task
285
279
  def test_task():
286
- print('hello')
280
+ print("hello")
287
281
 
288
282
  result = test_task.delay() # Always eager so no async
289
283
 
290
- response = self.get(url_for('api.task', id=result.id))
284
+ response = self.get(url_for("api.task", id=result.id))
291
285
  self.assert200(response)
292
- self.assertEqual(response.json['id'], result.id)
286
+ self.assertEqual(response.json["id"], result.id)
@@ -1,16 +1,16 @@
1
- from udata.tests import TestCase
2
1
  from udata.settings import Defaults
3
2
  from udata.tasks import default_scheduler_config
3
+ from udata.tests import TestCase
4
4
 
5
5
 
6
6
  class DefaultSchedulerConfigTest(TestCase):
7
7
  def test_parse_default_value(self):
8
8
  db, url = default_scheduler_config(Defaults.MONGODB_HOST)
9
- self.assertEqual(db, 'udata')
10
- self.assertEqual(url, 'mongodb://localhost:27017')
9
+ self.assertEqual(db, "udata")
10
+ self.assertEqual(url, "mongodb://localhost:27017")
11
11
 
12
12
  def test_parse_url_with_auth(self):
13
- full_url = 'mongodb://userid:password@somewhere.com:1234/mydb'
13
+ full_url = "mongodb://userid:password@somewhere.com:1234/mydb"
14
14
  db, url = default_scheduler_config(full_url)
15
- self.assertEqual(db, 'mydb')
16
- self.assertEqual(url, 'mongodb://userid:password@somewhere.com:1234')
15
+ self.assertEqual(db, "mydb")
16
+ self.assertEqual(url, "mongodb://userid:password@somewhere.com:1234")
udata/tracking.py CHANGED
@@ -1,12 +1,10 @@
1
1
  def send_signal(signal, request, user, **kwargs):
2
- '''Generic method to send signals to Piwik
2
+ """Generic method to send signals to Piwik
3
3
 
4
4
  given that we always have to compute IP and UID for instance.
5
- '''
6
- params = {
7
- 'user_ip': request.remote_addr
8
- }
5
+ """
6
+ params = {"user_ip": request.remote_addr}
9
7
  params.update(kwargs)
10
8
  if user.is_authenticated:
11
- params['uid'] = user.id
9
+ params["uid"] = user.id
12
10
  signal.send(request.url, **params)
udata/uris.py CHANGED
@@ -1,48 +1,49 @@
1
1
  import re
2
2
 
3
- from werkzeug.routing import BuildError
4
3
  from flask import current_app, url_for
5
- from netaddr import IPAddress, AddrFormatError
6
- from udata.i18n import _
4
+ from netaddr import AddrFormatError, IPAddress
5
+ from werkzeug.routing import BuildError
7
6
 
7
+ from udata.i18n import _
8
8
  from udata.settings import Defaults
9
9
 
10
10
  URL_REGEX = re.compile(
11
- r'^'
11
+ r"^"
12
12
  # scheme
13
- r'^(?:(?P<scheme>[a-z0-9\.\-]*):)?//'
13
+ r"^(?:(?P<scheme>[a-z0-9\.\-]*):)?//"
14
14
  # user:pass authentication
15
- r'(?P<credentials>\S+(?::\S*)?@)?'
16
- r'(?:'
15
+ r"(?P<credentials>\S+(?::\S*)?@)?"
16
+ r"(?:"
17
17
  # localhost
18
- r'(?P<localhost>localhost(?:\.localdomain)?)'
19
- r'|'
18
+ r"(?P<localhost>localhost(?:\.localdomain)?)"
19
+ r"|"
20
20
  # IPv4 addresses
21
- r'(?P<ipv4>(?:\d{,3}\.){3}(?:\d{,3}))'
22
- r'|'
21
+ r"(?P<ipv4>(?:\d{,3}\.){3}(?:\d{,3}))"
22
+ r"|"
23
23
  # IPv6 address
24
- r'(?:\[(?P<ipv6>[0-9a-f:]+)\])'
25
- r'|'
24
+ r"(?:\[(?P<ipv6>[0-9a-f:]+)\])"
25
+ r"|"
26
26
  # host name
27
- r'(?:(?:[a-z\u00a1-\uffff0-9_]-?)*[a-z\u00a1-\uffff0-9]+)'
27
+ r"(?:(?:[a-z\u00a1-\uffff0-9_]-?)*[a-z\u00a1-\uffff0-9]+)"
28
28
  # domain name
29
- r'(?:\.(?:[a-z\u00a1-\uffff0-9_]-?)*[a-z\u00a1-\uffff0-9]+)*'
29
+ r"(?:\.(?:[a-z\u00a1-\uffff0-9_]-?)*[a-z\u00a1-\uffff0-9]+)*"
30
30
  # TLD identifier
31
- r'(?:\.(?P<tld>[a-z0-9\u00a1-\uffff]{2,}))'
32
- r')'
31
+ r"(?:\.(?P<tld>[a-z0-9\u00a1-\uffff]{2,}))"
32
+ r")"
33
33
  # port number
34
- r'(?::\d{2,5})?'
34
+ r"(?::\d{2,5})?"
35
35
  # resource path
36
- r'(?:/\S*)?'
36
+ r"(?:/\S*)?"
37
37
  # query string
38
- r'(?:\?\S*)?'
39
- r'$',
40
- re.UNICODE | re.IGNORECASE
38
+ r"(?:\?\S*)?"
39
+ r"$",
40
+ re.UNICODE | re.IGNORECASE,
41
41
  )
42
42
 
43
43
 
44
44
  class ValidationError(ValueError):
45
- '''Raised when URL is invalid'''
45
+ """Raised when URL is invalid"""
46
+
46
47
  pass
47
48
 
48
49
 
@@ -74,59 +75,57 @@ def endpoint_for(endpoint, fallback_endpoint=None, **values):
74
75
  return None
75
76
 
76
77
 
77
-
78
78
  def idna(string):
79
- return string.encode('idna').decode('utf8')
79
+ return string.encode("idna").decode("utf8")
80
80
 
81
81
 
82
- def validate(url, schemes=None, tlds=None, private=None, local=None,
83
- credentials=None):
84
- '''
82
+ def validate(url, schemes=None, tlds=None, private=None, local=None, credentials=None):
83
+ """
85
84
  Validate and normalize an URL
86
85
 
87
86
  :param str url: The URL to validate and normalize
88
87
  :return str: The normalized URL
89
88
  :raises ValidationError: when URL does not validate
90
- '''
89
+ """
91
90
  url = url.strip()
92
91
 
93
- private = config_for(private, 'URLS_ALLOW_PRIVATE')
94
- local = config_for(local, 'URLS_ALLOW_LOCAL')
95
- credentials = config_for(credentials, 'URLS_ALLOW_CREDENTIALS')
96
- schemes = config_for(schemes, 'URLS_ALLOWED_SCHEMES')
97
- tlds = config_for(tlds, 'URLS_ALLOWED_TLDS')
92
+ private = config_for(private, "URLS_ALLOW_PRIVATE")
93
+ local = config_for(local, "URLS_ALLOW_LOCAL")
94
+ credentials = config_for(credentials, "URLS_ALLOW_CREDENTIALS")
95
+ schemes = config_for(schemes, "URLS_ALLOWED_SCHEMES")
96
+ tlds = config_for(tlds, "URLS_ALLOWED_TLDS")
98
97
 
99
98
  match = URL_REGEX.match(url)
100
99
  if not match:
101
100
  error(url)
102
101
 
103
- scheme = (match.group('scheme') or '').lower()
102
+ scheme = (match.group("scheme") or "").lower()
104
103
  if scheme and scheme not in schemes:
105
- error(url, _('Invalid scheme {0}, allowed schemes: {1}').format(scheme, ", ".join(schemes)))
104
+ error(url, _("Invalid scheme {0}, allowed schemes: {1}").format(scheme, ", ".join(schemes)))
106
105
 
107
- if not credentials and match.group('credentials'):
108
- error(url, _('Credentials in URL are not allowed'))
106
+ if not credentials and match.group("credentials"):
107
+ error(url, _("Credentials in URL are not allowed"))
109
108
 
110
- tld = match.group('tld')
109
+ tld = match.group("tld")
111
110
  if tld and tld not in tlds and idna(tld) not in tlds:
112
- error(url, _('Invalid TLD {0}').format(tld))
111
+ error(url, _("Invalid TLD {0}").format(tld))
113
112
 
114
- ip = match.group('ipv6') or match.group('ipv4')
113
+ ip = match.group("ipv6") or match.group("ipv4")
115
114
  if ip:
116
115
  try:
117
116
  ip = IPAddress(ip)
118
117
  except AddrFormatError:
119
118
  error(url)
120
119
  if ip.is_multicast():
121
- error(url, _('{0} is a multicast IP').format(ip))
120
+ error(url, _("{0} is a multicast IP").format(ip))
122
121
  elif not ip.is_loopback() and ip.is_hostmask() or ip.is_netmask():
123
- error(url, _('{0} is a mask IP').format(ip))
122
+ error(url, _("{0} is a mask IP").format(ip))
124
123
 
125
124
  if not local:
126
- if ip and ip.is_loopback() or match.group('localhost'):
127
- error(url, _('is a local URL'))
125
+ if ip and ip.is_loopback() or match.group("localhost"):
126
+ error(url, _("is a local URL"))
128
127
 
129
128
  if not private and ip and ip.is_private():
130
- error(url, _('is a private URL'))
129
+ error(url, _("is a private URL"))
131
130
 
132
131
  return url