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
@@ -1,10 +1,9 @@
1
1
  from flask import url_for
2
2
 
3
3
  from udata.api import api
4
- from udata.models import db, Follow
5
-
6
4
  from udata.core.followers.api import FollowAPI
7
5
  from udata.core.followers.signals import on_follow, on_unfollow
6
+ from udata.models import Follow, db
8
7
 
9
8
  from . import APITestCase
10
9
 
@@ -16,7 +15,7 @@ class FakeModel(db.Document):
16
15
  pass
17
16
 
18
17
 
19
- @api.route('/fake/<id>/follow/', endpoint='follow_fake')
18
+ @api.route("/fake/<id>/follow/", endpoint="follow_fake")
20
19
  class FollowFakeAPI(FollowAPI):
21
20
  model = FakeModel
22
21
 
@@ -30,34 +29,33 @@ class FollowAPITest(APITestCase):
30
29
  self.signal_emitted = True
31
30
 
32
31
  def test_follow(self):
33
- '''It should follow on POST'''
32
+ """It should follow on POST"""
34
33
  user = self.login()
35
34
  to_follow = FakeModel.objects.create()
36
35
 
37
36
  with on_follow.connected_to(self.handler):
38
- response = self.post(url_for('api.follow_fake', id=to_follow.id))
37
+ response = self.post(url_for("api.follow_fake", id=to_follow.id))
39
38
 
40
39
  self.assert201(response)
41
40
 
42
41
  nb_followers = Follow.objects.followers(to_follow).count()
43
42
 
44
- self.assertEqual(response.json['followers'], nb_followers)
43
+ self.assertEqual(response.json["followers"], nb_followers)
45
44
  self.assertEqual(Follow.objects.following(to_follow).count(), 0)
46
45
  self.assertEqual(nb_followers, 1)
47
- self.assertIsInstance(Follow.objects.followers(to_follow).first(),
48
- Follow)
46
+ self.assertIsInstance(Follow.objects.followers(to_follow).first(), Follow)
49
47
  self.assertEqual(Follow.objects.following(user).count(), 1)
50
48
  self.assertEqual(Follow.objects.followers(user).count(), 0)
51
49
  self.assertTrue(self.signal_emitted)
52
50
 
53
51
  def test_follow_already_followed(self):
54
- '''It should do nothing when following an already followed object'''
52
+ """It should do nothing when following an already followed object"""
55
53
  user = self.login()
56
54
  to_follow = FakeModel.objects.create()
57
55
  Follow.objects.create(follower=user, following=to_follow)
58
56
 
59
57
  with on_follow.connected_to(self.handler):
60
- response = self.post(url_for('api.follow_fake', id=to_follow.id))
58
+ response = self.post(url_for("api.follow_fake", id=to_follow.id))
61
59
 
62
60
  self.assertStatus(response, 200)
63
61
 
@@ -68,19 +66,19 @@ class FollowAPITest(APITestCase):
68
66
  self.assertFalse(self.signal_emitted)
69
67
 
70
68
  def test_unfollow(self):
71
- '''It should unfollow on DELETE'''
69
+ """It should unfollow on DELETE"""
72
70
  user = self.login()
73
71
  to_follow = FakeModel.objects.create()
74
72
  Follow.objects.create(follower=user, following=to_follow)
75
73
 
76
74
  with on_unfollow.connected_to(self.handler):
77
- response = self.delete(url_for('api.follow_fake', id=to_follow.id))
75
+ response = self.delete(url_for("api.follow_fake", id=to_follow.id))
78
76
 
79
77
  self.assert200(response)
80
78
 
81
79
  nb_followers = Follow.objects.followers(to_follow).count()
82
80
 
83
- self.assertEqual(response.json['followers'], nb_followers)
81
+ self.assertEqual(response.json["followers"], nb_followers)
84
82
 
85
83
  self.assertEqual(Follow.objects.following(to_follow).count(), 0)
86
84
  self.assertEqual(nb_followers, 0)
@@ -89,9 +87,9 @@ class FollowAPITest(APITestCase):
89
87
  self.assertTrue(self.signal_emitted)
90
88
 
91
89
  def test_unfollow_not_existing(self):
92
- '''It should raise 404 when trying to unfollow a not followed object'''
90
+ """It should raise 404 when trying to unfollow a not followed object"""
93
91
  self.login()
