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
@@ -1,37 +1,42 @@
1
1
  import csv
2
2
  import logging
3
- import pytest
4
-
5
3
  from datetime import datetime, timedelta
6
4
  from tempfile import NamedTemporaryFile
7
5
 
6
+ import pytest
8
7
  from mock import patch
9
8
 
10
- from udata.models import Dataset, PeriodicTask
11
-
12
- from udata.core.organization.factories import OrganizationFactory
13
- from udata.core.user.factories import UserFactory
14
9
  from udata.core.dataset.factories import DatasetFactory
15
10
  from udata.core.dataset.models import HarvestDatasetMetadata
11
+ from udata.core.organization.factories import OrganizationFactory
12
+ from udata.core.user.factories import UserFactory
13
+ from udata.models import Dataset, PeriodicTask
16
14
  from udata.tests.helpers import assert_emit, assert_equal_dates
17
- from udata.utils import faker, Paginable
15
+ from udata.utils import Paginable, faker
18
16
 
19
- from .factories import (
20
- HarvestSourceFactory, HarvestJobFactory, MockBackendsMixin,
21
- mock_initialize, mock_process, DEFAULT_COUNT as COUNT
22
- )
17
+ from .. import actions, signals
18
+ from ..backends import BaseBackend
23
19
  from ..models import (
24
- HarvestSource, HarvestJob, HarvestError,
25
- VALIDATION_PENDING, VALIDATION_ACCEPTED, VALIDATION_REFUSED
20
+ VALIDATION_ACCEPTED,
21
+ VALIDATION_PENDING,
22
+ VALIDATION_REFUSED,
23
+ HarvestError,
24
+ HarvestJob,
25
+ HarvestSource,
26
+ )
27
+ from .factories import DEFAULT_COUNT as COUNT
28
+ from .factories import (
29
+ HarvestJobFactory,
30
+ HarvestSourceFactory,
31
+ MockBackendsMixin,
32
+ mock_initialize,
33
+ mock_process,
26
34
  )
27
- from ..backends import BaseBackend
28
- from .. import actions, signals
29
-
30
35
 
31
36
  log = logging.getLogger(__name__)
32
37
 
33
38
  pytestmark = [
34
- pytest.mark.usefixtures('clean_db'),
39
+ pytest.mark.usefixtures("clean_db"),
35
40
  ]
36
41
 
37
42
 
@@ -163,15 +168,13 @@ class HarvestActionsTest:
163
168
  source_url = faker.url()
164
169
 
165
170
  with assert_emit(signals.harvest_source_created):
166
- source = actions.create_source('Test source',
167
- source_url,
168
- 'factory')
171
+ source = actions.create_source("Test source", source_url, "factory")
169
172
 
170
- assert source.name == 'Test source'
171
- assert source.slug == 'test-source'
173
+ assert source.name == "Test source"
174
+ assert source.slug == "test-source"
172
175
  assert source.url == source_url
173
- assert source.backend == 'factory'
174
- assert source.frequency == 'manual'
176
+ assert source.backend == "factory"
177
+ assert source.frequency == "manual"
175
178
  assert source.active
176
179
  assert source.owner is None
177
180
  assert source.organization is None
@@ -184,15 +187,12 @@ class HarvestActionsTest:
184
187
  def test_create_source_with_config(self):
185
188
  source_url = faker.url()
186
189
  config = {
187
- 'filters': [{'key': 'test', 'value': 42}],
188
- 'features': {'key': True},
190
+ "filters": [{"key": "test", "value": 42}],
191
+ "features": {"key": True},
189
192
  }
190
193
 
191
194
  with assert_emit(signals.harvest_source_created):
192
- source = actions.create_source('Test source',
193
- source_url,
194
- 'factory',
195
- config=config)
195
+ source = actions.create_source("Test source", source_url, "factory", config=config)
196
196
 
197
197
  assert source.config == config
198
198
 
@@ -200,7 +200,7 @@ class HarvestActionsTest:
200
200
  source = HarvestSourceFactory()
201
201
  data = source.to_dict()
202
202
  new_url = faker.url()
203
- data['url'] = new_url
203
+ data["url"] = new_url
204
204
 
205
205
  with assert_emit(signals.harvest_source_updated):
