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
@@ -4,44 +4,41 @@ from werkzeug.utils import cached_property
4
4
 
5
5
  from udata.app import cache
6
6
  from udata.core.metrics.models import WithMetrics
7
- from udata.uris import endpoint_for
8
7
  from udata.i18n import _, get_locale, language
9
8
  from udata.mongo import db
9
+ from udata.uris import endpoint_for
10
10
 
11
11
  from . import geoids
12
- from .constants import ADMIN_LEVEL_MIN, ADMIN_LEVEL_MAX, BASE_GRANULARITIES
12
+ from .constants import ADMIN_LEVEL_MAX, ADMIN_LEVEL_MIN, BASE_GRANULARITIES
13
13
 
14
-
15
- __all__ = ('GeoLevel', 'GeoZone', 'SpatialCoverage', 'spatial_granularities')
14
+ __all__ = ("GeoLevel", "GeoZone", "SpatialCoverage", "spatial_granularities")
16
15
 
17
16
 
18
17
  class GeoLevel(db.Document):
19
18
  id = db.StringField(primary_key=True)
20
19
  name = db.StringField(required=True)
21
- admin_level = db.IntField(min_value=ADMIN_LEVEL_MIN,
22
- max_value=ADMIN_LEVEL_MAX,
23
- default=100)
20
+ admin_level = db.IntField(min_value=ADMIN_LEVEL_MIN, max_value=ADMIN_LEVEL_MAX, default=100)
24
21
 
25
- class GeoZoneQuerySet(db.BaseQuerySet):
26
22
 
23
+ class GeoZoneQuerySet(db.BaseQuerySet):
27
24
  def resolve(self, geoid, id_only=False):