94
92
  to_follow = FakeModel.objects.create()
95
93
 
96
- response = self.delete(url_for('api.follow_fake', id=to_follow.id))
94
+ response = self.delete(url_for("api.follow_fake", id=to_follow.id))
97
95
  self.assert404(response)
@@ -2,18 +2,15 @@ from datetime import datetime
2
2
 
3
3
  from flask import url_for
4
4
 
5
- from udata.models import Discussion, Follow, Member, User
6
- from udata.core.discussions.models import Message as DiscMsg
7
- from udata.core.dataset.factories import (
8
- CommunityResourceFactory,
9
- DatasetFactory
10
- )
11
5
  from udata.core.dataset.activities import UserCreatedDataset
6
+ from udata.core.dataset.factories import CommunityResourceFactory, DatasetFactory
12
7
  from udata.core.discussions.factories import DiscussionFactory
13
- from udata.core.reuse.factories import ReuseFactory
8
+ from udata.core.discussions.models import Message as DiscMsg
14
9
  from udata.core.organization.factories import OrganizationFactory
10
+ from udata.core.reuse.factories import ReuseFactory
15
11
  from udata.core.user.factories import UserFactory
16
12
  from udata.i18n import _
13
+ from udata.models import Discussion, Follow, Member, User
17
14
  from udata.tests.helpers import capture_mails
18
15
  from udata.utils import faker
19
16
 
@@ -24,173 +21,163 @@ class MeAPITest(APITestCase):
24
21
  modules = []
25
22
 
26
23
  def test_get_profile(self):
27
- '''It should fetch my user data on GET'''
24
+ """It should fetch my user data on GET"""
28
25
  self.login()
29
- response = self.get(url_for('api.me'))
26
+ response = self.get(url_for("api.me"))
30
27
  self.assert200(response)
31
- self.assertEqual(response.json['email'], self.user.email)
32
- self.assertEqual(response.json['first_name'], self.user.first_name)
33
- self.assertEqual(response.json['roles'], [])
28
+ self.assertEqual(response.json["email"], self.user.email)
29
+ self.assertEqual(response.json["first_name"], self.user.first_name)
30
+ self.assertEqual(response.json["roles"], [])
34
31
 
35
32
  def test_get_profile_with_deleted_org(self):
36
- '''It should not display my membership to deleted organizations'''
33
+ """It should not display my membership to deleted organizations"""
37
34
  user = self.login()
38
- member = Member(user=user, role='editor')
35
+ member = Member(user=user, role="editor")
39
36
  org = OrganizationFactory(members=[member])
40
- deleted_org = OrganizationFactory(members=[member],
41
- deleted=datetime.utcnow())
42
- response = self.get(url_for('api.me'))
37
+ deleted_org = OrganizationFactory(members=[member], deleted=datetime.utcnow())
38
+ response = self.get(url_for("api.me"))
43
39
  self.assert200(response)
44
- orgs = [o['id'] for o in response.json['organizations']]
40
+ orgs = [o["id"] for o in response.json["organizations"]]
45
41
  self.assertIn(str(org.id), orgs)
46
42
  self.assertNotIn(str(deleted_org.id), orgs)
47
43
 
48
44
  def test_get_profile_401(self):
49
- '''It should raise a 401 on GET /me if no user is authenticated'''
50
- response = self.get(url_for('api.me'))
45
+ """It should raise a 401 on GET /me if no user is authenticated"""
46
+ response = self.get(url_for("api.me"))
51
47
  self.assert401(response)
52
48
 
53
49
  def test_update_profile(self):
54
- '''It should update my profile from the API'''
50
+ """It should update my profile from the API"""
55
51
  self.login()
56
52
  data = self.user.to_dict()
57
53
  self.assertTrue(self.user.active)
58
- data['about'] = 'new about'
59
- data['active'] = False
60
- response = self.put(url_for('api.me'), data)
54
+ data["about"] = "new about"
55
+ data["active"] = False
56
+ response = self.put(url_for("api.me"), data)
61
57
  self.assert200(response)
62
58
  self.assertEqual(User.objects.count(), 1)
63
59
  self.user.reload()
64
- self.assertEqual(self.user.about, 'new about')
60
+ self.assertEqual(self.user.about, "new about")
65
61
  self.assertTrue(self.user.active)
66
62
 
