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
@@ -2,27 +2,28 @@ from urllib.parse import urlparse
2
2
 
3
3
  from flask import current_app
4
4
 
5
- from .backends import get as get_linkchecker, NoCheckLinkchecker
5
+ from .backends import NoCheckLinkchecker
6
+ from .backends import get as get_linkchecker
6
7
 
7
8
 
8
9
  def _get_check_keys(the_dict, resource, previous_status):
9
- check_keys = {k: v for k, v in the_dict.items()
10
- if k.startswith('check:')}
11
- check_keys['check:count-availability'] = _compute_count_availability(
12
- resource, check_keys.get('check:available'), previous_status)
10
+ check_keys = {k: v for k, v in the_dict.items() if k.startswith("check:")}
11
+ check_keys["check:count-availability"] = _compute_count_availability(
12
+ resource, check_keys.get("check:available"), previous_status
13
+ )
13
14
  return check_keys
14
15
 
15
16
 
16
17
  def _compute_count_availability(resource, status, previous_status):
17
- '''Compute the `check:count-availability` extra value'''
18
- count_availability = resource.extras.get('check:count-availability', 1)
18
+ """Compute the `check:count-availability` extra value"""
19
+ count_availability = resource.extras.get("check:count-availability", 1)
19
20
  return count_availability + 1 if status == previous_status else 1
20
21
 
21
22
 
22
23
  def is_ignored(resource):
23
- '''Check if the resource's URL is to be ignored'''
24
- ignored_domains = current_app.config['LINKCHECKING_IGNORE_DOMAINS']
25
- ignored_patterns = current_app.config['LINKCHECKING_IGNORE_PATTERNS']
24
+ """Check if the resource's URL is to be ignored"""
25
+ ignored_domains = current_app.config["LINKCHECKING_IGNORE_DOMAINS"]
26
+ ignored_patterns = current_app.config["LINKCHECKING_IGNORE_PATTERNS"]
26
27
  url = resource.url
27
28
  if not url:
28
29
  return True
@@ -33,12 +34,12 @@ def is_ignored(resource):
33
34
 
34
35
 
35
36
  def dummy_check_response():
36
- '''Trigger a dummy check'''
37
+ """Trigger a dummy check"""
37
38
  return NoCheckLinkchecker().check(None)
38
39
 
39
40
 
40
41
  def check_resource(resource):