206
206
  source = actions.update_source(source.id, data)
@@ -209,7 +209,7 @@ class HarvestActionsTest:
209
209
  source.reload()
210
210
  assert source.url == new_url
211
211
 
212
- @patch('udata.harvest.actions.launch')
212
+ @patch("udata.harvest.actions.launch")
213
213
  def test_validate_source(self, mock):
214
214
  source = HarvestSourceFactory()
215
215
 
@@ -224,30 +224,30 @@ class HarvestActionsTest:
224
224
 
225
225
  assert source.periodic_task is not None
226
226
 
227
- @patch('udata.harvest.actions.launch')
227
+ @patch("udata.harvest.actions.launch")
228
228
  def test_validate_source_with_comment(self, mock):
229
229
  source = HarvestSourceFactory()
230
230
 
231
- actions.validate_source(source.id, 'comment')
231
+ actions.validate_source(source.id, "comment")
232
232
 
233
233
  source.reload()
234
234
 
235
235
  assert source.validation.state == VALIDATION_ACCEPTED
236
236
  assert source.validation.on is not None
237
237
  assert source.validation.by is None
238
- assert source.validation.comment == 'comment'
238
+ assert source.validation.comment == "comment"
239
239
  mock.assert_called_once_with(source.id)
240
240
 
241
241
  def test_reject_source(self):
242
242
  source = HarvestSourceFactory()
243
243
 
244
- actions.reject_source(source.id, 'comment')
244
+ actions.reject_source(source.id, "comment")
245
245
 
246
246
  source.reload()
247
247
  assert source.validation.state == VALIDATION_REFUSED
248
248
  assert source.validation.on is not None
249
249
  assert source.validation.by is None
250
- assert source.validation.comment == 'comment'
250
+ assert source.validation.comment == "comment"
251
251
 
252
252
  def test_get_source_by_slug(self):
253
253
  source = HarvestSourceFactory()
@@ -291,7 +291,7 @@ class HarvestActionsTest:
291
291
  deleted_sources = HarvestSource.objects(deleted__exists=True)
292
292
  assert len(deleted_sources) == 1
293
293
 
294
- @pytest.mark.parametrize('by_attr', ['source.id', 'str(source.id)', 'source.slug'])
294
+ @pytest.mark.parametrize("by_attr", ["source.id", "str(source.id)", "source.slug"])
295
295
  def test_clean_source(self, by_attr):
296
296
  source = HarvestSourceFactory()
297
297
  for _ in range(5):
@@ -319,30 +319,30 @@ class HarvestActionsTest:
319
319
  periodic_task = source.periodic_task
320
320
  assert periodic_task == PeriodicTask.objects.first()
321
321
  assert periodic_task.args == [str(source.id)]
322
- assert periodic_task.crontab.hour == '0'
323
- assert periodic_task.crontab.minute == '*'
324
- assert periodic_task.crontab.day_of_week == '*'
325
- assert periodic_task.crontab.day_of_month == '*'
326
- assert periodic_task.crontab.month_of_year == '*'
322
+ assert periodic_task.crontab.hour == "0"
323
+ assert periodic_task.crontab.minute == "*"
324
+ assert periodic_task.crontab.day_of_week == "*"
325
+ assert periodic_task.crontab.day_of_month == "*"
326
+ assert periodic_task.crontab.month_of_year == "*"
327
327
  assert periodic_task.enabled
328
- assert periodic_task.name == 'Harvest {0}'.format(source.name)
328
+ assert periodic_task.name == "Harvest {0}".format(source.name)
329
329
 
330
330
  def test_schedule_from_cron(self):
331
331
  source = HarvestSourceFactory()
332
332
  with assert_emit(signals.harvest_source_scheduled):
333
- source = actions.schedule(str(source.id), '0 1 2 3 sunday')
333
+ source = actions.schedule(str(source.id), "0 1 2 3 sunday")
334
334
 
335
335
  assert len(PeriodicTask.objects) == 1
336
336
  periodic_task = source.periodic_task
337
337
  assert periodic_task == PeriodicTask.objects.first()
338
338
  assert periodic_task.args == [str(source.id)]