67
63
  def test_my_metrics(self):
68
64
  self.login()
69
- response = self.get(url_for('api.my_metrics'))
65
+ response = self.get(url_for("api.my_metrics"))
70
66
  self.assert200(response)
71
- self.assertEqual(response.json['resources_availability'], 100.)
72
- self.assertEqual(response.json['datasets_org_count'], 0)
73
- self.assertEqual(response.json['followers_org_count'], 0)
74
- self.assertEqual(response.json['datasets_count'], 0)
75
- self.assertEqual(response.json['followers_count'], 0)
67
+ self.assertEqual(response.json["resources_availability"], 100.0)
68
+ self.assertEqual(response.json["datasets_org_count"], 0)
69
+ self.assertEqual(response.json["followers_org_count"], 0)
70
+ self.assertEqual(response.json["datasets_count"], 0)
71
+ self.assertEqual(response.json["followers_count"], 0)
76
72
 
77
73
  def test_my_reuses(self):
78
74
  user = self.login()
79
75
  reuses = [ReuseFactory(owner=user) for _ in range(2)]
80
76
 
81
- response = self.get(url_for('api.my_reuses'))
77
+ response = self.get(url_for("api.my_reuses"))
82
78
  self.assert200(response)
83
79
 
84
80
  self.assertEqual(len(response.json), len(reuses))
85
81
 
86
82
  def test_my_org_datasets(self):
87
83
  user = self.login()
88
- member = Member(user=user, role='editor')
84
+ member = Member(user=user, role="editor")
89
85
  organization = OrganizationFactory(members=[member])
90
- community_resources = [
91
- DatasetFactory(owner=user) for _ in range(2)]
92
- org_datasets = [
93
- DatasetFactory(organization=organization)
94
- for _ in range(2)]
86
+ community_resources = [DatasetFactory(owner=user) for _ in range(2)]
87
+ org_datasets = [DatasetFactory(organization=organization) for _ in range(2)]
95
88
 
96
- response = self.get(url_for('api.my_org_datasets'))
89
+ response = self.get(url_for("api.my_org_datasets"))
97
90
  self.assert200(response)
98
- self.assertEqual(
99
- len(response.json),
100
- len(community_resources) + len(org_datasets))
91
+ self.assertEqual(len(response.json), len(community_resources) + len(org_datasets))
101
92
 
102
93
  def test_my_org_datasets_with_search(self):
103
94
  user = self.login()
104
- member = Member(user=user, role='editor')
95
+ member = Member(user=user, role="editor")
105
96
  organization = OrganizationFactory(members=[member])
106
97
  datasets = [
107
- DatasetFactory(owner=user, title='foô'),
98
+ DatasetFactory(owner=user, title="foô"),
108
99
  ]
109
100
  org_datasets = [
110
- DatasetFactory(organization=organization, title='foô'),
101
+ DatasetFactory(organization=organization, title="foô"),
111
102
  ]
112
103
 
113
104
  # Should not be listed.
114
105
  DatasetFactory(owner=user)
115
106
  DatasetFactory(organization=organization)
116
107
 
117
- response = self.get(url_for('api.my_org_datasets'),
118
- qs={'q': 'foô'})
108
+ response = self.get(url_for("api.my_org_datasets"), qs={"q": "foô"})
119
109
  self.assert200(response)
120
110
  self.assertEqual(len(response.json), len(datasets) + len(org_datasets))
121
111
 
122
112
  def test_my_org_community_resources(self):
123
113
  user = self.login()
124
- member = Member(user=user, role='editor')
114
+ member = Member(user=user, role="editor")
125
115
  organization = OrganizationFactory(members=[member])
126
- community_resources = [
127
- CommunityResourceFactory(owner=user) for _ in range(2)]
116
+ community_resources = [CommunityResourceFactory(owner=user) for _ in range(2)]
128
117
  org_community_resources = [
129
- CommunityResourceFactory(organization=organization)
130
- for _ in range(2)]
118
+ CommunityResourceFactory(organization=organization) for _ in range(2)
119
+ ]
131
120
 
132
- response = self.get(url_for('api.my_org_community_resources'))
121
+ response = self.get(url_for("api.my_org_community_resources"))
133
122
  self.assert200(response)
134
123
  self.assertEqual(
135
- len(response.json),
136
- len(community_resources) + len(org_community_resources))
124
+ len(response.json), len(community_resources) + len(org_community_resources)
125
+ )
137
126
 