41
- '''
42
+ """
42
43
  Check a resource availability against a linkchecker backend
43
44
 
44
45
  The linkchecker used can be configured on a resource basis by setting
@@ -51,24 +52,24 @@ def check_resource(resource):
51
52
  -------
52
53
  dict or (dict, int)
53
54
  Check results dict and status code (if error).
54
- '''
55
- linkchecker_type = resource.extras.get('check:checker')
55
+ """
56
+ linkchecker_type = resource.extras.get("check:checker")
56
57
  LinkChecker = get_linkchecker(linkchecker_type)
57
58
  if not LinkChecker:
58
- return {'error': 'No linkchecker configured.'}, 503
59
+ return {"error": "No linkchecker configured."}, 503
59
60
  if is_ignored(resource):
60
61
  return dummy_check_response()
61
62
  result = LinkChecker().check(resource)
62
63
  if not result:
63
- return {'error': 'No response from linkchecker'}, 503
64
- elif result.get('check:error'):
65
- return {'error': result['check:error']}, 500
66
- elif not result.get('check:status'):
67
- return {'error': 'No status in response from linkchecker'}, 503
64
+ return {"error": "No response from linkchecker"}, 503
65
+ elif result.get("check:error"):
66
+ return {"error": result["check:error"]}, 500
67
+ elif not result.get("check:status"):
68
+ return {"error": "No status in response from linkchecker"}, 503
68
69
  # store the check result in the resource's extras
69
70
  # XXX maybe this logic should be in the `Resource` model?
70
- previous_status = resource.extras.get('check:available')
71
+ previous_status = resource.extras.get("check:available")
71
72
  check_keys = _get_check_keys(result, resource, previous_status)
72
73
  resource.extras.update(check_keys)
73
- resource.save(signal_kwargs={'ignores': ['post_save']}) # Prevent signal triggering on dataset
74
+ resource.save(signal_kwargs={"ignores": ["post_save"]}) # Prevent signal triggering on dataset
74
75
  return result
@@ -5,19 +5,17 @@ import click
5
5
  from udata.commands import cli
6
6
  from udata.linkchecker.tasks import check_resources
7
7
 
8
-
9
8
  log = logging.getLogger(__name__)
10
9
 
11
10
 
12
- @cli.group('linkchecker')
11
+ @cli.group("linkchecker")
13
12
  def grp():
14
- '''Link checking operations'''
13
+ """Link checking operations"""
15
14
  pass
16
15
 
17
16
 
18
17
  @grp.command()
19
- @click.option('-n', '--number', type=int, default=5000,
20
- help='Number of URLs to check')
18
+ @click.option("-n", "--number", type=int, default=5000, help="Number of URLs to check")
21
19
  def check(number):
22
- '''Check <number> of URLs that have not been (recently) checked'''
20
+ """Check <number> of URLs that have not been (recently) checked"""
23
21
  check_resources(number)
@@ -1,9 +1,9 @@
1
- from udata.mongo import db
2
1
  from udata.core.dataset.models import ResourceMixin
2
+ from udata.mongo import db
3
3
 
4
4
  # Register harvest extras
5
- ResourceMixin.extras.register('check:available', db.BooleanField)
6
- ResourceMixin.extras.register('check:count-availability', db.IntField)
7
- ResourceMixin.extras.register('check:status', db.IntField)
8
- ResourceMixin.extras.register('check:url', db.StringField)
9
- ResourceMixin.extras.register('check:date', db.DateTimeField)
5
+ ResourceMixin.extras.register("check:available", db.BooleanField)
6
+ ResourceMixin.extras.register("check:count-availability", db.IntField)
7
+ ResourceMixin.extras.register("check:status", db.IntField)
8
+ ResourceMixin.extras.register("check:url", db.StringField)
9
+ ResourceMixin.extras.register("check:date", db.DateTimeField)
@@ -12,46 +12,44 @@ from .checker import check_resource
12
12
  log = logging.getLogger(__name__)
13
13
 
14
14
 
15
- @job('check_resources')
15
+ @job("check_resources")
16
16
  def check_resources(self, number):
17
- '''Check <number> of URLs that have not been (recently) checked'''
18
- if not current_app.config.get('LINKCHECKING_ENABLED'):
19
- log.error('Link checking is disabled.')
17
+ """Check <number> of URLs that have not been (recently) checked"""
18
+ if not current_app.config.get("LINKCHECKING_ENABLED"):
19
+ log.error("Link checking is disabled.")
20
20
  return
21
21
 
22
22
  base_pipeline = [
23
- {'$match': {'resources': {'$gt': []}}},
24
- {'$project': {'resources._id': True,
25
- 'resources.extras.check:date': True}},
26
- {'$unwind': '$resources'},
23
+ {"$match": {"resources": {"$gt": []}}},
24
+ {"$project": {"resources._id": True, "resources.extras.check:date": True}},
25
+ {"$unwind": "$resources"},
27
26
  ]
28
27
  # unchecked resources
29
28
  pipeline = base_pipeline + [
30
- {'$match': {'resources.extras.check:date': {'$eq': None}}},
31
- {'$limit': number}
29
+ {"$match": {"resources.extras.check:date": {"$eq": None}}},
30
+ {"$limit": number},
32
31
  ]
33
32
  resources = list(Dataset.objects.aggregate(*pipeline))
34
33
  # not recently checked resources
35
34
  slots_left = number - len(resources)
36
35
  if slots_left:
37
36
  pipeline = base_pipeline + [
38
- {'$match': {'resources.extras.check:date': {'$ne': None}}},
39
- {'$sort': {'resources.extras.check:date': 1}},
40
- {'$limit': slots_left}
37
+ {"$match": {"resources.extras.check:date": {"$ne": None}}},
38
+ {"$sort": {"resources.extras.check:date": 1}},
39
+ {"$limit": slots_left},
41
40
  ]
42
41
  resources += list(Dataset.objects.aggregate(*pipeline))
43
42
 
44
43
  nb_resources = len(resources)
45
- log.info('Checking %s resources...', nb_resources)
44
+ log.info("Checking %s resources...", nb_resources)
46
45
  for idx, dataset_resource in enumerate(resources):
47
- dataset_obj = Dataset.objects.get(id=dataset_resource['_id'])
48
- resource_id = dataset_resource['resources']['_id']
46
+ dataset_obj = Dataset.objects.get(id=dataset_resource["_id"])
47
+ resource_id = dataset_resource["resources"]["_id"]
49
48
  rid = uuid.UUID(resource_id)
50
- resource_obj = get_by(dataset_obj.resources, 'id', rid)
51
- log.info('Checking resource %s (%s/%s)',
52
- resource_id, idx + 1, nb_resources)
49
+ resource_obj = get_by(dataset_obj.resources, "id", rid)
50
+ log.info("Checking resource %s (%s/%s)", resource_id, idx + 1, nb_resources)
53
51
  if resource_obj.need_check():
54
52
  check_resource(resource_obj)
55
53
  else:
56
54
  log.info("--> Skipping this resource, cache is fresh enough.")
57
- log.info('Done.')
55
+ log.info("Done.")
udata/mail.py CHANGED
@@ -1,25 +1,23 @@
1
1
  import logging
2
2
  from contextlib import contextmanager
3
+ from smtplib import SMTPException
3
4
 
4
5
  from blinker import signal
5
-
6
6
  from flask import current_app, render_template
7
7
  from flask_mail import Mail, Message
8
8
 
9
- from smtplib import SMTPException
10
-
11
9
  from udata import i18n
12
10
 
13
-
14
11
  log = logging.getLogger(__name__)
15
12
 
16
13
  mail = Mail()
17
14
 
18
- mail_sent = signal('mail-sent')
15
+ mail_sent = signal("mail-sent")
19
16
 
20
17
 
21
18
  class FakeMailer(object):
22
- '''Display sent mail in logging output'''
19
+ """Display sent mail in logging output"""
20
+
23
21
  def send(self, msg):
24
22
  log.debug(msg.body)
25
23
  log.debug(msg.html)
@@ -37,37 +35,39 @@ def init_app(app):
37
35
 
38
36
 
39
37
  def send(subject, recipients, template_base, **kwargs):
40
- '''
38
+ """
41
39
  Send a given email to multiple recipients.