339
- assert periodic_task.crontab.minute == '0'
340
- assert periodic_task.crontab.hour == '1'
341
- assert periodic_task.crontab.day_of_month == '2'
342
- assert periodic_task.crontab.month_of_year == '3'
343
- assert periodic_task.crontab.day_of_week == 'sunday'
339
+ assert periodic_task.crontab.minute == "0"
340
+ assert periodic_task.crontab.hour == "1"
341
+ assert periodic_task.crontab.day_of_month == "2"
342
+ assert periodic_task.crontab.month_of_year == "3"
343
+ assert periodic_task.crontab.day_of_week == "sunday"
344
344
  assert periodic_task.enabled
345
- assert periodic_task.name == 'Harvest {0}'.format(source.name)
345
+ assert periodic_task.name == "Harvest {0}".format(source.name)
346
346
 
347
347
  def test_reschedule(self):
348
348
  source = HarvestSourceFactory()
@@ -356,21 +356,21 @@ class HarvestActionsTest:
356
356
  periodic_task = source.periodic_task
357
357
  assert periodic_task == PeriodicTask.objects.first()
358
358
  assert periodic_task.args == [str(source.id)]
359
- assert periodic_task.crontab.hour == '*'
360
- assert periodic_task.crontab.minute == '0'
361
- assert periodic_task.crontab.day_of_week == '*'
362
- assert periodic_task.crontab.day_of_month == '*'
363
- assert periodic_task.crontab.month_of_year == '*'
359
+ assert periodic_task.crontab.hour == "*"
360
+ assert periodic_task.crontab.minute == "0"
361
+ assert periodic_task.crontab.day_of_week == "*"
362
+ assert periodic_task.crontab.day_of_month == "*"
363
+ assert periodic_task.crontab.month_of_year == "*"
364
364
  assert periodic_task.enabled
365
- assert periodic_task.name == 'Harvest {0}'.format(source.name)
365
+ assert periodic_task.name == "Harvest {0}".format(source.name)
366
366
 
367
367
  def test_unschedule(self):
368
368
  periodic_task = PeriodicTask.objects.create(
369
- task='harvest',
369
+ task="harvest",
370
370
  name=faker.name(),
371
371
  description=faker.sentence(),
372
372
  enabled=True,
373
- crontab=PeriodicTask.Crontab()
373
+ crontab=PeriodicTask.Crontab(),
374
374
  )
375
375
  source = HarvestSourceFactory(periodic_task=periodic_task)
376
376
  with assert_emit(signals.harvest_source_unscheduled):
@@ -382,17 +382,15 @@ class HarvestActionsTest:
382
382
 
383
383
  def test_purge_sources(self):
384
384
  periodic_task = PeriodicTask.objects.create(
385
- task='harvest',
385
+ task="harvest",
386
386
  name=faker.name(),
387
387
  description=faker.sentence(),
388
388
  enabled=True,
389
- crontab=PeriodicTask.Crontab()
389
+ crontab=PeriodicTask.Crontab(),
390
390
  )
391
391
  now = datetime.utcnow()
392
392
  to_delete = HarvestSourceFactory.create_batch(2, deleted=now)
393
- to_delete.append(
394
- HarvestSourceFactory(periodic_task=periodic_task, deleted=now)
395
- )
393
+ to_delete.append(HarvestSourceFactory(periodic_task=periodic_task, deleted=now))
396
394
  to_keep = HarvestSourceFactory.create_batch(2)
397
395
  harvest_job = HarvestJobFactory(source=to_delete[0])
