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
udata/commands/db.py CHANGED
@@ -1,87 +1,85 @@
1
1
  import collections
2
- from itertools import groupby
3
2
  import logging
4
3
  import os
5
4
  import traceback
5
+ from itertools import groupby
6
6
 
7
- from bson import DBRef
8
7
  import click
9
8
  import mongoengine
9
+ from bson import DBRef
10
10
 
11
- from udata import migrations, models as core_models
11
+ from udata import migrations
12
+ from udata import models as core_models
12
13
  from udata.api import oauth2 as oauth2_models
13
- from udata.commands import cli, green, yellow, cyan, red, magenta, white, echo
14
+ from udata.commands import cli, cyan, echo, green, magenta, red, white, yellow
14
15
  from udata.harvest import models as harvest_models
15
16
  from udata.mongo import db
16
17
 
17
-
18
18
  # Date format used to for display
19
- DATE_FORMAT = '%Y-%m-%d %H:%M'
19
+ DATE_FORMAT = "%Y-%m-%d %H:%M"
20
20
 
21
21
  log = logging.getLogger(__name__)
22
22
 
23
23
 
24
- @cli.group('db')
24
+ @cli.group("db")
25
25
  def grp():
26
- '''Database related operations'''
26
+ """Database related operations"""
27
27
  pass
28
28
 
29
29
 
30
30
  def log_status(migration, status):
31
- '''Properly display a migration status line'''
31
+ """Properly display a migration status line"""
32
32
  name = os.path.splitext(migration.filename)[0]
33
- display = ':'.join((migration.plugin, name)) + ' '
34
- log.info('%s [%s]', '{:.<70}'.format(display), status)
33
+ display = ":".join((migration.plugin, name)) + " "
34
+ log.info("%s [%s]", "{:.<70}".format(display), status)
35
35
 
36
36
 
37
37
  def status_label(record):
38
38
  if record.ok:
39
39
  return green(record.last_date.strftime(DATE_FORMAT))
40
40
  elif not record.exists():
41
- return yellow('Not applied')
41
+ return yellow("Not applied")
42
42
  else:
43
43
  return red(record.status)
44
44
 
45
45
 
46
46
  def format_output(output, success=True, traceback=None):
47
- echo('')
47
+ echo("")
48
48
  for level, msg in output:
49
- echo(' │ {0}'.format(msg))
50
- echo('')
49
+ echo(" │ {0}".format(msg))
50
+ echo("")
51
51
  if traceback:
52
- for tb in traceback.split('\n'):
53
- echo(' │ {0}'.format(tb))
54
- echo('')
55
- echo(' └──[{0}]'.format(green('OK') if success else red('KO')))
56
- echo('')
52
+ for tb in traceback.split("\n"):
53
+ echo(" │ {0}".format(tb))
54
+ echo("")
55
+ echo(" └──[{0}]".format(green("OK") if success else red("KO")))
56
+ echo("")
57
57
 
58
58
 
59
59
  @grp.command()
60
60
  def status():
61
- '''Display the database migrations status'''
61
+ """Display the database migrations status"""
62
62
  for migration in migrations.list_available():
63
63
  log_status(migration, status_label(migration.record))
64
64
 
65
65
 
66
66
  @grp.command()
67
- @click.option('-r', '--record', is_flag=True,
68
- help='Only records the migrations')
69
- @click.option('-d', '--dry-run', is_flag=True,
70
- help='Only print migrations to be applied')
67
+ @click.option("-r", "--record", is_flag=True, help="Only records the migrations")
68
+ @click.option("-d", "--dry-run", is_flag=True, help="Only print migrations to be applied")
71
69
  def migrate(record, dry_run=False):
72
- '''Perform database migrations'''
70
+ """Perform database migrations"""
73
71
  success = True
74
72
  for migration in migrations.list_available():
75
73
  if migration.record.ok or not success:
76
- log_status(migration, cyan('Skipped'))
74
+ log_status(migration, cyan("Skipped"))
77
75
  else:
78
- status = magenta('Recorded') if record else yellow('Apply')
76
+ status = magenta("Recorded") if record else yellow("Apply")
79
77
  log_status(migration, status)
80
78
  try:
81
79
  output = migration.execute(recordonly=record, dryrun=dry_run)
82
80
  except migrations.RollbackError as re:
83
81
  format_output(re.migrate_exc.output, False)
84
- log_status(migration, red('Rollback'))
82
+ log_status(migration, red("Rollback"))
85
83
  format_output(re.output, not re.exc)
86
84
  success = False
87
85
  except migrations.MigrationError as me:
@@ -93,10 +91,10 @@ def migrate(record, dry_run=False):
93
91
 
94
92
 
95
93
  @grp.command()
96
- @click.argument('plugin_or_specs')
97
- @click.argument('filename', default=None, required=False, metavar='[FILENAME]')
94
+ @click.argument("plugin_or_specs")
95
+ @click.argument("filename", default=None, required=False, metavar="[FILENAME]")
98
96
  def unrecord(plugin_or_specs, filename):
99
- '''
97
+ """
100
98
  Remove a database migration record.
101
99
 
102
100
  \b
@@ -105,155 +103,202 @@ def unrecord(plugin_or_specs, filename):
105
103
  - plugin filename.js
106
104
  - plugin:filename
107
105
  - plugin:fliename.js
108
- '''
106
+ """
109
107
  migration = migrations.get(plugin_or_specs, filename)
110
108
  removed = migration.unrecord()
111
109
  if removed:
112
- log.info('Removed migration %s', migration.label)
110
+ log.info("Removed migration %s", migration.label)
113
111
  else:
114
- log.error('Migration not found %s', migration.label)
112
+ log.error("Migration not found %s", migration.label)
115
113
 
116
114
 
117
115
  @grp.command()
118
- @click.argument('plugin_or_specs')
119
- @click.argument('filename', default=None, required=False, metavar='[FILENAME]')
116
+ @click.argument("plugin_or_specs")
117
+ @click.argument("filename", default=None, required=False, metavar="[FILENAME]")
120
118
  def info(plugin_or_specs, filename):
121
- '''
119
+ """
122
120
  Display detailed info about a migration
