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,349 +1,343 @@
1
1
  import logging
2
- import pytest
3
-
4
2
  from datetime import datetime
5
3
 
4
+ import pytest
6
5
  from flask import url_for
7
6
  from pytest_mock import MockerFixture
8
7
 
9
- from udata.tests.plugin import ApiClient
10
-
11
- from .. import actions
12
-
13
- from udata.models import Member, PeriodicTask
14
8
  from udata.core.organization.factories import OrganizationFactory
15
9
  from udata.core.user.factories import AdminFactory, UserFactory
10
+ from udata.models import Member, PeriodicTask
11
+ from udata.tests.helpers import assert200, assert201, assert204, assert400, assert403
12
+ from udata.tests.plugin import ApiClient
16
13
  from udata.utils import faker
17
- from udata.tests.helpers import (
18
- assert200, assert201, assert204, assert400, assert403
19
- )
20
14
 
15
+ from .. import actions
21
16
  from ..models import (
22
- HarvestSource, VALIDATION_ACCEPTED, VALIDATION_REFUSED, VALIDATION_PENDING, HarvestSourceValidation,
23
-
17
+ VALIDATION_ACCEPTED,
18
+ VALIDATION_PENDING,
19
+ VALIDATION_REFUSED,
20
+ HarvestSource,
21
+ HarvestSourceValidation,
24
22
  )
25
23
  from .factories import HarvestSourceFactory, MockBackendsMixin
26
24
 
27
-
28
25
  log = logging.getLogger(__name__)
29
26
 
30
27
 
31
-
32
- @pytest.mark.usefixtures('clean_db')
28
+ @pytest.mark.usefixtures("clean_db")
33
29
  class HarvestAPITest(MockBackendsMixin):
34
30
  modules = []
35
31
 
36
32
  def test_list_backends(self, api):
37
- '''It should fetch the harvest backends list from the API'''
38
- response = api.get(url_for('api.harvest_backends'))
33
+ """It should fetch the harvest backends list from the API"""
34
+ response = api.get(url_for("api.harvest_backends"))
39
35
  assert200(response)
40
36
  assert len(response.json) == len(actions.list_backends())
41
37
  for data in response.json:
42
- assert 'id' in data
43
- assert 'label' in data
44
- assert 'filters' in data
45
- assert isinstance(data['filters'], (list, tuple))
38
+ assert "id" in data
39
+ assert "label" in data
40
+ assert "filters" in data
41
+ assert isinstance(data["filters"], (list, tuple))
46
42
 
47
43
  def test_list_sources(self, api):
48
44
  sources = HarvestSourceFactory.create_batch(3)
49
45
 
50
- response = api.get(url_for('api.harvest_sources'))
46
+ response = api.get(url_for("api.harvest_sources"))
51
47
  assert200(response)
52
- assert len(response.json['data']) == len(sources)
48
+ assert len(response.json["data"]) == len(sources)
53
49
 
54
50
  def test_list_sources_exclude_deleted(self, api):
55
51
  sources = HarvestSourceFactory.create_batch(3)
56
52
  HarvestSourceFactory.create_batch(2, deleted=datetime.utcnow())
57
53
 
58
- response = api.get(url_for('api.harvest_sources'))
54
+ response = api.get(url_for("api.harvest_sources"))
59
55
  assert200(response)
60
- assert len(response.json['data']) == len(sources)
56
+ assert len(response.json["data"]) == len(sources)
61
57
 
62
58
  def test_list_sources_include_deleted(self, api):
63
59
  sources = HarvestSourceFactory.create_batch(3)
64
60
  sources.extend(HarvestSourceFactory.create_batch(2, deleted=datetime.utcnow()))
65
61
 
66
- response = api.get(url_for('api.harvest_sources', deleted=True))
62
+ response = api.get(url_for("api.harvest_sources", deleted=True))
67
63
  assert200(response)
68
- assert len(response.json['data']) == len(sources)
64
+ assert len(response.json["data"]) == len(sources)
69
65
 
