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
udata/core/spatial/api.py CHANGED
@@ -1,64 +1,60 @@
1
1
  import re
2
- from mongoengine.queryset.visitor import Q
3
2
 
4
3
  from flask_restx import inputs
4
+ from mongoengine.queryset.visitor import Q
5
5
 
6
- from udata.api import api, API
6
+ from udata.api import API, api
7
+ from udata.core.dataset.api_fields import dataset_ref_fields
7
8
  from udata.i18n import _
8
9
  from udata.models import Dataset
9
- from udata.core.dataset.api_fields import dataset_ref_fields
10
10
 
11
11
  from .api_fields import (
12
- level_fields,
13
- granularity_fields,
14
12
  feature_collection_fields,
15
- zone_suggestion_fields
13
+ granularity_fields,
14
+ level_fields,
15
+ zone_suggestion_fields,
16
16
  )
17
- from .models import GeoZone, GeoLevel, spatial_granularities
17
+ from .models import GeoLevel, GeoZone, spatial_granularities
18
18
 
19
-
20
- GEOM_TYPES = (
21
- 'Point', 'LineString', 'Polygon', 'MultiPoint', 'MultiLineString',
22
- 'MultiPolygon'
23
- )
19
+ GEOM_TYPES = ("Point", "LineString", "Polygon", "MultiPoint", "MultiLineString", "MultiPolygon")
24
20
  LEGACY_GEOID_PATTERN = r"^([a-z]+:[a-z]+:\d+)@(\d{4}-\d{2}-\d{2})$"
25
21
 
26
22
 
27
- ns = api.namespace('spatial', 'Spatial references')
23
+ ns = api.namespace("spatial", "Spatial references")
28
24
 
29
25
 
30
26
  suggest_parser = api.parser()
31
27
  suggest_parser.add_argument(
32
- 'q', type=str, help='The string to autocomplete/suggest',
33
- location='args', required=True)
28
+ "q", type=str, help="The string to autocomplete/suggest", location="args", required=True
29
+ )
34
30
  suggest_parser.add_argument(
35
- 'size', type=int, help='The amount of suggestion to fetch',
36
- location='args', default=10)
31
+ "size", type=int, help="The amount of suggestion to fetch", location="args", default=10
32
+ )
37
33
 
38
34
 
39
35
  def payload_name(name):
40
- '''localize name'''
36
+ """localize name"""
41
37
  return _(name) # Avoid dict quotes in gettext
42
38
 
43
39
 
44
40
  def legacy_geoid(legacy_id):
45
- ''' Returns an geoid without validity date
46
- as we do not support it anymore'''
41
+ """Returns an geoid without validity date
42
+ as we do not support it anymore"""
47
43
  match = re.match(LEGACY_GEOID_PATTERN, legacy_id)
48
44
  if match:
49
- return legacy_id.split('@')[0]
45
+ return legacy_id.split("@")[0]
50
46
  return legacy_id
51
47
 
52
48
 
53
- @ns.route('/zones/suggest/', endpoint='suggest_zones')
49
+ @ns.route("/zones/suggest/", endpoint="suggest_zones")
54
50
  class SuggestZonesAPI(API):
55
51
  @api.marshal_list_with(zone_suggestion_fields)
56
52
  @api.expect(suggest_parser)
57
- @api.doc('suggest_zones')
53
+ @api.doc("suggest_zones")
58
54
  def get(self):
59
- '''Geospatial zones suggest endpoint using mongoDB contains'''
55
+ """Geospatial zones suggest endpoint using mongoDB contains"""
60
56
  args = suggest_parser.parse_args()
61
- geozones = GeoZone.objects(Q(name__icontains=args['q']) | Q(code__icontains=args['q']))
57
+ geozones = GeoZone.objects(Q(name__icontains=args["q"]) | Q(code__icontains=args["q"]))
62
58
 
63
59
  # We're manually sorting based on zone level int (cause we don't have the int value directly in mongo document)
64
60
  level_id_to_int_level = {level.id: level.admin_level for level in GeoLevel.objects()}
@@ -66,114 +62,110 @@ class SuggestZonesAPI(API):
66
62
 