138
127
  def test_my_org_community_resources_with_search(self):
139
128
  user = self.login()
140
- member = Member(user=user, role='editor')
129
+ member = Member(user=user, role="editor")
141
130
  organization = OrganizationFactory(members=[member])
142
131
  community_resources = [
143
- CommunityResourceFactory(owner=user, title='foô'),
132
+ CommunityResourceFactory(owner=user, title="foô"),
144
133
  ]
145
134
  org_community_resources = [
146
- CommunityResourceFactory(organization=organization, title='foô'),
135
+ CommunityResourceFactory(organization=organization, title="foô"),
147
136
  ]
148
137
 
149
138
  # Should not be listed.
150
139
  CommunityResourceFactory(owner=user)
151
140
  CommunityResourceFactory(organization=organization)
152
141
 
153
- response = self.get(url_for('api.my_org_community_resources'),
154
- qs={'q': 'foô'})
142
+ response = self.get(url_for("api.my_org_community_resources"), qs={"q": "foô"})
155
143
  self.assert200(response)
156
144
  self.assertEqual(
157
- len(response.json),
158
- len(community_resources) + len(org_community_resources))
145
+ len(response.json), len(community_resources) + len(org_community_resources)
146
+ )
159
147
 
160
148
  def test_my_org_reuses(self):
161
149
  user = self.login()
162
- member = Member(user=user, role='editor')
150
+ member = Member(user=user, role="editor")
163
151
  organization = OrganizationFactory(members=[member])
164
152
  reuses = [ReuseFactory(owner=user) for _ in range(2)]
165
- org_reuses = [ReuseFactory(organization=organization)
166
- for _ in range(2)]
153
+ org_reuses = [ReuseFactory(organization=organization) for _ in range(2)]
167
154
 
168
- response = self.get(url_for('api.my_org_reuses'))
155
+ response = self.get(url_for("api.my_org_reuses"))
169
156
  self.assert200(response)
170
157
  self.assertEqual(len(response.json), len(reuses) + len(org_reuses))
171
158
 
172
159
  def test_my_org_reuses_with_search(self):
173
160
  user = self.login()
174
- member = Member(user=user, role='editor')
161
+ member = Member(user=user, role="editor")
175
162
  organization = OrganizationFactory(members=[member])
176
163
  reuses = [
177
- ReuseFactory(owner=user, title='foô'),
164
+ ReuseFactory(owner=user, title="foô"),
178
165
  ]
179
166
  org_reuses = [
180
- ReuseFactory(organization=organization, title='foô'),
167
+ ReuseFactory(organization=organization, title="foô"),
181
168
  ]
182
169
 
183
170
  # Should not be listed.
184
171
  ReuseFactory(owner=user)
185
172
  ReuseFactory(organization=organization)
186
173
 
187
- response = self.get(url_for('api.my_org_reuses'), qs={'q': 'foô'})
174
+ response = self.get(url_for("api.my_org_reuses"), qs={"q": "foô"})
188
175
  self.assert200(response)
189
176
  self.assertEqual(len(response.json), len(reuses) + len(org_reuses))
190
177
 
191
178
  def test_my_org_discussions(self):
192
179
  user = self.login()
193
- member = Member(user=user, role='editor')
180
+ member = Member(user=user, role="editor")
194
181
  organization = OrganizationFactory(members=[member])
195
182
  reuse = ReuseFactory(owner=user)
196
183
  org_reuse = ReuseFactory(organization=organization)
@@ -198,23 +185,23 @@ class MeAPITest(APITestCase):
198
185
  org_dataset = DatasetFactory(organization=organization)
199
186
 
200
187
  discussions = [
201
- Discussion.objects.create(subject=dataset, title='', user=user),
202
- Discussion.objects.create(subject=org_dataset, title='', user=user),
203
- Discussion.objects.create(subject=reuse, title='', user=user),
204
- Discussion.objects.create(subject=org_reuse, title='', user=user),
188
+ Discussion.objects.create(subject=dataset, title="", user=user),
189
+ Discussion.objects.create(subject=org_dataset, title="", user=user),
190
+ Discussion.objects.create(subject=reuse, title="", user=user),
191
+ Discussion.objects.create(subject=org_reuse, title="", user=user),
205
192
  ]