123
- '''
121
+ """
124
122
  migration = migrations.get(plugin_or_specs, filename)
125
123
  log_status(migration, status_label(migration.record))
126
124
  try:
127
125
  echo(migration.module.__doc__)
128
126
  except migrations.MigrationError:
129
- echo(yellow('Module not found'))
127
+ echo(yellow("Module not found"))
130
128
 
131
- for op in migration.record.get('ops', []):
129
+ for op in migration.record.get("ops", []):
132
130
  display_op(op)
133
131
 
134
132
 
135
133
  def display_op(op):
136
- timestamp = white(op['date'].strftime(DATE_FORMAT))
137
- label = white(op['type'].title()) + ' '
138
- echo('{label:.<70} [{date}]'.format(label=label, date=timestamp))
139
- format_output(op['output'], success=op['success'], traceback=op.get('traceback'))
134
+ timestamp = white(op["date"].strftime(DATE_FORMAT))
135
+ label = white(op["type"].title()) + " "
136
+ echo("{label:.<70} [{date}]".format(label=label, date=timestamp))
137
+ format_output(op["output"], success=op["success"], traceback=op.get("traceback"))
138
+
140
139
 
141
140
  def check_references(models_to_check):
142
141
  # Cannot modify local scope from Python… :-(
143
- class Log: errors = []
142
+ class Log:
143
+ errors = []
144
144
 
145
145
  def print_and_save(text: str):
146
146
  Log.errors.append(text.strip())
147
- print(text)
147
+ print(text)
148
148
 
149
149
  errors = collections.defaultdict(int)
150
150
 
151
151
  _models = []
152
152
  for models in core_models, harvest_models, oauth2_models:
153
153
  _models += [
154
- elt for _, elt in models.__dict__.items()
154
+ elt
155
+ for _, elt in models.__dict__.items()
155
156
  if isinstance(elt, type) and issubclass(elt, (db.Document))
156
157
  ]
157
158
 
158
159
  references = []
159
160
  for model in set(_models):
160
- if model.__name__ == 'Activity':
161
- print(f'Skipping Activity model, scheduled for deprecation')
161
+ if model.__name__ == "Activity":
162
+ print(f"Skipping Activity model, scheduled for deprecation")
162
163
  continue
163
- if model.__name__ == 'GeoLevel':
164
- print(f'Skipping GeoLevel model, scheduled for deprecation')
164
+ if model.__name__ == "GeoLevel":
165
+ print(f"Skipping GeoLevel model, scheduled for deprecation")
165
166
  continue
166
167
 
167
168
  if models_to_check and model.__name__ not in models_to_check:
168
169
  continue
169
170
 
170
171
  # find "root" ReferenceField fields
171
- refs = [elt for elt in model._fields.values()
172
- if isinstance(elt, mongoengine.fields.ReferenceField)]
173
- references += [{
174
- 'model': model,
175
- 'repr': f'{model.__name__}.{r.name}',
176
- 'name': r.name,
177
- 'destination': r.document_type.__name__,
178
- 'type': 'direct',
179
- } for r in refs]
172
+ refs = [
173
+ elt
174
+ for elt in model._fields.values()
175
+ if isinstance(elt, mongoengine.fields.ReferenceField)
176
+ ]
177
+ references += [
178
+ {
179
+ "model": model,
180
+ "repr": f"{model.__name__}.{r.name}",
181
+ "name": r.name,
182
+ "destination": r.document_type.__name__,
183
+ "type": "direct",
184
+ }
185
+ for r in refs
186
+ ]
180
187
 
181
188
  # find "root" GenericReferenceField
182
- refs = [elt for elt in model._fields.values()
183
- if isinstance(elt, mongoengine.fields.GenericReferenceField)]
184
- references += [{
185
- 'model': model,
186
- 'repr': f'{model.__name__}.{r.name}',
187
- 'name': r.name,
188
- 'destination': 'Generic',
189
- 'type': 'direct',
190
- } for r in refs]
189
+ refs = [
190
+ elt
191
+ for elt in model._fields.values()
192
+ if isinstance(elt, mongoengine.fields.GenericReferenceField)
193
+ ]
194
+ references += [
195
+ {
196
+ "model": model,
197
+ "repr": f"{model.__name__}.{r.name}",
198
+ "name": r.name,
199
+ "destination": "Generic",
200
+ "type": "direct",
201
+ }
202
+ for r in refs
203
+ ]
191
204
 
192
205
  # find ListField with ReferenceField
193
- list_fields = [elt for elt in model._fields.values()
194
- if isinstance(elt, mongoengine.fields.ListField)]
195
- list_refs = [elt for elt in list_fields
196
- if isinstance(elt.field, mongoengine.fields.ReferenceField)]
197
- references += [{
198
- 'model': model,
199
- 'repr': f'{model.__name__}.{lr.name}',
200
- 'name': lr.name,
201
- 'destination': lr.field.document_type.__name__,
202
- 'type': 'list',
203
- } for lr in list_refs]
206
+ list_fields = [
207
+ elt for elt in model._fields.values() if isinstance(elt, mongoengine.fields.ListField)
208
+ ]
209
+ list_refs = [
210
+ elt for elt in list_fields if isinstance(elt.field, mongoengine.fields.ReferenceField)
211
+ ]
212
+ references += [
213
+ {
214
+ "model": model,
215
+ "repr": f"{model.__name__}.{lr.name}",
216
+ "name": lr.name,
217
+ "destination": lr.field.document_type.__name__,
218
+ "type": "list",
219
+ }
220
+ for lr in list_refs
221
+ ]
204
222
 
205
223
  # find ListField w/ EmbeddedDocumentField w/ ReferenceField
206
- list_embeds = [(elt, elt.field) for elt in list_fields
207
- if isinstance(elt.field, mongoengine.fields.EmbeddedDocumentField)]
224
+ list_embeds = [
225
+ (elt, elt.field)
226
+ for elt in list_fields
227
+ if isinstance(elt.field, mongoengine.fields.EmbeddedDocumentField)
228
+ ]
208
229
  for embed, embed_field in list_embeds:
209
- embed_refs = [elt for elt in embed_field.document_type_obj._fields.values()
210
- if isinstance(elt, mongoengine.fields.ReferenceField)]
211
- references += [{
212
- 'model': model,
213
- 'repr': f'{model.__name__}.{embed.name}__{er.name}',
214
- 'name': f'{embed.name}__{er.name}',
215
- 'destination': er.document_type.__name__,
216
- 'type': 'embed_list',
217
- } for er in embed_refs]
230
+ embed_refs = [
231
+ elt
232
+ for elt in embed_field.document_type_obj._fields.values()
233
+ if isinstance(elt, mongoengine.fields.ReferenceField)
234
+ ]
235
+ references += [
236
+ {
237
+ "model": model,
238
+ "repr": f"{model.__name__}.{embed.name}__{er.name}",
239
+ "name": f"{embed.name}__{er.name}",
240
+ "destination": er.document_type.__name__,
241
+ "type": "embed_list",
242
+ }
243
+ for er in embed_refs
244
+ ]
218
245
 
219
246
  # find EmbeddedDocumentField w/ ReferenceField
220
- embeds = [elt for elt in model._fields.values()
221
- if isinstance(elt, mongoengine.fields.EmbeddedDocumentField)]
247
+ embeds = [
248
+ elt
249
+ for elt in model._fields.values()
250
+ if isinstance(elt, mongoengine.fields.EmbeddedDocumentField)
251
+ ]
222
252
  for embed_field in embeds:
223
- embed_refs = [elt for elt in embed_field.document_type_obj._fields.values()
224
- if isinstance(elt, mongoengine.fields.ReferenceField)]
225
- references += [{
226
- 'model': model,
227
- 'repr': f'{model.__name__}.{embed_field.name}__{er.name}',
228
- 'name': f'{embed_field.name}__{er.name}',
229
- 'destination': er.document_type.__name__,
230
- 'type': 'embed',
231
- } for er in embed_refs]
253
+ embed_refs = [
254
+ elt
255
+ for elt in embed_field.document_type_obj._fields.values()
256
+ if isinstance(elt, mongoengine.fields.ReferenceField)
257
+ ]
258
+ references += [
259
+ {
260
+ "model": model,
261
+ "repr": f"{model.__name__}.{embed_field.name}__{er.name}",
262
+ "name": f"{embed_field.name}__{er.name}",
263
+ "destination": er.document_type.__name__,
264
+ "type": "embed",
265
+ }
266
+ for er in embed_refs
267
+ ]
232
268
 
233
269
  # find EmbeddedDocumentField w/ ListField w/ ReferenceField
234
270
  for embed_field in embeds:
235
- embed_lists = [elt for elt in embed_field.document_type_obj._fields.values()
236
- if isinstance(elt, mongoengine.fields.ListField)]
237
- elists_refs = [elt for elt in embed_lists
238
- if isinstance(elt.field, mongoengine.fields.ReferenceField)]
239
- references += [{
240
- 'model': model,
241
- 'repr': f'{model.__name__}.{embed_field.name}__{lr.name}',
242
- 'name': f'{embed_field.name}__{lr.name}',
243
- 'destination': lr.field.document_type.__name__,
244
- 'type': 'embed_list_ref',
245
- } for lr in elists_refs]
246
-
247
- print('Those references will be inspected:')
271
+ embed_lists = [
272
+ elt
273
+ for elt in embed_field.document_type_obj._fields.values()
274
+ if isinstance(elt, mongoengine.fields.ListField)
275
+ ]
276
+ elists_refs = [
277
+ elt
278
+ for elt in embed_lists
279
+ if isinstance(elt.field, mongoengine.fields.ReferenceField)
280
+ ]
281
+ references += [
282
+ {
283
+ "model": model,
284
+ "repr": f"{model.__name__}.{embed_field.name}__{lr.name}",
285
+ "name": f"{embed_field.name}__{lr.name}",
286
+ "destination": lr.field.document_type.__name__,
287
+ "type": "embed_list_ref",
288
+ }
289
+ for lr in elists_refs
290
+ ]
291
+
292
+ print("Those references will be inspected:")
248
293
  for reference in references:
249
294
  print(f'- {reference["repr"]}({reference["destination"]}) — {reference["type"]}')
250
- print('')
295
+ print("")
251
296
 
252
297
  total = 0
253
298
  for model, model_references in groupby(references, lambda i: i["model"]):
254
299
  model_references = list(model_references)
255
300
  count = model.objects.count()
256
- print(f'- doing {count} {model.__name__}…')
301
+ print(f"- doing {count} {model.__name__}…")
257
302
  errors[model] = {}
258
303
 
259
304
  qs = model.objects().no_cache().all()
@@ -265,71 +310,87 @@ def check_references(models_to_check):
265
310
  errors[model][key] = 0
266
311
 
267
312
  try:
268
- if reference['type'] == 'direct':
313
+ if reference["type"] == "direct":
269
314
  try:
270
- _ = getattr(obj, reference['name'])
315
+ _ = getattr(obj, reference["name"])
271
316
  except mongoengine.errors.DoesNotExist:
272
317
  errors[model][key] += 1
273
- print_and_save(f'\t{model.__name__}#{obj.id} have a broken reference for `{reference["name"]}`')
274
- elif reference['type'] == 'list':
275
- attr_list = getattr(obj, reference['name'], [])
318
+ print_and_save(
319
+ f'\t{model.__name__}#{obj.id} have a broken reference for `{reference["name"]}`'
320
+ )
321
+ elif reference["type"] == "list":
322
+ attr_list = getattr(obj, reference["name"], [])
276
323
  for i, sub in enumerate(attr_list):
277
324
  # If it's still an instance of DBRef it means that it failed to
278
325
  # dereference the ID.
279
326
  if isinstance(sub, DBRef):
280
327
  errors[model][key] += 1
281
- print_and_save(f'\t{model.__name__}#{obj.id} have a broken reference for {reference["name"]}[{i}]')
282
- elif reference['type'] == 'embed_list':
283
- p1, p2 = reference['name'].split('__')
328
+ print_and_save(
329
+ f'\t{model.__name__}#{obj.id} have a broken reference for {reference["name"]}[{i}]'
330
+ )
331
+ elif reference["type"] == "embed_list":
332
+ p1, p2 = reference["name"].split("__")
284
333
  attr_list = getattr(obj, p1, [])
285
334
  for i, sub in enumerate(attr_list):
286
335
  try:
287
336
  getattr(sub, p2)
288
337
  except mongoengine.errors.DoesNotExist:
289
338
  errors[model][key] += 1
290
- print_and_save(f'\t{model.__name__}#{obj.id} have a broken reference for {p1}[{i}].{p2}')
291
- elif reference['type'] == 'embed':
292
- p1, p2 = reference['name'].split('__')
339
+ print_and_save(
340
+ f"\t{model.__name__}#{obj.id} have a broken reference for {p1}[{i}].{p2}"
341
+ )
342
+ elif reference["type"] == "embed":
343
+ p1, p2 = reference["name"].split("__")
293
344
  sub = getattr(obj, p1)
294
- if sub is None: continue
345
+ if sub is None:
346
+ continue
295
347
  try:
296
348
  getattr(sub, p2)
297
349
  except mongoengine.errors.DoesNotExist:
298
350
  errors[model][key] += 1
299
- print_and_save(f'\t{model.__name__}#{obj.id} have a broken reference for {p1}.{p2}')
300
- elif reference['type'] == 'embed_list_ref':
301
- p1, p2 = reference['name'].split('__')
351
+ print_and_save(
352
+ f"\t{model.__name__}#{obj.id} have a broken reference for {p1}.{p2}"
353
+ )
354
+ elif reference["type"] == "embed_list_ref":
355
+ p1, p2 = reference["name"].split("__")
302
356
  a = getattr(obj, p1)
303
- if a is None: continue
357
+ if a is None:
358
+ continue
304
359
  sub = getattr(a, p2, [])
305
360
  for i, child in enumerate(sub):
306
361
  # If it's still an instance of DBRef it means that it failed to
307
362
  # dereference the ID.
308
363
  if isinstance(child, DBRef):
309
364
  errors[model][key] += 1
310
- print_and_save(f'\t{model.__name__}#{obj.id} have a broken reference for {p1}.{p2}[{i}]')
365
+ print_and_save(
366
+ f"\t{model.__name__}#{obj.id} have a broken reference for {p1}.{p2}[{i}]"
367
+ )
311
368
  else:
312
369
  print_and_save(f'Unknown ref type {reference["type"]}')
313
370
  except mongoengine.errors.FieldDoesNotExist as e:
314
- print_and_save(f'[ERROR for {model.__name__} {obj.id}] {traceback.format_exc()}')
371
+ print_and_save(
372
+ f"[ERROR for {model.__name__} {obj.id}] {traceback.format_exc()}"
373
+ )
315
374
 
316
375
  for key, nb_errors in errors[model].items():
317
- print(f'{key}: {nb_errors}')
376
+ print(f"{key}: {nb_errors}")
318
377
  total += nb_errors
319
378
 
320
- print(f'\n Total errors: {total}')
379
+ print(f"\n Total errors: {total}")
321
380
 
322
381
  if total > 0:
323
382
  try:
324
383
  import sentry_sdk
384
+
325
385
  with sentry_sdk.push_scope() as scope:
326
386
  scope.set_extra("errors", Log.errors)
327
387
  sentry_sdk.capture_message(f"{total} integrity errors", "fatal")
328
388
  except ImportError:
329
389
  print("`sentry_sdk` not installed. The errors weren't reported")
330
390
 
391
+
331
392
  @grp.command()
332
- @click.option('--models', multiple=True, default=[], help='Model(s) to check')
393
+ @click.option("--models", multiple=True, default=[], help="Model(s) to check")
333
394
  def check_integrity(models):
334
- '''Check the integrity of the database from a business perspective'''
395
+ """Check the integrity of the database from a business perspective"""
335
396
  check_references(models)
udata/commands/dcat.py CHANGED
@@ -2,50 +2,54 @@ import logging
2
2
 
3
3
  import click
4
4
  import mongoengine
5
-
6
5
  from rdflib import Graph
7
6
 
8
- from udata.commands import cli, green, yellow, cyan, echo, magenta
7
+ from udata.commands import cli, cyan, echo, green, magenta, yellow
9
8
  from udata.core.dataset.factories import DatasetFactory
10
9
  from udata.core.dataset.rdf import dataset_from_rdf
11
- from udata.harvest.backends.dcat import DcatBackend, CswDcatBackend, CswIso19139DcatBackend
10
+ from udata.harvest.backends.dcat import (
11
+ CswDcatBackend,
12
+ CswIso19139DcatBackend,
13
+ DcatBackend,
14
+ )
12
15
  from udata.rdf import namespace_manager
13
16
 
14
17
  log = logging.getLogger(__name__)
15
18
 
16
19
 
17
- @cli.group('dcat')
20
+ @cli.group("dcat")
18
21
  def grp():
19
- '''DCAT diagnosis operations'''
22
+ """DCAT diagnosis operations"""
20
23
  pass
21
24
 
22
25
 
23
26
  @grp.command()
24
- @click.argument('url')
25
- @click.option('-q', '--quiet', is_flag=True, help='Ignore warnings')
26
- @click.option('-r', '--rid', help='Inspect specific remote id (contains)')
27
- @click.option('-c', '--csw', is_flag=True, help='The target is a CSW endpoint with DCAT output')
28
- @click.option('-i', '--iso', is_flag=True, help='The target is a CSW endpoint with ISO output')
29
- def parse_url(url, csw, iso, quiet=False, rid=''):
30
- '''Parse the datasets in a DCAT format located at URL (debug)'''
27
+ @click.argument("url")
28
+ @click.option("-q", "--quiet", is_flag=True, help="Ignore warnings")
29
+ @click.option("-r", "--rid", help="Inspect specific remote id (contains)")
30
+ @click.option("-c", "--csw", is_flag=True, help="The target is a CSW endpoint with DCAT output")
31
+ @click.option("-i", "--iso", is_flag=True, help="The target is a CSW endpoint with ISO output")
32
+ def parse_url(url, csw, iso, quiet=False, rid=""):
33
+ """Parse the datasets in a DCAT format located at URL (debug)"""
31
34
  if quiet:
32
- verbose_loggers = ['rdflib', 'udata.core.dataset']
35
+ verbose_loggers = ["rdflib", "udata.core.dataset"]
33
36
  [logging.getLogger(l).setLevel(logging.ERROR) for l in verbose_loggers]
34
37
 
35
38
  class MockSource:
36
- url = ''
39
+ url = ""
37
40
 
38
41
  class MockJob:
39
42
  items = []
40
43
 
41
44
  class MockDatasetFactory(DatasetFactory):
42
- '''Use DatasetFactory without .save()'''
45
+ """Use DatasetFactory without .save()"""
46
+
43
47
  @classmethod
44
48
  def _create(cls, model_class, *args, **kwargs):
45
49
  instance = model_class(*args, **kwargs)
46
50
  return instance
47
51
 
48
- echo(cyan('Parsing url {}'.format(url)))
52
+ echo(cyan("Parsing url {}".format(url)))
49
53
  source = MockSource()
50
54
  source.url = url
51
55
  if csw:
@@ -56,7 +60,7 @@ def parse_url(url, csw, iso, quiet=False, rid=''):
56
60
  backend = DcatBackend(source, dryrun=True)
57
61
  backend.job = MockJob()
58
62
  format = backend.get_format()
59
- echo(yellow('Detected format: {}'.format(format)))
63
+ echo(yellow("Detected format: {}".format(format)))
60
64
  graphs = backend.parse_graph(url, format)
61
65
 
62
66
  # serialize/unserialize graph like in the job mechanism
@@ -68,25 +72,27 @@ def parse_url(url, csw, iso, quiet=False, rid=''):
68
72
 
69
73
  for item in backend.job.items:
70
74
  if not rid or rid in item.remote_id:
71
- echo(magenta('Processing item {}'.format(item.remote_id)))
72
- echo('Item kwargs: {}'.format(yellow(item.kwargs)))
75
+ echo(magenta("Processing item {}".format(item.remote_id)))
76
+ echo("Item kwargs: {}".format(yellow(item.kwargs)))
73
77
  node = backend.get_node_from_item(graph, item)
74
78
  dataset = MockDatasetFactory()
75
79
  dataset = dataset_from_rdf(graph, dataset, node=node)
76
- echo('')
77
- echo(green('Dataset found!'))
78
- echo('Title: {}'.format(yellow(dataset)))
79
- echo('License: {}'.format(yellow(dataset.license)))
80
- echo('Description: {}'.format(yellow(dataset.description)))
81
- echo('Tags: {}'.format(yellow(dataset.tags)))
82
- echo('Resources: {}'.format(yellow(
83
- [(r.title, r.format, r.url) for r in dataset.resources]
84
- )))
80
+ echo("")
81
+ echo(green("Dataset found!"))
82
+ echo("Title: {}".format(yellow(dataset)))
83
+ echo("License: {}".format(yellow(dataset.license)))
84
+ echo("Description: {}".format(yellow(dataset.description)))
85
+ echo("Tags: {}".format(yellow(dataset.tags)))
86
+ echo(
87
+ "Resources: {}".format(
88
+ yellow([(r.title, r.format, r.url) for r in dataset.resources])
89
+ )
90
+ )
85
91
 
86
92
  try:
87
93
  dataset.validate()
88
94
  except mongoengine.errors.ValidationError as e:
89
95
  log.error(e, exc_info=True)
90
96
  else:
91
- echo(green('Dataset is valid ✅'))
92
- echo('')
97
+ echo(green("Dataset is valid ✅"))
98
+ echo("")