67
63
  return [
68
64
  {
69
- 'id': geozone.id,
70
- 'name': payload_name(geozone.name),
71
- 'code': geozone.code,
72
- 'level': geozone.level,
73
- 'uri': geozone.uri
65
+ "id": geozone.id,
66
+ "name": payload_name(geozone.name),
67
+ "code": geozone.code,
68
+ "level": geozone.level,
69
+ "uri": geozone.uri,
74
70
  }
75
- for geozone in geozones[:args['size']]
71
+ for geozone in geozones[: args["size"]]
76
72
  ]
77
73
 
78
74
 
79
75
  dataset_parser = api.parser()
80
76
  dataset_parser.add_argument(
81
- 'dynamic', type=inputs.boolean, help='Append dynamic datasets',
82
- location='args', required=False)
77
+ "dynamic", type=inputs.boolean, help="Append dynamic datasets", location="args", required=False
78
+ )
83
79
  dataset_parser.add_argument(
84
- 'size', type=int, help='The amount of datasets to fetch',
85
- location='args', default=25)
80
+ "size", type=int, help="The amount of datasets to fetch", location="args", default=25
81
+ )
86
82
 
87
83
 
88
- @ns.route('/zones/<list:ids>/', endpoint='zones')
84
+ @ns.route("/zones/<list:ids>/", endpoint="zones")
89
85
  class ZonesAPI(API):
90
- @api.doc('spatial_zones',
91
- params={'ids': 'A zone identifiers list (comma separated)'})
86
+ @api.doc("spatial_zones", params={"ids": "A zone identifiers list (comma separated)"})
92
87
  @api.marshal_with(feature_collection_fields)
93
88
  def get(self, ids):
94
- '''Fetch a zone list as GeoJSON'''
89
+ """Fetch a zone list as GeoJSON"""
95
90
  ids_list = list(map(legacy_geoid, ids))
96
91
  zones = GeoZone.objects.in_bulk(ids_list)
97
92
  zones = [zones[id] for id in ids_list]
98
93
  return {
99
- 'type': 'FeatureCollection',
100
- 'features': [z.toGeoJSON() for z in zones],
94
+ "type": "FeatureCollection",
95
+ "features": [z.toGeoJSON() for z in zones],
101
96
  }
102
97
 
103
98
 
104
- @ns.route('/zone/<id>/datasets/', endpoint='zone_datasets')
99
+ @ns.route("/zone/<id>/datasets/", endpoint="zone_datasets")
105
100
  class ZoneDatasetsAPI(API):
106
- @api.doc('spatial_zone_datasets', params={'id': 'A zone identifier'})
101
+ @api.doc("spatial_zone_datasets", params={"id": "A zone identifier"})
107
102
  @api.expect(dataset_parser)
108
103
  @api.marshal_with(dataset_ref_fields)
109
104
  def get(self, id):
110
- '''Fetch datasets for a given zone'''
105
+ """Fetch datasets for a given zone"""
111
106
  id = legacy_geoid(id)
112
107
  args = dataset_parser.parse_args()
113
108
  zone = GeoZone.objects.get_or_404(id=id)
114
109
  datasets = []
115
- datasets += list(Dataset.objects.visible()
116
- .filter(spatial__zones=zone)
117
- .limit(args['size']))
110
+ datasets += list(Dataset.objects.visible().filter(spatial__zones=zone).limit(args["size"]))
118
111
  return datasets
119
112
 
120
113
 
121
- @ns.route('/zone/<id>/', endpoint='zone')
114
+ @ns.route("/zone/<id>/", endpoint="zone")
122
115
  class ZoneAPI(API):
123
- @api.doc('spatial_zone', params={'id': 'A zone identifier'})
116
+ @api.doc("spatial_zone", params={"id": "A zone identifier"})
124
117
  def get(self, id):
125
- '''Fetch a zone'''
118
+ """Fetch a zone"""
126
119
  id = legacy_geoid(id)
127
120
  zone = GeoZone.objects.get_or_404(id=id)
128
121
  return zone.toGeoJSON()
129
122
 
130
123
 
131
- @ns.route('/levels/', endpoint='spatial_levels')
124
+ @ns.route("/levels/", endpoint="spatial_levels")
132
125
  class SpatialLevelsAPI(API):
133
- @api.doc('spatial_levels')
126
+ @api.doc("spatial_levels")
134
127
  @api.marshal_list_with(level_fields)
135
128
  def get(self):