206
193
 
207
194
  # Should not be listed
208
- Discussion.objects.create(subject=DatasetFactory(), title='', user=user)
209
- Discussion.objects.create(subject=ReuseFactory(), title='', user=user)
195
+ Discussion.objects.create(subject=DatasetFactory(), title="", user=user)
196
+ Discussion.objects.create(subject=ReuseFactory(), title="", user=user)
210
197
 
211
- response = self.get(url_for('api.my_org_discussions'))
198
+ response = self.get(url_for("api.my_org_discussions"))
212
199
  self.assert200(response)
213
200
  self.assertEqual(len(response.json), len(discussions))
214
201
 
215
202
  def test_my_org_discussions_with_search(self):
216
203
  user = self.login()
217
- member = Member(user=user, role='editor')
204
+ member = Member(user=user, role="editor")
218
205
  organization = OrganizationFactory(members=[member])
219
206
  reuse = ReuseFactory(owner=user)
220
207
  org_reuse = ReuseFactory(organization=organization)
@@ -222,68 +209,68 @@ class MeAPITest(APITestCase):
222
209
  org_dataset = DatasetFactory(organization=organization)
223
210
 
224
211
  discussions = [
225
- Discussion.objects.create(subject=dataset, title='foô', user=user),
226
- Discussion.objects.create(subject=org_reuse, title='foô', user=user),
212
+ Discussion.objects.create(subject=dataset, title="foô", user=user),
213
+ Discussion.objects.create(subject=org_reuse, title="foô", user=user),
227
214
  ]
228
215
 
229
216
  # Should not be listed.
230
- Discussion.objects.create(subject=reuse, title='', user=user),
231
- Discussion.objects.create(subject=org_dataset, title='', user=user),
217
+ (Discussion.objects.create(subject=reuse, title="", user=user),)
218
+ (Discussion.objects.create(subject=org_dataset, title="", user=user),)
232
219
 
233
220
  # Should really not be listed.
234
- Discussion.objects.create(subject=DatasetFactory(), title='foô', user=user)
235
- Discussion.objects.create(subject=ReuseFactory(), title='foô', user=user)
221
+ Discussion.objects.create(subject=DatasetFactory(), title="foô", user=user)
222
+ Discussion.objects.create(subject=ReuseFactory(), title="foô", user=user)
236
223
 
237
- response = self.get(url_for('api.my_org_discussions'), qs={'q': 'foô'})
224
+ response = self.get(url_for("api.my_org_discussions"), qs={"q": "foô"})
238
225
  self.assert200(response)
239
226
  self.assertEqual(len(response.json), len(discussions))
240
227
 
241
228
  def test_my_reuses_401(self):
242
- response = self.get(url_for('api.my_reuses'))
229
+ response = self.get(url_for("api.my_reuses"))
243
230
  self.assert401(response)
244
231
 
245
232
  def test_generate_apikey(self):
246
- '''It should generate an API Key on POST'''
233
+ """It should generate an API Key on POST"""
247
234
  self.login()
248
- response = self.post(url_for('api.my_apikey'))
235
+ response = self.post(url_for("api.my_apikey"))
249
236
  self.assert201(response)
250
- self.assertIsNotNone(response.json['apikey'])
237
+ self.assertIsNotNone(response.json["apikey"])
251
238
 
252
239
  self.user.reload()
253
240
  self.assertFalse(self.user.apikey.startswith("b'"))
254
241
  self.assertIsNotNone(self.user.apikey)
255
- self.assertEqual(self.user.apikey, response.json['apikey'])
242
+ self.assertEqual(self.user.apikey, response.json["apikey"])
256
243
 
257
244
  def test_regenerate_apikey(self):
258
- '''It should regenerate an API Key on POST'''
245
+ """It should regenerate an API Key on POST"""
259
246
  self.login()
260
247
  self.user.generate_api_key()
261
248
  self.user.save()
262
249
 
263
250
  apikey = self.user.apikey
264
- response = self.post(url_for('api.my_apikey'))
251
+ response = self.post(url_for("api.my_apikey"))
265
252
  self.assert201(response)
266
- self.assertIsNotNone(response.json['apikey'])
253
+ self.assertIsNotNone(response.json["apikey"])
267
254
 
268
255
  self.user.reload()
269
256
  self.assertIsNotNone(self.user.apikey)