42
40
 
43
41
  User prefered language is taken in account.
44
42
  To translate the subject in the right language, you should ugettext_lazy
45
- '''
46
- sender = kwargs.pop('sender', None)
43
+ """
44
+ sender = kwargs.pop("sender", None)
47
45
  if not isinstance(recipients, (list, tuple)):
48
46
  recipients = [recipients]
49
47
 
50
- tpl_path = f'mail/{template_base}'
48
+ tpl_path = f"mail/{template_base}"
51
49
 
52
- debug = current_app.config.get('DEBUG', False)
53
- send_mail = current_app.config.get('SEND_MAIL', not debug)
50
+ debug = current_app.config.get("DEBUG", False)
51
+ send_mail = current_app.config.get("SEND_MAIL", not debug)
54
52
  connection = send_mail and mail.connect or dummyconnection
55
53
 
56
54
  with connection() as conn:
57
55
  for recipient in recipients:
58
56
  lang = i18n._default_lang(recipient)
59
57
  with i18n.language(lang):
60
- log.debug(
61
- 'Sending mail "%s" to recipient "%s"', subject, recipient)
62
- msg = Message(subject, sender=sender,
63
- recipients=[recipient.email])
58
+ log.debug('Sending mail "%s" to recipient "%s"', subject, recipient)
59
+ msg = Message(subject, sender=sender, recipients=[recipient.email])
64
60
  msg.body = render_template(
65
- f'{tpl_path}.txt', subject=subject,
66
- sender=sender, recipient=recipient, **kwargs)
61
+ f"{tpl_path}.txt", subject=subject, sender=sender, recipient=recipient, **kwargs
62
+ )
67
63
  msg.html = render_template(
68
- f'{tpl_path}.html', subject=subject,
69
- sender=sender, recipient=recipient, **kwargs)
64
+ f"{tpl_path}.html",
65
+ subject=subject,
66
+ sender=sender,
67
+ recipient=recipient,
68
+ **kwargs,
69
+ )
70
70
  try:
71
71
  conn.send(msg)
72
72
  except SMTPException as e:
73
- log.error(f'Error sending mail {e}')
73
+ log.error(f"Error sending mail {e}")
@@ -1,8 +1,9 @@
1
- '''
1
+ """
2
2
  The purpose here is to change the scopes attribute of
3
3
  the OAuth2Client to scope without the s, then
4
4
  to turn the list into a string.
5
- '''
5
+ """
6
+
6
7
  import logging