136
- '''List all known levels'''
137
- return [{
138
- 'id': level.id,
139
- 'name': _(level.name)
140
- } for level in GeoLevel.objects]
129
+ """List all known levels"""
130
+ return [{"id": level.id, "name": _(level.name)} for level in GeoLevel.objects]
141
131
 
142
132
 
143
- @ns.route('/granularities/', endpoint='spatial_granularities')
133
+ @ns.route("/granularities/", endpoint="spatial_granularities")
144
134
  class SpatialGranularitiesAPI(API):
145
- @api.doc('spatial_granularities')
135
+ @api.doc("spatial_granularities")
146
136
  @api.marshal_list_with(granularity_fields)
147
137
  def get(self):
148
- '''List all known spatial granularities'''
149
- return [{
150
- 'id': id,
151
- 'name': name,
152
- } for id, name in spatial_granularities]
138
+ """List all known spatial granularities"""
139
+ return [
140
+ {
141
+ "id": id,
142
+ "name": name,
143
+ }
144
+ for id, name in spatial_granularities
145
+ ]
153
146
 
154
147
 
155
- @ns.route('/coverage/<level>/', endpoint='spatial_coverage')
148
+ @ns.route("/coverage/<level>/", endpoint="spatial_coverage")
156
149
  class SpatialCoverageAPI(API):
157
- @api.doc('spatial_coverage')
150
+ @api.doc("spatial_coverage")
158
151
  @api.marshal_list_with(feature_collection_fields)
159
152
  def get(self, level):
160
- '''List each zone for a given level with their datasets count'''
153
+ """List each zone for a given level with their datasets count"""
161
154
  level = GeoLevel.objects.get_or_404(id=level)
162
155
  features = []
163
156
 
164
157
  for zone in GeoZone.objects(level=level.id):