398
396
  dataset_to_archive = DatasetFactory(
@@ -406,7 +404,7 @@ class HarvestActionsTest:
406
404
  assert len(HarvestSource.objects) == len(to_keep)
407
405
  assert PeriodicTask.objects.filter(id=periodic_task.id).count() == 0
408
406
  assert HarvestJob.objects(id=harvest_job.id).count() == 0
409
- assert dataset_to_archive.harvest.archived == 'harvester-deleted'
407
+ assert dataset_to_archive.harvest.archived == "harvester-deleted"
410
408
  assert_equal_dates(dataset_to_archive.archived, now)
411
409
 
412
410
  @pytest.mark.options(HARVEST_JOBS_RETENTION_DAYS=2)
@@ -428,91 +426,71 @@ class HarvestActionsTest:
428
426
  def test_attach(self):
429
427
  datasets = DatasetFactory.create_batch(3)
430
428
 
431
- with NamedTemporaryFile(mode='w') as csvfile:
432
- writer = csv.DictWriter(csvfile,
433
- fieldnames=['local', 'remote'],
434
- delimiter=';',
435
- quotechar='"')
429
+ with NamedTemporaryFile(mode="w") as csvfile:
430
+ writer = csv.DictWriter(
431
+ csvfile, fieldnames=["local", "remote"], delimiter=";", quotechar='"'
432
+ )
436
433
 
437
434
  writer.writeheader()
438
435
  for index, dataset in enumerate(datasets):
439
- writer.writerow({
440
- 'local': str(dataset.id),
441
- 'remote': str(index)
442
- })
436
+ writer.writerow({"local": str(dataset.id), "remote": str(index)})
443
437
  csvfile.flush()
444
438
 
445
- result = actions.attach('test.org', csvfile.name)
439
+ result = actions.attach("test.org", csvfile.name)
446
440
 
447
441
  assert result.success == len(datasets)
448
442
  assert result.errors == 0
449
443
  for index, dataset in enumerate(datasets):
450
444
  dataset.reload()
451
- assert dataset.harvest.domain == 'test.org'
445
+ assert dataset.harvest.domain == "test.org"
452
446
  assert dataset.harvest.remote_id == str(index)
453
447
 
454
448
  def test_attach_does_not_duplicate(self):
455
449
  attached_datasets = []
456
450
  for i in range(2):
457
451
  dataset = DatasetFactory.build()
458
- dataset.harvest = HarvestDatasetMetadata(
459
- domain='test.org',
460
- remote_id=str(i)
461
- )
452
+ dataset.harvest = HarvestDatasetMetadata(domain="test.org", remote_id=str(i))
462
453
  dataset.last_modified_internal = datetime.utcnow()
463
454
  dataset.save()
464
455
  attached_datasets.append(dataset)
465
456
 
466
457
  datasets = DatasetFactory.create_batch(3)
467
458
 
468
- with NamedTemporaryFile(mode='w') as csvfile:
469
- writer = csv.DictWriter(csvfile,
470
- fieldnames=['local', 'remote'],
471
- delimiter=';',
472
- quotechar='"')
459
+ with NamedTemporaryFile(mode="w") as csvfile:
460
+ writer = csv.DictWriter(
461
+ csvfile, fieldnames=["local", "remote"], delimiter=";", quotechar='"'
462
+ )
473
463
 
474
464
  writer.writeheader()
475
465
  for index, dataset in enumerate(datasets):
476
- writer.writerow({
477
- 'local': str(dataset.id),
478
- 'remote': str(index)
479
- })
466
+ writer.writerow({"local": str(dataset.id), "remote": str(index)})
480
467
  csvfile.flush()
481
468
 
482
- result = actions.attach('test.org', csvfile.name)
469
+ result = actions.attach("test.org", csvfile.name)
483
470
 
484
- dbcount = Dataset.objects(**{
485
- 'harvest__remote_id__exists': True
486
- }).count()
471
+ dbcount = Dataset.objects(**{"harvest__remote_id__exists": True}).count()
487
472
  assert result.success == len(datasets)
488
473
  assert dbcount == result.success
489
474
  for index, dataset in enumerate(datasets):
490
475
  dataset.reload()
491
- assert dataset.harvest.domain == 'test.org'
476
+ assert dataset.harvest.domain == "test.org"
492
477
  assert dataset.harvest.remote_id == str(index)
493
478
 
494
479
  def test_attach_skip_not_found(self):
495
480
  datasets = DatasetFactory.create_batch(3)
496
481
 
497
- with NamedTemporaryFile(mode='w') as csvfile:
498
- writer = csv.DictWriter(csvfile,
499
- fieldnames=['local', 'remote'],
500
- delimiter=';',
501
- quotechar='"')
482
+ with NamedTemporaryFile(mode="w") as csvfile:
483
+ writer = csv.DictWriter(
484
+ csvfile, fieldnames=["local", "remote"], delimiter=";", quotechar='"'
485
+ )
502
486
 
503
487
  writer.writeheader()
504
- writer.writerow({
505
- 'local': 'not-found',
506
- 'remote': '42'
507
- })
488
+ writer.writerow({"local": "not-found", "remote": "42"})
508
489
  for index, dataset in enumerate(datasets):
509
- writer.writerow({
510
- 'local': str(dataset.id),
511
- 'remote': str(index)
512
- })
490
+ writer.writerow({"local": str(dataset.id), "remote": str(index)})
513
491
  csvfile.flush()
514
492
 
515
- result = actions.attach('test.org', csvfile.name)
493
+ result = actions.attach("test.org", csvfile.name)
516
494
 
517
495
  assert result.success == len(datasets)
518
496
  assert result.errors == 1
@@ -521,9 +499,8 @@ class HarvestActionsTest:
521
499
  class ExecutionTestMixin(MockBackendsMixin):
522
500
  def test_default(self):
523
501
  org = OrganizationFactory()
524
- source = HarvestSourceFactory(backend='factory', organization=org)
525
- with assert_emit(signals.before_harvest_job,
526
- signals.after_harvest_job):
502
+ source = HarvestSourceFactory(backend="factory", organization=org)
503
+ with assert_emit(signals.before_harvest_job, signals.after_harvest_job):
527
504
  self.action(source.slug)
528
505
 
529
506
  source.reload()
@@ -531,14 +508,14 @@ class ExecutionTestMixin(MockBackendsMixin):
531
508
 
532
509
  job = source.get_last_job()
533
510
 
534
- assert job.status == 'done'
511
+ assert job.status == "done"
535
512
  assert job.errors == []
536
513
  assert job.started is not None
537
514
  assert job.ended is not None
538
515
  assert len(job.items) == COUNT
539
516
 
540
517
  for item in job.items:
541
- assert item.status == 'done'
518
+ assert item.status == "done"
542
519
  assert item.errors == []
543
520
  assert item.started is not None
544
521
  assert item.ended is not None
@@ -547,27 +524,26 @@ class ExecutionTestMixin(MockBackendsMixin):
547
524
  dataset = item.dataset
548
525
  assert Dataset.objects(id=dataset.id).first() is not None
549
526
  assert dataset.organization == org
550
- assert 'remote_id' in dataset.harvest
551
- assert 'last_update' in dataset.harvest
552
- assert 'source_id' in dataset.harvest
527
+ assert "remote_id" in dataset.harvest
528
+ assert "last_update" in dataset.harvest
529
+ assert "source_id" in dataset.harvest
553
530
 
554
531
  assert len(HarvestJob.objects) == 1
555
532
  assert len(Dataset.objects) == COUNT
556
533
 
557
534
  def test_error_on_initialize(self):
558
535
  def init(self):
559
- raise ValueError('test')
536
+ raise ValueError("test")
560
537
 
561
- source = HarvestSourceFactory(backend='factory')
562
- with assert_emit(signals.before_harvest_job),\
563
- mock_initialize.connected_to(init):
538
+ source = HarvestSourceFactory(backend="factory")
539
+ with assert_emit(signals.before_harvest_job), mock_initialize.connected_to(init):
564
540
  self.action(source.slug)
565
541
 
566
542
  source.reload()
567
543
  assert len(HarvestJob.objects(source=source)) == 1
568
544
 
569
545
  job = source.get_last_job()
570
- assert job.status == 'failed'
546
+ assert job.status == "failed"
571
547
  assert len(job.errors) == 1
572
548
  error = job.errors[0]
573
549
  assert isinstance(error, HarvestError)
@@ -580,20 +556,21 @@ class ExecutionTestMixin(MockBackendsMixin):
580
556
 
581
557
  def test_error_on_item(self):
582
558
  def process(self, item):
583
- if item == '1':
584
- raise ValueError('test')
585
-
586
- source = HarvestSourceFactory(backend='factory')
587
- with assert_emit(signals.before_harvest_job,
588
- signals.after_harvest_job), \
589
- mock_process.connected_to(process):
559
+ if item == "1":
560
+ raise ValueError("test")
561
+
562
+ source = HarvestSourceFactory(backend="factory")
563
+ with (
564
+ assert_emit(signals.before_harvest_job, signals.after_harvest_job),
565
+ mock_process.connected_to(process),
566
+ ):
590
567
  self.action(source.slug)
591
568
 
592
569
  source.reload()
593
570
  assert len(HarvestJob.objects(source=source)) == 1
594
571
 
595
572
  job = source.get_last_job()
596
- assert job.status == 'done-errors'
573
+ assert job.status == "done-errors"
597
574
  assert job.started is not None
598
575
  assert job.ended is not None
599
576
  assert len(job.errors) == 0
@@ -605,13 +582,13 @@ class ExecutionTestMixin(MockBackendsMixin):
605
582
  for item in items_ok:
606
583
  assert item.started is not None
607
584
  assert item.ended is not None
608
- assert item.status == 'done'
585
+ assert item.status == "done"
609
586
  assert item.errors == []
610
587
 
611
588
  item_ko = next(i for i in job.items if i.errors)
612
589
  assert item_ko.started is not None
613
590
  assert item_ko.ended is not None
614
- assert item_ko.status == 'failed'
591
+ assert item_ko.status == "failed"
615
592
  assert len(item_ko.errors) == 1
616
593
 
617
594
  error = item_ko.errors[0]
@@ -621,9 +598,8 @@ class ExecutionTestMixin(MockBackendsMixin):
621
598
  assert len(Dataset.objects) == COUNT - 1
622
599
 
623
600
  def test_empty(self):
624
- source = HarvestSourceFactory(backend='factory', config={'count': 0})
625
- with assert_emit(signals.before_harvest_job,
626
- signals.after_harvest_job):
601
+ source = HarvestSourceFactory(backend="factory", config={"count": 0})
602
+ with assert_emit(signals.before_harvest_job, signals.after_harvest_job):
627
603
  self.action(source.slug)
628
604
 
629
605
  source.reload()
@@ -631,7 +607,7 @@ class ExecutionTestMixin(MockBackendsMixin):
631
607
 
632
608
  job = source.get_last_job()
633
609
 
634
- assert job.status == 'done'
610
+ assert job.status == "done"
635
611
  assert job.errors == []
636
612
  assert job.started is not None
637
613
  assert job.ended is not None
@@ -643,9 +619,7 @@ class ExecutionTestMixin(MockBackendsMixin):
643
619
  @pytest.mark.options(HARVEST_MAX_ITEMS=5)
644
620
  def test_harvest_max_items(self):
645
621
  org = OrganizationFactory()
646
- source = HarvestSourceFactory(backend='factory',
647
- organization=org,
648
- config={'count': 10})
622
+ source = HarvestSourceFactory(backend="factory", organization=org, config={"count": 10})
649
623
 
650
624
  self.action(source.slug)
651
625
  assert len(Dataset.objects) == 5
@@ -664,18 +638,18 @@ class HarvestRunTest(ExecutionTestMixin):
664
638
  class HarvestPreviewTest(MockBackendsMixin):
665
639
  def test_preview(self):
666
640
  org = OrganizationFactory()
667
- source = HarvestSourceFactory(backend='factory', organization=org)
641
+ source = HarvestSourceFactory(backend="factory", organization=org)
668
642
 
669
643
  job = actions.preview(source.slug)
670
644
 
671
- assert job.status == 'done'
645
+ assert job.status == "done"
672
646
  assert job.errors == []
673
647
  assert job.started is not None
674
648
  assert job.ended is not None
675
649
  assert len(job.items) == COUNT
676
650
 
677
651
  for item in job.items:
678
- assert item.status == 'done'
652
+ assert item.status == "done"
679
653
  assert item.errors == []
680
654
  assert item.started is not None
681
655
  assert item.ended is not None
@@ -683,9 +657,9 @@ class HarvestPreviewTest(MockBackendsMixin):
683
657
 
684
658
  dataset = item.dataset
685
659
  assert dataset.organization == org
686
- assert 'remote_id' in dataset.harvest
687
- assert 'last_update' in dataset.harvest
688
- assert 'source_id' in dataset.harvest
660
+ assert "remote_id" in dataset.harvest
661
+ assert "last_update" in dataset.harvest
662
+ assert "source_id" in dataset.harvest
689
663
 
690
664
  assert len(HarvestJob.objects) == 0
691
665
  assert len(Dataset.objects) == 0
@@ -693,9 +667,7 @@ class HarvestPreviewTest(MockBackendsMixin):
693
667
  @pytest.mark.options(HARVEST_PREVIEW_MAX_ITEMS=5)
694
668
  def test_preview_max_items(self):
695
669
  org = OrganizationFactory()
696
- source = HarvestSourceFactory(backend='factory',
697
- organization=org,
698
- config={'count': 10})
670
+ source = HarvestSourceFactory(backend="factory", organization=org, config={"count": 10})
699
671
 
700
672
  job = actions.preview(source.slug)
701
673
 
@@ -703,14 +675,14 @@ class HarvestPreviewTest(MockBackendsMixin):
703
675
 
704
676
  def test_preview_with_error_on_initialize(self):
705
677
  def init(self):
706
- raise ValueError('test')
678
+ raise ValueError("test")
707
679
 
708
- source = HarvestSourceFactory(backend='factory')
680
+ source = HarvestSourceFactory(backend="factory")
709
681
 
710
682
  with mock_initialize.connected_to(init):
711
683
  job = actions.preview(source.slug)
712
684
 
713
- assert job.status == 'failed'
685
+ assert job.status == "failed"
714
686
  assert len(job.errors) == 1
715
687
  error = job.errors[0]
716
688
  assert isinstance(error, HarvestError)
@@ -723,15 +695,15 @@ class HarvestPreviewTest(MockBackendsMixin):
723
695
 
724
696
  def test_preview_with_error_on_item(self):
725
697
  def process(self, item):
726
- if item == '1':
727
- raise ValueError('test')
698
+ if item == "1":
699
+ raise ValueError("test")
728
700
 
729
- source = HarvestSourceFactory(backend='factory')
701
+ source = HarvestSourceFactory(backend="factory")
730
702
 
731
703
  with mock_process.connected_to(process):
732
704
  job = actions.preview(source.slug)
733
705
 
734
- assert job.status == 'done-errors'
706
+ assert job.status == "done-errors"
735
707
  assert job.started is not None
736
708
  assert job.ended is not None
737
709
  assert len(job.errors) == 0
@@ -743,13 +715,13 @@ class HarvestPreviewTest(MockBackendsMixin):
743
715
  for item in items_ok:
744
716
  assert item.started is not None
745
717
  assert item.ended is not None
746
- assert item.status == 'done'
718
+ assert item.status == "done"
747
719
  assert item.errors == []
748
720
 
749
721
  item_ko = next(i for i in job.items if i.errors)
750
722
  assert item_ko.started is not None
751
723
  assert item_ko.ended is not None
752
- assert item_ko.status == 'failed'
724
+ assert item_ko.status == "failed"
753
725
  assert len(item_ko.errors) == 1
754
726
 
755
727
  error = item_ko.errors[0]
@@ -762,20 +734,18 @@ class HarvestPreviewTest(MockBackendsMixin):
762
734
  org = OrganizationFactory()
763
735
  source_url = faker.url()
764
736
  count = 10
765
- job = actions.preview_from_config('Test source',
766
- source_url,
767
- 'factory',
768
- organization=org,
769
- config={'count': count})
737
+ job = actions.preview_from_config(
738
+ "Test source", source_url, "factory", organization=org, config={"count": count}
739
+ )
770
740
 
771
- assert job.status == 'done'
741
+ assert job.status == "done"
772
742
  assert job.errors == []
773
743
  assert job.started is not None
774
744
  assert job.ended is not None
775
745
  assert len(job.items) == count
776
746
 
777
747
  for item in job.items:
778
- assert item.status == 'done'
748
+ assert item.status == "done"
779
749
  assert item.errors == []
780
750
  assert item.started is not None
781
751
  assert item.ended is not None
@@ -783,9 +753,9 @@ class HarvestPreviewTest(MockBackendsMixin):
783
753
 
784
754
  dataset = item.dataset
785
755
  assert dataset.organization == org
786
- assert 'remote_id' in dataset.harvest
787
- assert 'last_update' in dataset.harvest
788
- assert 'source_id' in dataset.harvest
756
+ assert "remote_id" in dataset.harvest
757
+ assert "last_update" in dataset.harvest
758
+ assert "source_id" in dataset.harvest
789
759
 
790
760
  assert len(HarvestJob.objects) == 0
791
761
  assert len(Dataset.objects) == 0