28
- '''
25
+ """
29
26
  Resolve a GeoZone given a GeoID.
30
27
 
31
28
  If `id_only` is True,
32
29
  the result will be the resolved GeoID
33
30
  instead of the resolved zone.
34
- '''
31
+ """
35
32
  level, code = geoids.parse(geoid)
36
33
  qs = self(level=level, code=code)
37
34
  if id_only:
38
- qs = qs.only('id')
35
+ qs = qs.only("id")
39
36
  result = qs.first()
40
37
  return result.id if id_only and result else result
41
38
 
42
39
 
43
40
  class GeoZone(WithMetrics, db.Document):
44
- SEPARATOR = ':'
41
+ SEPARATOR = ":"
45
42
 
46
43
  id = db.StringField(primary_key=True)
47
44
  slug = db.StringField(required=True)
@@ -51,11 +48,11 @@ class GeoZone(WithMetrics, db.Document):
51
48
  uri = db.StringField()
52
49
 
53
50
  meta = {
54
- 'indexes': [
55
- 'name',
56
- ('level', 'code'),
51
+ "indexes": [
52
+ "name",
53
+ ("level", "code"),
57
54
  ],
58
- 'queryset_class': GeoZoneQuerySet
55
+ "queryset_class": GeoZoneQuerySet,
59
56
  }
60
57
 
61
58
  def __str__(self):
@@ -63,20 +60,19 @@ class GeoZone(WithMetrics, db.Document):
63
60
 
64
61
  def __html__(self):
65
62
  """In use within the admin."""
66
- return '{name} <i>({code})</i>'.format(
67
- name=_(self.name), code=self.code)
63
+ return "{name} <i>({code})</i>".format(name=_(self.name), code=self.code)
68
64
 
69
65
  @cached_property
70
66
  def level_code(self):
71
67
  """Truncated level code for the sake of readability."""
72
68
  # Either 'region', 'departement' or 'commune',
73
69
  # useful to match TERRITORY_DATASETS keys.
74
- return self.id.split(':')[1]
70
+ return self.id.split(":")[1]
75
71
 
76
72
  @cached_property
77
73
  def level_name(self):
78
74
  """Truncated level name for the sake of readability."""
79
- if self.level.startswith('fr:'):
75
+ if self.level.startswith("fr:"):
80
76
  return self.level[3:]
81
77
  # Keep the whole level name as a fallback (e.g. `country:fr`)
82
78
  return self.level
@@ -91,48 +87,48 @@ class GeoZone(WithMetrics, db.Document):
91
87
 
92
88
  @property
93
89
  def handled_level(self):
94
- return self.level in current_app.config.get('HANDLED_LEVELS')
90
+ return self.level in current_app.config.get("HANDLED_LEVELS")
95
91
 
96
92
  @property
97
93
  def url(self):
98
- return endpoint_for('territories.territory', territory=self)
94
+ return endpoint_for("territories.territory", territory=self)
99
95
 
100
96
  @property
101
97
  def external_url(self):
102
- return endpoint_for('territories.territory', territory=self, _external=True)
98
+ return endpoint_for("territories.territory", territory=self, _external=True)
103
99
 
104
100
  def count_datasets(self):
105
101
  from udata.models import Dataset
106
- self.metrics['datasets'] = Dataset.objects(spatial__zones=self.id).visible().count()
102
+
103
+ self.metrics["datasets"] = Dataset.objects(spatial__zones=self.id).visible().count()
107
104
  self.save()
108
105
 
109
106
  def toGeoJSON(self):
110
107
  return {
111
- 'id': self.id,
112
- 'type': 'Feature',
113
- 'properties': {
114
- 'slug': self.slug,
115
- 'name': _(self.name),
116
- 'code': self.code,
117
- 'uri': self.uri,
118
- 'level': self.level,
119
- }
108
+ "id": self.id,
109
+ "type": "Feature",
110
+ "properties": {
111
+ "slug": self.slug,
112
+ "name": _(self.name),
113
+ "code": self.code,
114
+ "uri": self.uri,
115
+ "level": self.level,
116
+ },
120
117
  }
121
118
 
122
119
 
123
120
  @cache.memoize()
124
121
  def get_spatial_granularities(lang):
125
122
  with language(lang):
126
- return [
127
- (l.id, _(l.name)) for l in GeoLevel.objects
128
- ] + [(id, str(label)) for id, label in BASE_GRANULARITIES]
123
+ return [(l.id, _(l.name)) for l in GeoLevel.objects] + [
124
+ (id, str(label)) for id, label in BASE_GRANULARITIES
125
+ ]
129
126
 
130
127
 
131
- spatial_granularities = LocalProxy(
132
- lambda: get_spatial_granularities(get_locale()))
128
+ spatial_granularities = LocalProxy(lambda: get_spatial_granularities(get_locale()))
133
129
 
134
130
 
135
- @cache.cached(timeout=50, key_prefix='admin_levels')
131
+ @cache.cached(timeout=50, key_prefix="admin_levels")
136
132
  def get_spatial_admin_levels():
137
133
  return dict((l.id, l.admin_level) for l in GeoLevel.objects)
138
134
 
@@ -141,15 +137,15 @@ admin_levels = LocalProxy(get_spatial_admin_levels)
141
137
 
142
138
 
143
139
  class SpatialCoverage(db.EmbeddedDocument):
144
- """Represent a spatial coverage as a list of territories and/or a geometry.
145
- """
140
+ """Represent a spatial coverage as a list of territories and/or a geometry."""
141
+
146
142
  geom = db.MultiPolygonField()
147
143
  zones = db.ListField(db.ReferenceField(GeoZone))
148
- granularity = db.StringField(default='other')
144
+ granularity = db.StringField(default="other")
149
145
 
150
146
  @property
151
147
  def granularity_label(self):
152
- return dict(spatial_granularities).get(self.granularity or 'other', 'other')
148
+ return dict(spatial_granularities).get(self.granularity or "other", "other")
153
149
 
154
150
  @property
155
151
  def top_label(self):
@@ -168,9 +164,9 @@ class SpatialCoverage(db.EmbeddedDocument):
168
164
  return [zone for zone in self.zones if zone.handled_level]
169
165
 
170
166
  def clean(self):
171
- if 'geom' in self._get_changed_fields():
167
+ if "geom" in self._get_changed_fields():
172
168
  if self.zones:
173
- raise db.ValidationError('The spatial coverage already has a Geozone')
174
- if 'zones' in self._get_changed_fields():
169
+ raise db.ValidationError("The spatial coverage already has a Geozone")
170
+ if "zones" in self._get_changed_fields():
175
171
  if self.geom:
176
- raise db.ValidationError('The spatial coverage already has a Geometry')
172
+ raise db.ValidationError("The spatial coverage already has a Geometry")
@@ -1,7 +1,8 @@
1
1
  from udata.core.spatial.models import GeoZone
2
2
  from udata.tasks import job
3
3
 
4
- @job('compute-geozones-metrics')
4
+
5
+ @job("compute-geozones-metrics")
5
6
  def compute_geozones_metrics(self):
6
7
  for geozone in GeoZone.objects.timeout(False):
7
8
  geozone.count_datasets()
@@ -1,16 +1,19 @@
1
1
  from flask import url_for
2
2
 
3
- from udata.utils import faker
4
- from udata.tests.api import APITestCase
5
- from udata.tests.features.territories import (
6
- create_geozones_fixtures, TerritoriesSettings
7
- )
8
- from udata.core.organization.factories import OrganizationFactory
9
3
  from udata.core.dataset.factories import DatasetFactory
4
+ from udata.core.organization.factories import OrganizationFactory
10
5
  from udata.core.spatial.factories import (
11
- SpatialCoverageFactory, GeoZoneFactory, GeoLevelFactory
6
+ GeoLevelFactory,
7
+ GeoZoneFactory,
8
+ SpatialCoverageFactory,
12
9
  )
13
10
  from udata.core.spatial.tasks import compute_geozones_metrics
11
+ from udata.tests.api import APITestCase
12
+ from udata.tests.features.territories import (
13
+ TerritoriesSettings,
14
+ create_geozones_fixtures,
15
+ )
16
+ from udata.utils import faker
14
17
 
15
18
 
16
19
  class SpatialApiTest(APITestCase):
@@ -19,151 +22,141 @@ class SpatialApiTest(APITestCase):
19
22
  def test_zones_api_one(self):
20
23
  zone = GeoZoneFactory()
21
24
 
22
- url = url_for('api.zones', ids=[zone.id])
25
+ url = url_for("api.zones", ids=[zone.id])
23
26
  response = self.get(url)
24
27
  self.assert200(response)
25
28
 
26
- self.assertEqual(len(response.json['features']), 1)
29
+ self.assertEqual(len(response.json["features"]), 1)
27
30
 
28
- feature = response.json['features'][0]
29
- self.assertEqual(feature['type'], 'Feature')
30
- self.assertEqual(feature['id'], zone.id)
31
+ feature = response.json["features"][0]
32
+ self.assertEqual(feature["type"], "Feature")
33
+ self.assertEqual(feature["id"], zone.id)
31
34
 
32
- properties = feature['properties']
33
- self.assertEqual(properties['name'], zone.name)
34
- self.assertEqual(properties['code'], zone.code)
35
- self.assertEqual(properties['level'], zone.level)
36
- self.assertEqual(properties['uri'], zone.uri)
35
+ properties = feature["properties"]
36
+ self.assertEqual(properties["name"], zone.name)
37
+ self.assertEqual(properties["code"], zone.code)
38
+ self.assertEqual(properties["level"], zone.level)
39
+ self.assertEqual(properties["uri"], zone.uri)
37
40
 
38
41
  def test_zones_api_many(self):
39
42
  zones = [GeoZoneFactory() for _ in range(3)]
40
43
 
41
- url = url_for('api.zones', ids=zones)
44
+ url = url_for("api.zones", ids=zones)
42
45
  response = self.get(url)
43
46
  self.assert200(response)
44
47
 
45
- self.assertEqual(len(response.json['features']), len(zones))
48
+ self.assertEqual(len(response.json["features"]), len(zones))
46
49
 
47
- for zone, feature in zip(zones, response.json['features']):
48
- self.assertEqual(feature['type'], 'Feature')
49
- self.assertEqual(feature['id'], zone.id)
50
+ for zone, feature in zip(zones, response.json["features"]):
51
+ self.assertEqual(feature["type"], "Feature")
52
+ self.assertEqual(feature["id"], zone.id)
50
53
 
51
- properties = feature['properties']
52
- self.assertEqual(properties['name'], zone.name)
53
- self.assertEqual(properties['code'], zone.code)
54
- self.assertEqual(properties['level'], zone.level)
55
- self.assertEqual(properties['uri'], zone.uri)
54
+ properties = feature["properties"]
55
+ self.assertEqual(properties["name"], zone.name)
56
+ self.assertEqual(properties["code"], zone.code)
57
+ self.assertEqual(properties["level"], zone.level)
58
+ self.assertEqual(properties["uri"], zone.uri)
56
59
 
57
60
  def test_suggest_zones_on_name(self):
58
- '''It should suggest zones based on its name'''
61
+ """It should suggest zones based on its name"""
59
62
  for i in range(4):
60
- GeoZoneFactory(name='name-test-{0}'.format(i)
61
- if i % 2 else faker.word())
63
+ GeoZoneFactory(name="name-test-{0}".format(i) if i % 2 else faker.word())
62
64
 
63
- response = self.get(
64
- url_for('api.suggest_zones'), qs={'q': 'name-test', 'size': '5'})
65
+ response = self.get(url_for("api.suggest_zones"), qs={"q": "name-test", "size": "5"})
65
66
  self.assert200(response)
66
67
 
67
68
  self.assertEqual(len(response.json), 2)
68
69
 
69
70
  for suggestion in response.json:
70
- self.assertIn('id', suggestion)
71
- self.assertIn('name', suggestion)
72
- self.assertIn('code', suggestion)
73
- self.assertIn('uri', suggestion)
74
- self.assertIn('level', suggestion)
75
- self.assertIn('name-test', suggestion['name'])
71
+ self.assertIn("id", suggestion)
72
+ self.assertIn("name", suggestion)
73
+ self.assertIn("code", suggestion)
74
+ self.assertIn("uri", suggestion)
75
+ self.assertIn("level", suggestion)
76
+ self.assertIn("name-test", suggestion["name"])
76
77
 
77
78
  def test_suggest_zones_sorted(self):
78
- '''It should suggest zones based on its name'''
79
- country_level = GeoLevelFactory(id='country', name='country', admin_level=10)
80
- region_level = GeoLevelFactory(id='region', name='region', admin_level=20)
81
- country_zone = GeoZoneFactory(name='name-test-country', level=country_level.id)
82
- region_zone = GeoZoneFactory(name='name-test-region', level=region_level.id)
83
-
84
- response = self.get(
85
- url_for('api.suggest_zones'), qs={'q': 'name-test', 'size': '5'})
79
+ """It should suggest zones based on its name"""
80
+ country_level = GeoLevelFactory(id="country", name="country", admin_level=10)
81
+ region_level = GeoLevelFactory(id="region", name="region", admin_level=20)
82
+ country_zone = GeoZoneFactory(name="name-test-country", level=country_level.id)
83
+ region_zone = GeoZoneFactory(name="name-test-region", level=region_level.id)
84
+
85
+ response = self.get(url_for("api.suggest_zones"), qs={"q": "name-test", "size": "5"})
86
86
  self.assert200(response)
87
87
 
88
88
  self.assertEqual(len(response.json), 2)
89
- self.assertEqual((response.json[0]['id']), country_zone.id)
90
- self.assertEqual((response.json[1]['id']), region_zone.id)
89
+ self.assertEqual((response.json[0]["id"]), country_zone.id)
90
+ self.assertEqual((response.json[1]["id"]), region_zone.id)
91
91
 
92
92
  def test_suggest_zones_on_code(self):
93
- '''It should suggest zones based on its code'''
93
+ """It should suggest zones based on its code"""
94
94
  for i in range(4):
95
- GeoZoneFactory(code='code-test-{0}'.format(i)
96
- if i % 2 else faker.word())
95
+ GeoZoneFactory(code="code-test-{0}".format(i) if i % 2 else faker.word())
97
96
 
98
- response = self.get(
99
- url_for('api.suggest_zones'), qs={'q': 'code-test', 'size': '5'})
97
+ response = self.get(url_for("api.suggest_zones"), qs={"q": "code-test", "size": "5"})
100
98
  self.assert200(response)
101
99
 
102
100
  self.assertEqual(len(response.json), 2)
103
101
 
104
102
  for suggestion in response.json:
105
- self.assertIn('id', suggestion)
106
- self.assertIn('name', suggestion)
107
- self.assertIn('code', suggestion)
108
- self.assertIn('level', suggestion)
109
- self.assertIn('uri', suggestion)
110
- self.assertIn('code-test', suggestion['code'])
103
+ self.assertIn("id", suggestion)
104
+ self.assertIn("name", suggestion)
105
+ self.assertIn("code", suggestion)
106
+ self.assertIn("level", suggestion)
107
+ self.assertIn("uri", suggestion)
108
+ self.assertIn("code-test", suggestion["code"])
111
109
 
112
110
  def test_suggest_zones_no_match(self):
113
- '''It should not provide zones suggestions if no match'''
111
+ """It should not provide zones suggestions if no match"""
114
112
  for i in range(3):
115
- GeoZoneFactory(name=5 * '{0}'.format(i),
116
- code=3 * '{0}'.format(i))
113
+ GeoZoneFactory(name=5 * "{0}".format(i), code=3 * "{0}".format(i))
117
114
 
118
- response = self.get(
119
- url_for('api.suggest_zones'), qs={'q': 'xxxxxx', 'size': '5'})
115
+ response = self.get(url_for("api.suggest_zones"), qs={"q": "xxxxxx", "size": "5"})
120
116
  self.assert200(response)
121
117
  self.assertEqual(len(response.json), 0)
122
118
 
123
119
  def test_suggest_zones_unicode(self):
124
- '''It should suggest zones based on its name'''
120
+ """It should suggest zones based on its name"""
125
121
  for i in range(4):
126
- GeoZoneFactory(name='name-testé-{0}'.format(i)
127
- if i % 2 else faker.word())
122
+ GeoZoneFactory(name="name-testé-{0}".format(i) if i % 2 else faker.word())
128
123
 
129
- response = self.get(
130
- url_for('api.suggest_zones'), qs={'q': 'name-testé', 'size': '5'})
124
+ response = self.get(url_for("api.suggest_zones"), qs={"q": "name-testé", "size": "5"})
131
125
  self.assert200(response)
132
126
 
133
127
  self.assertEqual(len(response.json), 2)
134
128
 
135
129
  for suggestion in response.json:
136
- self.assertIn('id', suggestion)
137
- self.assertIn('name', suggestion)
138
- self.assertIn('code', suggestion)
139
- self.assertIn('level', suggestion)
140
- self.assertIn('uri', suggestion)
141
- self.assertIn('name-testé', suggestion['name'])
130
+ self.assertIn("id", suggestion)
131
+ self.assertIn("name", suggestion)
132
+ self.assertIn("code", suggestion)
133
+ self.assertIn("level", suggestion)
134
+ self.assertIn("uri", suggestion)
135
+ self.assertIn("name-testé", suggestion["name"])
142
136
 
143
137
  def test_suggest_zones_empty(self):
144
- '''It should not provide zones suggestion if no data is present'''
145
- response = self.get(
146
- url_for('api.suggest_zones'), qs={'q': 'xxxxxx', 'size': '5'})
138
+ """It should not provide zones suggestion if no data is present"""
139
+ response = self.get(url_for("api.suggest_zones"), qs={"q": "xxxxxx", "size": "5"})
147
140
  self.assert200(response)
148
141
  self.assertEqual(len(response.json), 0)
149
142
 
150
143
  def test_spatial_levels(self):
151
144
  levels = [GeoLevelFactory() for _ in range(3)]
152
145
 
153
- response = self.get(url_for('api.spatial_levels'))
146
+ response = self.get(url_for("api.spatial_levels"))
154
147
  self.assert200(response)
155
148
  self.assertEqual(len(response.json), len(levels))
156
149
 
157
150
  def test_spatial_granularities(self):
158
151
  levels = [GeoLevelFactory() for _ in range(3)]
159
152
 
160
- response = self.get(url_for('api.spatial_granularities'))
153
+ response = self.get(url_for("api.spatial_granularities"))
161
154
  self.assert200(response)
162
155
  self.assertEqual(len(response.json), len(levels) + 2)
163
156
 
164
157
  def test_zone_datasets_empty(self):
165
158
  paca, bdr, arles = create_geozones_fixtures()
166
- response = self.get(url_for('api.zone_datasets', id=paca.id))
159
+ response = self.get(url_for("api.zone_datasets", id=paca.id))
167
160
  self.assert200(response)
168
161
  self.assertEqual(response.json, [])
169
162
 
@@ -172,10 +165,10 @@ class SpatialApiTest(APITestCase):
172
165
  organization = OrganizationFactory()
173
166
  for _ in range(3):
174
167
  DatasetFactory(
175
- organization=organization,
176
- spatial=SpatialCoverageFactory(zones=[paca.id]))
168
+ organization=organization, spatial=SpatialCoverageFactory(zones=[paca.id])
169
+ )
177
170
 
178
- response = self.get(url_for('api.zone_datasets', id=paca.id))
171
+ response = self.get(url_for("api.zone_datasets", id=paca.id))
179
172
  self.assert200(response)
180
173
  self.assertEqual(len(response.json), 3)
181
174
 
@@ -184,11 +177,10 @@ class SpatialApiTest(APITestCase):
184
177
  organization = OrganizationFactory()
185
178
  for _ in range(3):
186
179
  DatasetFactory(
187
- organization=organization,
188
- spatial=SpatialCoverageFactory(zones=[paca.id]))
180
+ organization=organization, spatial=SpatialCoverageFactory(zones=[paca.id])
181
+ )
189
182
 
190
- response = self.get(url_for('api.zone_datasets', id=paca.id),
191
- qs={'size': 2})
183
+ response = self.get(url_for("api.zone_datasets", id=paca.id), qs={"size": 2})
192
184
  self.assert200(response)
193
185
  self.assertEqual(len(response.json), 2)
194
186
 
@@ -197,11 +189,10 @@ class SpatialApiTest(APITestCase):
197
189
  organization = OrganizationFactory()
198
190
  for _ in range(3):
199
191
  DatasetFactory(
200
- organization=organization,
201
- spatial=SpatialCoverageFactory(zones=[paca.id]))
192
+ organization=organization, spatial=SpatialCoverageFactory(zones=[paca.id])
193
+ )
202
194
 
203
- response = self.get(
204
- url_for('api.zone_datasets', id=paca.id), qs={'dynamic': 1})
195
+ response = self.get(url_for("api.zone_datasets", id=paca.id), qs={"dynamic": 1})
205
196
  self.assert200(response)
206
197
  # No dynamic datasets given that the setting is deactivated by default.
207
198
  self.assertEqual(len(response.json), 3)
@@ -211,49 +202,48 @@ class SpatialApiTest(APITestCase):
211
202
  organization = OrganizationFactory()
212
203
  for _ in range(3):
213
204
  DatasetFactory(
214
- organization=organization,
215
- spatial=SpatialCoverageFactory(zones=[paca.id]))
205
+ organization=organization, spatial=SpatialCoverageFactory(zones=[paca.id])
206
+ )
216
207
 
217
- response = self.get(
218
- url_for('api.zone_datasets', id=paca.id),
219
- qs={'dynamic': 1, 'size': 2})
208
+ response = self.get(url_for("api.zone_datasets", id=paca.id), qs={"dynamic": 1, "size": 2})
220
209
  self.assert200(response)
221
210
  # No dynamic datasets given that the setting is deactivated by default.
222
211
  self.assertEqual(len(response.json), 2)
223
212
 
224
213
  def test_coverage_empty(self):
225
- GeoLevelFactory(id='top')
226
- response = self.get(url_for('api.spatial_coverage', level='top'))
214
+ GeoLevelFactory(id="top")
215
+ response = self.get(url_for("api.spatial_coverage", level="top"))
227
216
  self.assert200(response)
228
- self.assertEqual(response.json, {
229
- 'type': 'FeatureCollection',
230
- 'features': [],
231
- })
217
+ self.assertEqual(
218
+ response.json,
219
+ {
220
+ "type": "FeatureCollection",
221
+ "features": [],
222
+ },
223
+ )
232
224
 
233
225
  def test_coverage_datasets_count(self):
234
- GeoLevelFactory(id='fr:commune')
226
+ GeoLevelFactory(id="fr:commune")
235
227
  paris = GeoZoneFactory(
236
- id='fr:commune:75056', level='fr:commune',
237
- name='Paris', code='75056')
228
+ id="fr:commune:75056", level="fr:commune", name="Paris", code="75056"
229
+ )
238
230
  arles = GeoZoneFactory(
239
- id='fr:commune:13004', level='fr:commune',
240
- name='Arles', code='13004')
231
+ id="fr:commune:13004", level="fr:commune", name="Arles", code="13004"
232
+ )
241
233
 
242
234
  for _ in range(3):
243
- DatasetFactory(
244
- spatial=SpatialCoverageFactory(zones=[paris.id]))
235
+ DatasetFactory(spatial=SpatialCoverageFactory(zones=[paris.id]))
245
236
  for _ in range(2):
246
- DatasetFactory(
247
- spatial=SpatialCoverageFactory(zones=[arles.id]))
248
-
237
+ DatasetFactory(spatial=SpatialCoverageFactory(zones=[arles.id]))
238
+
249
239
  compute_geozones_metrics()
250
240
 
251
- response = self.get(url_for('api.spatial_coverage', level='fr:commune'))
241
+ response = self.get(url_for("api.spatial_coverage", level="fr:commune"))
252
242
  self.assert200(response)
253
- self.assertEqual(response.json['features'][0]['id'], 'fr:commune:13004')
254
- self.assertEqual(response.json['features'][0]['properties']['datasets'], 2)
255
- self.assertEqual(response.json['features'][1]['id'], 'fr:commune:75056')
256
- self.assertEqual(response.json['features'][1]['properties']['datasets'], 3)
243
+ self.assertEqual(response.json["features"][0]["id"], "fr:commune:13004")
244
+ self.assertEqual(response.json["features"][0]["properties"]["datasets"], 2)
245
+ self.assertEqual(response.json["features"][1]["id"], "fr:commune:75056")
246
+ self.assertEqual(response.json["features"][1]["properties"]["datasets"], 3)
257
247
 
258
248
 
259
249
  class SpatialTerritoriesApiTest(APITestCase):
@@ -265,11 +255,10 @@ class SpatialTerritoriesApiTest(APITestCase):
265
255
  organization = OrganizationFactory()
266
256
  for _ in range(3):
267
257
  DatasetFactory(
268
- organization=organization,
269
- spatial=SpatialCoverageFactory(zones=[paca.id]))
258
+ organization=organization, spatial=SpatialCoverageFactory(zones=[paca.id])
259
+ )
270
260
 
271
- response = self.get(
272
- url_for('api.zone_datasets', id=paca.id), qs={'dynamic': 1})
261
+ response = self.get(url_for("api.zone_datasets", id=paca.id), qs={"dynamic": 1})
273
262
  self.assert200(response)
274
263
  # No dynamic datasets given that they are added by udata-front extension.
275
264
  self.assertEqual(len(response.json), 3)
@@ -279,14 +268,10 @@ class SpatialTerritoriesApiTest(APITestCase):
279
268
  organization = OrganizationFactory()
280
269
  for _ in range(3):
281
270
  DatasetFactory(
282
- organization=organization,
283
- spatial=SpatialCoverageFactory(zones=[paca.id]))
284
-
285
- response = self.get(
286
- url_for('api.zone_datasets', id=paca.id), qs={
287
- 'dynamic': 1,
288
- 'size': 2
289
- })
271
+ organization=organization, spatial=SpatialCoverageFactory(zones=[paca.id])
272
+ )
273
+
274
+ response = self.get(url_for("api.zone_datasets", id=paca.id), qs={"dynamic": 1, "size": 2})
290
275
  self.assert200(response)
291
276
  # No dynamic datasets given that they are added by udata-front extension.
292
277
  self.assertEqual(len(response.json), 2)