270
257
  self.assertNotEqual(self.user.apikey, apikey)
271
- self.assertEqual(self.user.apikey, response.json['apikey'])
258
+ self.assertEqual(self.user.apikey, response.json["apikey"])
272
259
 
273
260
  def test_clear_apikey(self):
274
- '''It should clear an API Key on DELETE'''
261
+ """It should clear an API Key on DELETE"""
275
262
  self.login()
276
263
  self.user.generate_api_key()
277
264
  self.user.save()
278
265
 
279
- response = self.delete(url_for('api.my_apikey'))
266
+ response = self.delete(url_for("api.my_apikey"))
280
267
  self.assert204(response)
281
268
 
282
269
  self.user.reload()
283
270
  self.assertIsNone(self.user.apikey)
284
271
 
285
272
  def test_delete(self):
286
- '''It should delete the connected user'''
273
+ """It should delete the connected user"""
287
274
  user = self.login()
288
275
  user_email = user.email
289
276
  self.assertIsNone(user.deleted)
@@ -291,13 +278,10 @@ class MeAPITest(APITestCase):
291
278
  members = [Member(user=user), Member(user=other_user)]
292
279
  organization = OrganizationFactory(members=members)
293
280
  disc_msg_content = faker.sentence()
294
- disc_msg = DiscMsg(content=disc_msg_content,
295
- posted_by=user)
281
+ disc_msg = DiscMsg(content=disc_msg_content, posted_by=user)
296
282
  other_disc_msg_content = faker.sentence()
297
- other_disc_msg = DiscMsg(content=other_disc_msg_content,
298
- posted_by=other_user)
299
- discussion = DiscussionFactory(user=user,
300
- discussion=[disc_msg, other_disc_msg])
283
+ other_disc_msg = DiscMsg(content=other_disc_msg_content, posted_by=other_user)
284
+ discussion = DiscussionFactory(user=user, discussion=[disc_msg, other_disc_msg])
301
285
  dataset = DatasetFactory(owner=user)
302
286
  reuse = ReuseFactory(owner=user)
303
287
  resource = CommunityResourceFactory(owner=user)
@@ -307,10 +291,10 @@ class MeAPITest(APITestCase):
307
291
  followed = Follow.objects().create(follower=other_user, following=user)
308
292
 
309
293
  with capture_mails() as mails:
310
- response = self.delete(url_for('api.me'))
294
+ response = self.delete(url_for("api.me"))
311
295
  self.assertEqual(len(mails), 1)
312
296
  self.assertEqual(mails[0].send_to, set([user_email]))
313
- self.assertEqual(mails[0].subject, _('Account deletion'))
297
+ self.assertEqual(mails[0].subject, _("Account deletion"))
314
298
  self.assert204(response)
315
299
 
316
300
  user.reload()
@@ -329,11 +313,11 @@ class MeAPITest(APITestCase):
329
313
  followed.reload()
330
314
 
331
315
  # The personal data of the user are anonymized
332
- self.assertEqual(user.email, '{}@deleted'.format(user.id))
316
+ self.assertEqual(user.email, "{}@deleted".format(user.id))
333
317
  self.assertEqual(user.password, None)
334
318
  self.assertEqual(user.active, False)
335
- self.assertEqual(user.first_name, 'DELETED')
336
- self.assertEqual(user.last_name, 'DELETED')
319
+ self.assertEqual(user.first_name, "DELETED")
320
+ self.assertEqual(user.last_name, "DELETED")
337
321
  self.assertFalse(bool(user.avatar))
338
322
  self.assertEqual(user.avatar_url, None)
339
323
  self.assertEqual(user.website, None)
@@ -348,9 +332,8 @@ class MeAPITest(APITestCase):
348
332
 
349
333
  # The discussions are kept but the messages are anonymized
350
334
  self.assertEqual(len(discussion.discussion), 2)
351
- self.assertEqual(discussion.discussion[0].content, 'DELETED')
352
- self.assertEqual(discussion.discussion[1].content,
353
- other_disc_msg_content)
335
+ self.assertEqual(discussion.discussion[0].content, "DELETED")
336
+ self.assertEqual(discussion.discussion[1].content, other_disc_msg_content)
354
337
 
355
338
  # The datasets are unchanged
356
339
  self.assertEqual(dataset.owner, user)