70
66
  def test_list_sources_for_owner(self, api):
71
67
  owner = UserFactory()
72
68
  sources = HarvestSourceFactory.create_batch(3, owner=owner)
73
69
  HarvestSourceFactory()
74
70
 
75
- url = url_for('api.harvest_sources', owner=str(owner.id))
71
+ url = url_for("api.harvest_sources", owner=str(owner.id))
76
72
  response = api.get(url)
77
73
  assert200(response)
78
74
 
79
- assert len(response.json['data']) == len(sources)
75
+ assert len(response.json["data"]) == len(sources)
80
76
 
81
77
  def test_list_sources_for_org(self, api):
82
78
  org = OrganizationFactory()
83
79
  sources = HarvestSourceFactory.create_batch(3, organization=org)
84
80
  HarvestSourceFactory()
85
81
 
86
- response = api.get(url_for('api.harvest_sources', owner=str(org.id)))
82
+ response = api.get(url_for("api.harvest_sources", owner=str(org.id)))
87
83
  assert200(response)
88
84
 
89
- assert len(response.json['data']) == len(sources)
85
+ assert len(response.json["data"]) == len(sources)
90
86
 
91
87
  def test_create_source_with_owner(self, api):
92
- '''It should create and attach a new source to an owner'''
88
+ """It should create and attach a new source to an owner"""
93
89
  user = api.login()
94
- data = {
95
- 'name': faker.word(),
96
- 'url': faker.url(),
97
- 'backend': 'factory'
98
- }
99
- response = api.post(url_for('api.harvest_sources'), data)
90
+ data = {"name": faker.word(), "url": faker.url(), "backend": "factory"}
91
+ response = api.post(url_for("api.harvest_sources"), data)
100
92
 
101
93
  assert201(response)
102
94
 
103
95
  source = response.json
104
- assert source['validation']['state'] == VALIDATION_PENDING
105
- assert source['owner']['id'] == str(user.id)
106
- assert source['organization'] is None
96
+ assert source["validation"]["state"] == VALIDATION_PENDING
97
+ assert source["owner"]["id"] == str(user.id)
98
+ assert source["organization"] is None
107
99
 
108
100
  def test_create_source_with_org(self, api):
109
- '''It should create and attach a new source to an organization'''
101
+ """It should create and attach a new source to an organization"""
110
102
  user = api.login()
111
- member = Member(user=user, role='admin')
103
+ member = Member(user=user, role="admin")
112
104
  org = OrganizationFactory(members=[member])
113
105
  data = {
114
- 'name': faker.word(),
115
- 'url': faker.url(),
116
- 'backend': 'factory',
117
- 'organization': str(org.id)
106
+ "name": faker.word(),
107
+ "url": faker.url(),
108
+ "backend": "factory",
109
+ "organization": str(org.id),
118
110
  }
119
- response = api.post(url_for('api.harvest_sources'), data)
111
+ response = api.post(url_for("api.harvest_sources"), data)
120
112
 
121
113
  assert201(response)
122
114
 
123
115
  source = response.json
124
- assert source['validation']['state'] == VALIDATION_PENDING
125
- assert source['owner'] is None
126
- assert source['organization']['id'] == str(org.id)
116
+ assert source["validation"]["state"] == VALIDATION_PENDING
117
+ assert source["owner"] is None
118
+ assert source["organization"]["id"] == str(org.id)
127
119
 
128
120
  def test_create_source_with_org_not_member(self, api):
129
- '''It should create and attach a new source to an organization'''
121
+ """It should create and attach a new source to an organization"""
130
122
  user = api.login()
131
- member = Member(user=user, role='editor')
123
+ member = Member(user=user, role="editor")
132
124
  org = OrganizationFactory(members=[member])
133
125
  data = {
134
- 'name': faker.word(),
135
- 'url': faker.url(),
136
- 'backend': 'factory',
137
- 'organization': str(org.id)
126
+ "name": faker.word(),
127
+ "url": faker.url(),
128
+ "backend": "factory",
129
+ "organization": str(org.id),
138
130
  }