7
8
 
8
9
  from mongoengine.connection import get_db
@@ -11,15 +12,15 @@ log = logging.getLogger(__name__)
11
12
 
12
13
 
13
14
  def migrate(db):
14
- log.info('Processing OAuth2Client objects.')
15
+ log.info("Processing OAuth2Client objects.")
15
16
 
16
17
  db = get_db()
17
18
  oauth_clients = db.oauth2_client
18
- oauth_clients.update_many({}, {'$rename': {'scopes': 'scope'}})
19
+ oauth_clients.update_many({}, {"$rename": {"scopes": "scope"}})
19
20
  for client in oauth_clients.find():
20
- if type(client['scope']) == list:
21
- scope_str = ' '.join(client['scope'])
22
- client['scope'] = scope_str
21
+ if type(client["scope"]) == list:
22
+ scope_str = " ".join(client["scope"])
23
+ client["scope"] = scope_str
23
24
  oauth_clients.save(client)
24
25
 
25
- log.info('Completed.')
26
+ log.info("Completed.")
@@ -1,17 +1,18 @@
1
- '''
1
+ """
2
2
  The purpose here is to fill every resource with a fs_filename string field.
3
- '''
3
+ """
4
+
4
5
  import logging
5
6
  from urllib.parse import urlparse
6
7
 
7
8
  from udata.core import storages
8
- from udata.models import Dataset, CommunityResource
9
+ from udata.models import CommunityResource, Dataset
9
10
 
10
11
  log = logging.getLogger(__name__)
11
12
 
12
13
 
13
14
  def migrate(db):
14
- log.info('Processing resources.')
15
+ log.info("Processing resources.")
15
16
 
16
17
  datasets = Dataset.objects().no_cache().timeout(False)
17
18
  for dataset in datasets:
@@ -19,7 +20,7 @@ def migrate(db):
19
20
  for resource in dataset.resources:
20
21
  if resource.url.startswith(storages.resources.base_url):
21
22
  parsed = urlparse(resource.url)
22
- fs_name = parsed.path.replace('/resources/', '')
23
+ fs_name = parsed.path.replace("/resources/", "")
23
24
  resource.fs_filename = fs_name
24
25
  save_res = True
25
26
  elif resource.fs_filename is not None:
@@ -32,14 +33,14 @@ def migrate(db):
32
33
  log.warning(e)
33
34
  pass
34
35
 
35
- log.info('Processing community resources.')
36
+ log.info("Processing community resources.")
36
37
 
37
38
  community_resources = CommunityResource.objects().no_cache().timeout(False)
38
39
  for community_resource in community_resources:
39
40
  save_res = False
40
41
  if community_resource.url.startswith(storages.resources.base_url):
41
42
  parsed = urlparse(community_resource.url)
42
- fs_name = parsed.path.replace('/resources/', '')
43
+ fs_name = parsed.path.replace("/resources/", "")
43
44
  community_resource.fs_filename = fs_name
44
45
  save_res = True
45
46
  elif community_resource.fs_filename is not None:
@@ -52,4 +53,4 @@ def migrate(db):
52
53
  log.warning(e)
53
54
  pass
54
55
 
55
- log.info('Completed.')
56
+ log.info("Completed.")
@@ -1,7 +1,8 @@
1
- '''
1
+ """
2
2
  The purpose here is to update every reuse's datasets metrics
3
3
  after the PR https://github.com/opendatateam/udata/pull/2531
4
- '''
4
+ """
5
+
5
6
  import logging
6
7
 
7
8
  from udata.models import Reuse
@@ -10,10 +11,10 @@ log = logging.getLogger(__name__)
10
11
 
11
12
 
12
13
  def migrate(db):
13
- log.info('Processing reuses.')
14
+ log.info("Processing reuses.")
14
15
 
15
16
  reuses = Reuse.objects().no_cache().timeout(False)
16
17
  for reuse in reuses:
17
18
  reuse.count_datasets()
18
19
 
19
- log.info('Completed.')
20
+ log.info("Completed.")
@@ -1,27 +1,26 @@
1
- '''
1
+ """
2
2
  Migrate ODS harvested resources URLS from
3
3
  use_labels_for_header=true to use_labels_for_header=false
4
4
  cf https://github.com/opendatateam/udata-ods/pull/169
5
- '''
5
+ """
6
+
6
7
  import logging