165
- features.append({
166
- 'id': zone.id,
167
- 'type': 'Feature',
168
- 'properties': {
169
- 'name': _(zone.name),
170
- 'code': zone.code,
171
- 'uri': zone.uri,
172
- 'datasets': zone.metrics.get('datasets', 0)
158
+ features.append(
159
+ {
160
+ "id": zone.id,
161
+ "type": "Feature",
162
+ "properties": {
163
+ "name": _(zone.name),
164
+ "code": zone.code,
165
+ "uri": zone.uri,
166
+ "datasets": zone.metrics.get("datasets", 0),
167
+ },
173
168
  }
174
- })
169
+ )
175
170
 
176
- return {
177
- 'type': 'FeatureCollection',
178
- 'features': features
179
- }
171
+ return {"type": "FeatureCollection", "features": features}
@@ -1,71 +1,86 @@
1
1
  from udata.api import api, fields
2
2
 
3
-
4
- GEOM_TYPES = (
5
- 'Point', 'LineString', 'Polygon', 'MultiPoint', 'MultiLineString',
6
- 'MultiPolygon'
7
- )
3
+ GEOM_TYPES = ("Point", "LineString", "Polygon", "MultiPoint", "MultiLineString", "MultiPolygon")
8
4
 
9
5
 
10
- geojson = api.model('GeoJSON', {
11
- 'type': fields.String(
12
- description='The GeoJSON Type', required=True, enum=GEOM_TYPES),
13
- 'coordinates': fields.List(
14
- fields.Raw(), description='The geometry as coordinates lists',
15
- required=True),
16
- })
6
+ geojson = api.model(
7
+ "GeoJSON",
8
+ {
9
+ "type": fields.String(description="The GeoJSON Type", required=True, enum=GEOM_TYPES),
10
+ "coordinates": fields.List(
11
+ fields.Raw(), description="The geometry as coordinates lists", required=True
12
+ ),
13
+ },
14
+ )
17
15
 
18
- feature_fields = api.model('GeoJSONFeature', {
19
- 'id': fields.String,
20
- 'type': fields.String(required=True, enum=['Feature']),
21
- 'geometry': fields.Nested(geojson, required=True),
22
- 'properties': fields.Raw,
23
- })
16
+ feature_fields = api.model(
17
+ "GeoJSONFeature",
18
+ {
19
+ "id": fields.String,
20
+ "type": fields.String(required=True, enum=["Feature"]),
21
+ "geometry": fields.Nested(geojson, required=True),
22
+ "properties": fields.Raw,
23
+ },
24
+ )
24
25
 
25
- feature_collection_fields = api.model('GeoJSONFeatureCollection', {
26
- 'type': fields.String(required=True, enum=['FeatureCollection']),
27
- 'features': fields.List(fields.Nested(feature_fields), required=True)
28
- })
26
+ feature_collection_fields = api.model(
27
+ "GeoJSONFeatureCollection",
28
+ {
29
+ "type": fields.String(required=True, enum=["FeatureCollection"]),
30
+ "features": fields.List(fields.Nested(feature_fields), required=True),
31
+ },
32
+ )
29
33
 
30
- level_fields = api.model('GeoLevel', {
31
- 'id': fields.String(description='The level identifier', required=True),
32
- 'name': fields.String(description='The level name', required=True)
33
- })
34
+ level_fields = api.model(
35
+ "GeoLevel",
36
+ {
37
+ "id": fields.String(description="The level identifier", required=True),
38
+ "name": fields.String(description="The level name", required=True),
39
+ },
40
+ )
34
41
 
35
- zone_fields = api.model('GeoZone', {
36
- 'id': fields.String(description='The zone identifier', required=True),
37
- 'name': fields.String(description='The zone name', required=True),
38
- 'slug': fields.String(description='The zone slug', required=True),
39
- 'code': fields.String(
40
- description='The zone unique code in the level', required=True),
41
- 'level': fields.String(description='The zone level', required=True),
42
- 'uri': fields.String(description='The zone uri', required=True)
43
- })
42
+ zone_fields = api.model(
43
+ "GeoZone",
44
+ {
45
+ "id": fields.String(description="The zone identifier", required=True),
46
+ "name": fields.String(description="The zone name", required=True),
47
+ "slug": fields.String(description="The zone slug", required=True),
48
+ "code": fields.String(description="The zone unique code in the level", required=True),
49
+ "level": fields.String(description="The zone level", required=True),
50
+ "uri": fields.String(description="The zone uri", required=True),
51
+ },
52
+ )
44
53
 
45
- granularity_fields = api.model('GeoGranularity', {
46
- 'id': fields.String(
47
- description='The granularity identifier', required=True),
48
- 'name': fields.String(description='The granularity name', required=True),
49
- })
54
+ granularity_fields = api.model(
55
+ "GeoGranularity",
56
+ {
57
+ "id": fields.String(description="The granularity identifier", required=True),
58
+ "name": fields.String(description="The granularity name", required=True),
59
+ },
60
+ )
50
61
 
51
62
 
52
- spatial_coverage_fields = api.model('SpatialCoverage', {
53
- 'geom': fields.Nested(
54
- geojson, allow_null=True,
55
- description='A multipolygon for the whole coverage'),
56
- 'zones': fields.List(
57
- fields.String, description='The covered zones identifiers'),
58
- 'granularity': fields.String(default='other',
59
- description='The spatial/territorial granularity'),
60
- })
63
+ spatial_coverage_fields = api.model(
64
+ "SpatialCoverage",
65
+ {
66
+ "geom": fields.Nested(
67
+ geojson, allow_null=True, description="A multipolygon for the whole coverage"
68
+ ),
69
+ "zones": fields.List(fields.String, description="The covered zones identifiers"),
70
+ "granularity": fields.String(
71
+ default="other", description="The spatial/territorial granularity"
72
+ ),
73
+ },
74
+ )
61
75
 
62
76
 
63
- zone_suggestion_fields = api.model('TerritorySuggestion', {
64
- 'id': fields.String(description='The territory identifier', required=True),
65
- 'name': fields.String(description='The territory name', required=True),
66
- 'code': fields.String(
67
- description='The territory main code', required=True),
68
- 'level': fields.String(
69
- description='The territory administrative level', required=True),
70
- 'uri': fields.String(description='The zone uri', required=True)
71
- })
77
+ zone_suggestion_fields = api.model(
78
+ "TerritorySuggestion",
79
+ {
80
+ "id": fields.String(description="The territory identifier", required=True),
81
+ "name": fields.String(description="The territory name", required=True),
82
+ "code": fields.String(description="The territory main code", required=True),
83
+ "level": fields.String(description="The territory administrative level", required=True),
84
+ "uri": fields.String(description="The zone uri", required=True),
85
+ },
86
+ )