139
- response = api.post(url_for('api.harvest_sources'), data)
131
+ response = api.post(url_for("api.harvest_sources"), data)
140
132
 
141
133
  assert403(response)
142
134
 
143
135
  def test_create_source_with_config(self, api):
144
- '''It should create a new source with configuration'''
136
+ """It should create a new source with configuration"""
145
137
  api.login()
146
138
  data = {
147
- 'name': faker.word(),
148
- 'url': faker.url(),
149
- 'backend': 'factory',
150
- 'config': {
151
- 'filters': [
152
- {'key': 'test', 'value': 1},
153
- {'key': 'test', 'value': 42},
154
- {'key': 'tag', 'value': 'my-tag'},
139
+ "name": faker.word(),
140
+ "url": faker.url(),
141
+ "backend": "factory",
142
+ "config": {
143
+ "filters": [
144
+ {"key": "test", "value": 1},
145
+ {"key": "test", "value": 42},
146
+ {"key": "tag", "value": "my-tag"},
155
147
  ],
156
- 'features': {
157
- 'test': True,
158
- 'toggled': True,
159
- }
160
- }
148
+ "features": {
149
+ "test": True,
150
+ "toggled": True,
151
+ },
152
+ },
161
153
  }
162
- response = api.post(url_for('api.harvest_sources'), data)
154
+ response = api.post(url_for("api.harvest_sources"), data)
163
155
 
164
156
  assert201(response)
165
157
 
166
158
  source = response.json
167
- assert source['config'] == {
168
- 'filters': [
169
- {'key': 'test', 'value': 1},
170
- {'key': 'test', 'value': 42},
171
- {'key': 'tag', 'value': 'my-tag'},
159
+ assert source["config"] == {
160
+ "filters": [
161
+ {"key": "test", "value": 1},
162
+ {"key": "test", "value": 42},
163
+ {"key": "tag", "value": "my-tag"},
172
164
  ],
173
- 'features': {
174
- 'test': True,
175
- 'toggled': True,
176
- }
165
+ "features": {
166
+ "test": True,
167
+ "toggled": True,
168
+ },
177
169
  }
178
170
 
179
171
  def test_create_source_with_unknown_filter(self, api):
180
- '''Can only use known filters in config'''
172
+ """Can only use known filters in config"""
181
173
  api.login()
182
174
  data = {
183
- 'name': faker.word(),
184
- 'url': faker.url(),
185
- 'backend': 'factory',
186
- 'config': {
187
- 'filters': [
188
- {'key': 'unknown', 'value': 'any'},
175
+ "name": faker.word(),
176
+ "url": faker.url(),
177
+ "backend": "factory",
178
+ "config": {
179
+ "filters": [
180
+ {"key": "unknown", "value": "any"},
189
181
  ]
190
- }
182
+ },
191
183
  }
192
- response = api.post(url_for('api.harvest_sources'), data)
184
+ response = api.post(url_for("api.harvest_sources"), data)
193
185
 
194
186
  assert400(response)
195
187
 
196
188
  def test_create_source_with_bad_filter_type(self, api):
197
- '''Can only use the xpected filter type'''
189
+ """Can only use the xpected filter type"""
198
190
  api.login()
199
191
  data = {
200
- 'name': faker.word(),
201
- 'url': faker.url(),
202
- 'backend': 'factory',
203
- 'config': {
204
- 'filters': [
205
- {'key': 'test', 'value': 'not-an-integer'},
192
+ "name": faker.word(),
193
+ "url": faker.url(),
194
+ "backend": "factory",
195
+ "config": {
196
+ "filters": [
197
+ {"key": "test", "value": "not-an-integer"},
206
198
  ]
207
- }
199
+ },
208
200
  }
209
- response = api.post(url_for('api.harvest_sources'), data)
201
+ response = api.post(url_for("api.harvest_sources"), data)
210
202
 
211
203
  assert400(response)
212
204
 
213
205
  def test_create_source_with_bad_filter_format(self, api):
214
- '''Filters should have the right format'''
206
+ """Filters should have the right format"""
215
207
  api.login()
216
208
  data = {
217
- 'name': faker.word(),
218
- 'url': faker.url(),
219
- 'backend': 'factory',
220
- 'config': {
221
- 'filters': [
222
- {'key': 'unknown', 'notvalue': 'any'},
209
+ "name": faker.word(),
210
+ "url": faker.url(),
211
+ "backend": "factory",
212
+ "config": {
213
+ "filters": [
214
+ {"key": "unknown", "notvalue": "any"},
223
215
  ]
224
- }
216
+ },
225
217
  }
226
- response = api.post(url_for('api.harvest_sources'), data)
218
+ response = api.post(url_for("api.harvest_sources"), data)
227
219
 
228
220
  assert400(response)
229
221
 
230
222
  def test_create_source_with_unknown_feature(self, api):
231
- '''Can only use known features in config'''
223
+ """Can only use known features in config"""
232
224
  api.login()
233
225
  data = {
234
- 'name': faker.word(),
235
- 'url': faker.url(),
236
- 'backend': 'factory',
237
- 'config': {
238
- 'features': {'unknown': True},
239
- }
226
+ "name": faker.word(),
227
+ "url": faker.url(),
228
+ "backend": "factory",
229
+ "config": {
230
+ "features": {"unknown": True},
231
+ },
240
232
  }
241
- response = api.post(url_for('api.harvest_sources'), data)
233
+ response = api.post(url_for("api.harvest_sources"), data)
242
234
 
243
235
  assert400(response)
244
236
 
245
237
  def test_create_source_with_false_feature(self, api):
246
- '''It should handled negative values'''
238
+ """It should handled negative values"""
247
239
  api.login()
248
240
  data = {
249
- 'name': faker.word(),
250
- 'url': faker.url(),
251
- 'backend': 'factory',
252
- 'config': {
253
- 'features': {
254
- 'test': False,
255
- 'toggled': False,
241
+ "name": faker.word(),
242
+ "url": faker.url(),
243
+ "backend": "factory",
244
+ "config": {
245
+ "features": {
246
+ "test": False,
247
+ "toggled": False,
256
248
  }
257
- }
249
+ },
258
250
  }
259
- response = api.post(url_for('api.harvest_sources'), data)
251
+ response = api.post(url_for("api.harvest_sources"), data)
260
252
 
261
253
  assert201(response)
262
254
 
263
255
  source = response.json
264
- assert source['config'] == {'features': {
265
- 'test': False,
266
- 'toggled': False,
267
- }}
256
+ assert source["config"] == {
257
+ "features": {
258
+ "test": False,
259
+ "toggled": False,
260
+ }
261
+ }
268
262
 
269
263
  def test_create_source_with_not_boolean_feature(self, api):
270
- '''It should handled negative values'''
264
+ """It should handled negative values"""
271
265
  api.login()
272
266
  data = {
273
- 'name': faker.word(),
274
- 'url': faker.url(),
275
- 'backend': 'factory',
276
- 'config': {
277
- 'features': {
278
- 'test': 'not a boolean',
267
+ "name": faker.word(),
268
+ "url": faker.url(),
269
+ "backend": "factory",
270
+ "config": {
271
+ "features": {
272
+ "test": "not a boolean",
279
273
  }
280
- }
274
+ },
281
275
  }
282
- response = api.post(url_for('api.harvest_sources'), data)
276
+ response = api.post(url_for("api.harvest_sources"), data)
283
277
 
284
278
  assert400(response)
285
279
 
286
280
  def test_create_source_with_config_with_custom_key(self, api):
287
281
  api.login()
288
282
  data = {
289
- 'name': faker.word(),
290
- 'url': faker.url(),
291
- 'backend': 'factory',
292
- 'config': {'custom': 'value'}
283
+ "name": faker.word(),
284
+ "url": faker.url(),
285
+ "backend": "factory",
286
+ "config": {"custom": "value"},
293
287
  }
294
- response = api.post(url_for('api.harvest_sources'), data)
288
+ response = api.post(url_for("api.harvest_sources"), data)
295
289
 
296
290
  assert201(response)
297
291
 
298
292
  source = response.json
299
- assert source['config'] == {'custom': 'value'}
293
+ assert source["config"] == {"custom": "value"}
300
294
 
301
295
  def test_update_source(self, api):
302
- '''It should update a source if owner or orga member'''
296
+ """It should update a source if owner or orga member"""
303
297
  user = api.login()
304
298
  source = HarvestSourceFactory(owner=user)
305
299
  new_url = faker.url()
306
300
  data = {
307
- 'name': source.name,
308
- 'description': source.description,
309
- 'url': new_url,
310
- 'backend': 'factory',
301
+ "name": source.name,
302
+ "description": source.description,
303
+ "url": new_url,
304
+ "backend": "factory",
311
305
  }
312
- api_url = url_for('api.harvest_source', ident=str(source.id))
306
+ api_url = url_for("api.harvest_source", ident=str(source.id))
313
307
  response = api.put(api_url, data)
314
308
  assert200(response)
315
- assert response.json['url'] == new_url
309
+ assert response.json["url"] == new_url
316
310
 
317
311
  # Source is now owned by orga, with user as member
318
312
  source.organization = OrganizationFactory(members=[Member(user=user)])
319
313
  source.save()
320
- api_url = url_for('api.harvest_source', ident=str(source.id))
314
+ api_url = url_for("api.harvest_source", ident=str(source.id))
321
315
  response = api.put(api_url, data)
322
316
  assert200(response)
323
317
 
324
318
  def test_update_source_require_permission(self, api):
325
- '''It should not update a source if not the owner'''
319
+ """It should not update a source if not the owner"""
326
320
  api.login()
327
321
  source = HarvestSourceFactory()
328
322
  new_url: str = faker.url()
329
323
  data = {
330
- 'name': source.name,
331
- 'description': source.description,
332
- 'url': new_url,
333
- 'backend': 'factory',
324
+ "name": source.name,
325
+ "description": source.description,
326
+ "url": new_url,
327
+ "backend": "factory",
334
328
  }
335
- api_url: str = url_for('api.harvest_source', ident=str(source.id))
329
+ api_url: str = url_for("api.harvest_source", ident=str(source.id))
336
330
  response = api.put(api_url, data)
337
331
 
338
332
  assert403(response)
339
333
 
340
334
  def test_validate_source(self, api):
341
- '''It should allow to validate a source if admin'''
335
+ """It should allow to validate a source if admin"""
342
336
  user = api.login(AdminFactory())
343
337
  source = HarvestSourceFactory()
344
338
 
345
- data = {'state': VALIDATION_ACCEPTED}
346
- url = url_for('api.validate_harvest_source', ident=str(source.id))
339
+ data = {"state": VALIDATION_ACCEPTED}
340
+ url = url_for("api.validate_harvest_source", ident=str(source.id))
347
341
  response = api.post(url, data)
348
342
  assert200(response)
349
343
 
@@ -352,53 +346,57 @@ class HarvestAPITest(MockBackendsMixin):
352
346
  assert source.validation.by == user
353
347
 
354
348
  def test_reject_source(self, api):
355
- '''It should allow to reject a source if admin'''
349
+ """It should allow to reject a source if admin"""
356
350
  user = api.login(AdminFactory())
357
351
  source = HarvestSourceFactory()
358
352
 
359
- data = {'state': VALIDATION_REFUSED, 'comment': 'Not valid'}
360
- url = url_for('api.validate_harvest_source', ident=str(source.id))
353
+ data = {"state": VALIDATION_REFUSED, "comment": "Not valid"}
354
+ url = url_for("api.validate_harvest_source", ident=str(source.id))
361
355
  response = api.post(url, data)
362
356
  assert200(response)
363
357
 
364
358
  source.reload()
365
359
  assert source.validation.state == VALIDATION_REFUSED
366
- assert source.validation.comment == 'Not valid'
360
+ assert source.validation.comment == "Not valid"
367
361
  assert source.validation.by == user
368
362
 
369
363
  def test_validate_source_is_admin_only(self, api):
370
- '''It should allow to validate a source if admin'''
364
+ """It should allow to validate a source if admin"""
371
365
  api.login()
372
366
  source = HarvestSourceFactory()
373
367
 
374
- data = {'validate': True}
375
- url = url_for('api.validate_harvest_source', ident=str(source.id))
368
+ data = {"validate": True}
369
+ url = url_for("api.validate_harvest_source", ident=str(source.id))
376
370
  response = api.post(url, data)
377
371
  assert403(response)
378
372
 
379
373
  def test_get_source(self, api):
380
374
  source = HarvestSourceFactory()
381
375
 
382
- url = url_for('api.harvest_source', ident=str(source.id))
376
+ url = url_for("api.harvest_source", ident=str(source.id))
383
377
  response = api.get(url)
384
378
  assert200(response)
385
379
 
386
380
  def test_source_preview(self, api):
387
381
  api.login()
388
- source = HarvestSourceFactory(backend='factory')
382
+ source = HarvestSourceFactory(backend="factory")
389
383
 
390
- url = url_for('api.preview_harvest_source', ident=str(source.id))
384
+ url = url_for("api.preview_harvest_source", ident=str(source.id))
391
385
  response = api.get(url)
392
386
  assert200(response)
393
387
 
394
388
  @pytest.mark.options(HARVEST_ENABLE_MANUAL_RUN=True)
395
389
  def test_run_source(self, mocker: MockerFixture, api: ApiClient):
396
- launch = mocker.patch.object(actions.harvest, 'delay')
390
+ launch = mocker.patch.object(actions.harvest, "delay")
397
391
  user = api.login()
398
392
 
399
- source = HarvestSourceFactory(backend='factory', owner=user, validation=HarvestSourceValidation(state=VALIDATION_ACCEPTED))
393
+ source = HarvestSourceFactory(
394
+ backend="factory",
395
+ owner=user,
396
+ validation=HarvestSourceValidation(state=VALIDATION_ACCEPTED),
397
+ )
400
398
 
401
- url = url_for('api.run_harvest_source', ident=str(source.id))
399
+ url = url_for("api.run_harvest_source", ident=str(source.id))
402
400
  response = api.post(url)
403
401
  assert200(response)
404
402
 
@@ -406,12 +404,16 @@ class HarvestAPITest(MockBackendsMixin):
406
404
 
407
405
  @pytest.mark.options(HARVEST_ENABLE_MANUAL_RUN=False)
408
406
  def test_cannot_run_source_if_disabled(self, mocker: MockerFixture, api: ApiClient):
409
- launch = mocker.patch.object(actions.harvest, 'delay')
407
+ launch = mocker.patch.object(actions.harvest, "delay")
410
408
  user = api.login()
411
409
 
412
- source = HarvestSourceFactory(backend='factory', owner=user, validation=HarvestSourceValidation(state=VALIDATION_ACCEPTED))
410
+ source = HarvestSourceFactory(
411
+ backend="factory",
412
+ owner=user,
413
+ validation=HarvestSourceValidation(state=VALIDATION_ACCEPTED),
414
+ )
413
415
 
414
- url = url_for('api.run_harvest_source', ident=str(source.id))
416
+ url = url_for("api.run_harvest_source", ident=str(source.id))
415
417
  response = api.post(url)
416
418
  assert400(response)
417
419
 
@@ -419,13 +421,17 @@ class HarvestAPITest(MockBackendsMixin):
419
421
 
420
422
  @pytest.mark.options(HARVEST_ENABLE_MANUAL_RUN=True)
421
423
  def test_cannot_run_source_if_not_owned(self, mocker: MockerFixture, api: ApiClient):
422
- launch = mocker.patch.object(actions.harvest, 'delay')
424
+ launch = mocker.patch.object(actions.harvest, "delay")
423
425
  other_user = UserFactory()
424
426
  api.login()
425
427
 
426
- source = HarvestSourceFactory(backend='factory', owner=other_user, validation=HarvestSourceValidation(state=VALIDATION_ACCEPTED))
428
+ source = HarvestSourceFactory(
429
+ backend="factory",
430
+ owner=other_user,
431
+ validation=HarvestSourceValidation(state=VALIDATION_ACCEPTED),
432
+ )
427
433
 
428
- url = url_for('api.run_harvest_source', ident=str(source.id))
434
+ url = url_for("api.run_harvest_source", ident=str(source.id))
429
435
  response = api.post(url)
430
436
  assert403(response)
431
437
 
@@ -433,12 +439,16 @@ class HarvestAPITest(MockBackendsMixin):
433
439
 
434
440
  @pytest.mark.options(HARVEST_ENABLE_MANUAL_RUN=True)
435
441
  def test_cannot_run_source_if_not_validated(self, mocker: MockerFixture, api: ApiClient):
436
- launch = mocker.patch.object(actions.harvest, 'delay')
442
+ launch = mocker.patch.object(actions.harvest, "delay")
437
443
  user = api.login()
438
444
 
439
- source = HarvestSourceFactory(backend='factory', owner=user, validation=HarvestSourceValidation(state=VALIDATION_PENDING))
445
+ source = HarvestSourceFactory(
446
+ backend="factory",
447
+ owner=user,
448
+ validation=HarvestSourceValidation(state=VALIDATION_PENDING),
449
+ )
440
450
 
441
- url = url_for('api.run_harvest_source', ident=str(source.id))
451
+ url = url_for("api.run_harvest_source", ident=str(source.id))
442
452
  response = api.post(url)
443
453
  assert400(response)
444
454
 
@@ -446,19 +456,15 @@ class HarvestAPITest(MockBackendsMixin):
446
456
 
447
457
  def test_source_from_config(self, api):
448
458
  api.login()
449
- data = {
450
- 'name': faker.word(),
451
- 'url': faker.url(),
452
- 'backend': 'factory'
453
- }
454
- response = api.post(url_for('api.preview_harvest_source_config'), data)
459
+ data = {"name": faker.word(), "url": faker.url(), "backend": "factory"}
460
+ response = api.post(url_for("api.preview_harvest_source_config"), data)
455
461
  assert200(response)
456
462
 
457
463
  def test_delete_source(self, api):
458
464
  user = api.login()
459
465
  source = HarvestSourceFactory(owner=user)
460
466
 
461
- url = url_for('api.harvest_source', ident=str(source.id))
467
+ url = url_for("api.harvest_source", ident=str(source.id))
462
468
  response = api.delete(url)
463
469
  assert204(response)
464
470
 
@@ -466,44 +472,44 @@ class HarvestAPITest(MockBackendsMixin):
466
472
  assert len(deleted_sources) == 1
467
473
 
468
474
  def test_delete_source_require_permission(self, api):
469
- '''It should not delete a source if not the owner'''
475
+ """It should not delete a source if not the owner"""
470
476
  api.login()
471
477
  source = HarvestSourceFactory()
472
478
 
473
- url = url_for('api.harvest_source', ident=str(source.id))
479
+ url = url_for("api.harvest_source", ident=str(source.id))
474
480
  response = api.delete(url)
475
481
 
476
482
  assert403(response)
477
483
 
478
484
  def test_schedule_source(self, api):
479
- '''It should allow to schedule a source if admin'''
485
+ """It should allow to schedule a source if admin"""
480
486
  api.login(AdminFactory())
481
487
  source = HarvestSourceFactory()
482
488
 
483
- data = '0 0 * * *'
484
- url = url_for('api.schedule_harvest_source', ident=str(source.id))
489
+ data = "0 0 * * *"
490
+ url = url_for("api.schedule_harvest_source", ident=str(source.id))
485
491
  response = api.post(url, data)
486
492
  assert200(response)
487
493
 
488
- assert response.json['schedule'] == '0 0 * * *'
494
+ assert response.json["schedule"] == "0 0 * * *"
489
495
 
490
496
  source.reload()
491
497
  assert source.periodic_task is not None
492
498
  periodic_task = source.periodic_task
493
- assert periodic_task.crontab.hour == '0'
494
- assert periodic_task.crontab.minute == '0'
495
- assert periodic_task.crontab.day_of_week == '*'
496
- assert periodic_task.crontab.day_of_month == '*'
497
- assert periodic_task.crontab.month_of_year == '*'
499
+ assert periodic_task.crontab.hour == "0"
500
+ assert periodic_task.crontab.minute == "0"
501
+ assert periodic_task.crontab.day_of_week == "*"
502
+ assert periodic_task.crontab.day_of_month == "*"
503
+ assert periodic_task.crontab.month_of_year == "*"
498
504
  assert periodic_task.enabled
499
505
 
500
506
  def test_schedule_source_is_admin_only(self, api):
501
- '''It should only allow admins to schedule a source'''
507
+ """It should only allow admins to schedule a source"""
502
508
  api.login()
503
509
  source = HarvestSourceFactory()
504
510
 
505
- data = '0 0 * * *'
506
- url = url_for('api.schedule_harvest_source', ident=str(source.id))
511
+ data = "0 0 * * *"
512
+ url = url_for("api.schedule_harvest_source", ident=str(source.id))
507
513
  response = api.post(url, data)
508
514
  assert403(response)
509
515
 
@@ -511,18 +517,18 @@ class HarvestAPITest(MockBackendsMixin):
511
517
  assert source.periodic_task is None
512
518
 
513
519
  def test_unschedule_source(self, api):
514
- '''It should allow to unschedule a source if admin'''
520
+ """It should allow to unschedule a source if admin"""
515
521
  api.login(AdminFactory())
516
522
  periodic_task = PeriodicTask.objects.create(
517
- task='harvest',
523
+ task="harvest",
518
524
  name=faker.name(),
519
525
  description=faker.sentence(),
520
526
  enabled=True,
521
- crontab=PeriodicTask.Crontab()
527
+ crontab=PeriodicTask.Crontab(),
522
528
  )
523
529
  source = HarvestSourceFactory(periodic_task=periodic_task)
524
530
 
525
- url = url_for('api.schedule_harvest_source', ident=str(source.id))
531
+ url = url_for("api.schedule_harvest_source", ident=str(source.id))
526
532
  response = api.delete(url)
527
533
  assert204(response)
528
534
 
@@ -530,18 +536,18 @@ class HarvestAPITest(MockBackendsMixin):
530
536
  assert source.periodic_task is None
531
537
 
532
538
  def test_unschedule_source_is_admin_only(self, api):
533
- '''It should only allow admins to unschedule a source'''
539
+ """It should only allow admins to unschedule a source"""
534
540
  api.login()
535
541
  periodic_task = PeriodicTask.objects.create(
536
- task='harvest',
542
+ task="harvest",
537
543
  name=faker.name(),
538
544
  description=faker.sentence(),
539
545
  enabled=True,
540
- crontab=PeriodicTask.Crontab()
546
+ crontab=PeriodicTask.Crontab(),
541
547
  )
542
548
  source = HarvestSourceFactory(periodic_task=periodic_task)
543
549
 
544
- url = url_for('api.schedule_harvest_source', ident=str(source.id))
550
+ url = url_for("api.schedule_harvest_source", ident=str(source.id))
545
551
  response = api.delete(url)
546
552
  assert403(response)
547
553