7
8
 
8
9
  from mongoengine.errors import ValidationError
10
+
9
11
  from udata.models import Dataset
10
12
 
11
13
  log = logging.getLogger(__name__)
12
14
 
13
- MIX_MATCH = [
14
- 'use_labels_for_header=true',
15
- 'use_labels_for_header=false'
16
- ]
15
+ MIX_MATCH = ["use_labels_for_header=true", "use_labels_for_header=false"]
17
16
 
18
17
 
19
18
  def migrate(db):
20
- log.info('Migrating ODS harvest datasets...')
19
+ log.info("Migrating ODS harvest datasets...")
21
20
 
22
21
  count = 0
23
22
  # datasets from ODS
24
- datasets = Dataset.objects.filter(**{'extras__ods:url__ne': None})
23
+ datasets = Dataset.objects.filter(**{"extras__ods:url__ne": None})
25
24
  for d in datasets:
26
25
  touched = False
27
26
  for r in d.resources:
@@ -33,6 +32,6 @@ def migrate(db):
33
32
  try:
34
33
  d.save()
35
34
  except ValidationError as e:
36
- log.warning(f'Error while saving dataset {d.id}: {str(e)}')
35
+ log.warning(f"Error while saving dataset {d.id}: {str(e)}")
37
36
 
38
- log.info(f'Completed, {count} resources migrated.')
37
+ log.info(f"Completed, {count} resources migrated.")
@@ -1,7 +1,8 @@
1
- '''
1
+ """
2
2
  The purpose here is to update every resource's metadata 'schema'
3
3
  with a new format (string to object)
4
- '''
4
+ """
5
+
5
6
  import logging
6
7
 
7
8
  from udata.models import Dataset
@@ -10,17 +11,17 @@ log = logging.getLogger(__name__)
10
11
 
11
12
 
12
13
  def migrate(db):
13
- log.info('Processing resources.')
14
+ log.info("Processing resources.")
14
15
 
15
16
  datasets = Dataset.objects().no_cache().timeout(False)
16
17
  for dataset in datasets:
17
18
  save_res = False
18
19
  for resource in dataset.resources:
19
- if hasattr(resource, 'schema'):
20
+ if hasattr(resource, "schema"):
20
21
  schema = resource.schema
21
- resource.schema = {'name': None}
22
+ resource.schema = {"name": None}
22
23
  if schema is not None and isinstance(schema, str):
23
- resource.schema = {'name': schema}
24
+ resource.schema = {"name": schema}
24
25
  save_res = True
25
26
  if save_res:
26
27
  try:
@@ -29,4 +30,4 @@ def migrate(db):
29
30
  log.warning(e)
30
31
  pass
31
32
 
32
- log.info('Completed.')
33
+ log.info("Completed.")
@@ -1,6 +1,7 @@
1
- '''
1
+ """
2
2
  The purpose here is to update every resource's metadata 'schema' name.
3
- '''
3
+ """
4
+
4
5
  import logging
5
6
 
6
7
  from udata.models import Dataset
@@ -9,15 +10,15 @@ log = logging.getLogger(__name__)
9
10
 
10
11
 
11
12
  def migrate(db):
12
- log.info('Processing resources.')
13
+ log.info("Processing resources.")
13
14
 
14
15
  datasets = Dataset.objects().no_cache().timeout(False)
15
16
  for dataset in datasets:
16
17
  save_res = False
17
18
  for resource in dataset.resources:
18
- if hasattr(resource, 'schema'):
19
+ if hasattr(resource, "schema"):
19
20
  for key, value in resource.schema.items():
20
- if key == 'name' and value is None:
21
+ if key == "name" and value is None:
21
22
  resource.schema = {}
22
23
  save_res = True
23
24
  if save_res:
@@ -27,4 +28,4 @@ def migrate(db):
27
28
  log.warning(e)
28
29
  pass
29
30
 
30
- log.info('Completed.')
31
+ log.info("Completed.")
@@ -1,27 +1,29 @@
1
- '''
1
+ """
2
2
  The purpose here is to update every resource's metadata 'schema' name.
3
- '''
3
+ """
4
+
4
5
  import logging
5
- from udata.core.reuse.models import Reuse
6
6
 
7
+ from udata.core.reuse.models import Reuse
7
8
  from udata.models import Dataset, Reuse
8
9
 
9
10
  log = logging.getLogger(__name__)
10
11
 
11
12
  UNUSED_BADGES = [
12
- 'dataconnexions-5-candidate',
13
- 'dataconnexions-5-laureate',
14
- 'dataconnexions-6-candidate',
15
- 'dataconnexions-6-laureate',
16
- 'covid-19',
17
- 'c3',
18
- 'nec',
19
- 'openfield16',
20
- 'bal'
13
+ "dataconnexions-5-candidate",
14
+ "dataconnexions-5-laureate",
15
+ "dataconnexions-6-candidate",
16
+ "dataconnexions-6-laureate",
17
+ "covid-19",
18
+ "c3",
19
+ "nec",
20
+ "openfield16",
21
+ "bal",
21
22
  ]
22
23
 
24
+
23
25
  def migrate(db):
24
- log.info('Processing datasets.')
26
+ log.info("Processing datasets.")
25
27
 
26
28
  datasets = Dataset.objects().no_cache().timeout(False)
27
29
  for dataset in datasets:
@@ -29,7 +31,7 @@ def migrate(db):
29
31
  if dataset.get_badge(badge):
30
32
  dataset.remove_badge(badge)
31
33
 
32
- log.info('Processing reuses.')
34
+ log.info("Processing reuses.")
33
35
 
34
36
  reuses = Reuse.objects().no_cache().timeout(False)
35
37
  for reuse in reuses:
@@ -37,4 +39,4 @@ def migrate(db):
37
39
  if reuse.get_badge(badge):
38
40
  reuse.remove_badge(badge)
39
41
 
40
- log.info('Completed.')
42
+ log.info("Completed.")
@@ -1,7 +1,8 @@
1
- '''
1
+ """
2
2
  The purpose here is to update every community resource's metadata 'schema'
3
3
  with a new format (string to object)
4
- '''
4
+ """
5
+
5
6
  import logging
6
7
 
7
8
  from udata.models import CommunityResource
@@ -10,16 +11,16 @@ log = logging.getLogger(__name__)
10
11
 
11
12
 
12
13
  def migrate(db):
13
- log.info('Processing community resources.')
14
+ log.info("Processing community resources.")
14
15
 
15
16
  community_resources = CommunityResource.objects().no_cache().timeout(False)
16
17
  for resource in community_resources:
17
18
  save_res = False
18
- if hasattr(resource, 'schema'):
19
+ if hasattr(resource, "schema"):
19
20
  schema = resource.schema
20
21
  resource.schema = {}
21
22
  if schema is not None and isinstance(schema, str):
22
- resource.schema = {'name': schema}
23
+ resource.schema = {"name": schema}
23
24
  save_res = True
24
25
  if save_res:
25
26
  try:
@@ -28,4 +29,4 @@ def migrate(db):
28
29
  log.warning(e)
29
30
  pass
30
31
 
31
- log.info('Completed.')
32
+ log.info("Completed.")
@@ -1,7 +1,8 @@
1
- '''
1
+ """
2
2
  Remove Follow integrity problems
3
3
  ⚠️ long migration
4
- '''
4
+ """
5
+
5
6
  import logging
6
7
 
7
8
  import mongoengine
@@ -12,7 +13,7 @@ log = logging.getLogger(__name__)
12
13
 
13
14
 
14
15
  def migrate(db):
15
- log.info('Processing Follow references.')
16
+ log.info("Processing Follow references.")
16
17
 
17
18
  count = 0
18
19
  follows = Follow.objects(following__ne=None).no_cache().all()
@@ -23,4 +24,4 @@ def migrate(db):
23
24
  count += 1
24
25
  follow.delete()
25
26
 
26
- log.info(f'Delete {count} Follow objects')
27
+ log.info(f"Delete {count} Follow objects")