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
@@ -1,27 +1,22 @@
1
1
  import re
2
2
  from io import StringIO
3
-
4
- import factory
5
-
6
3
  from random import randint
7
4
 
5
+ import factory
8
6
  from factory.mongoengine import MongoEngineFactory
7
+ from flask import Blueprint, url_for
9
8
 
10
- from flask import url_for, Blueprint
11
-
12
- from udata.mongo import db
13
9
  from udata.frontend import csv
10
+ from udata.mongo import db
14
11
  from udata.utils import faker
15
12
 
16
13
  from . import FrontTestCase
17
14
 
18
-
19
- RE_ATTACHMENT = re.compile(r'^attachment; filename=(?P<filename>.*)$')
20
- RE_FILENAME = re.compile(
21
- r'^(?P<basename>.*)-\d{4}-\d{2}-\d{2}-\d{2}-\d{2}\.csv$')
15
+ RE_ATTACHMENT = re.compile(r"^attachment; filename=(?P<filename>.*)$")
16
+ RE_FILENAME = re.compile(r"^(?P<basename>.*)-\d{4}-\d{2}-\d{2}-\d{2}-\d{2}\.csv$")
22
17
 
23
18
 
24
- blueprint = Blueprint('testcsv', __name__)
19
+ blueprint = Blueprint("testcsv", __name__)
25
20
 
26
21
 
27
22
  class NestedFake(db.EmbeddedDocument):
@@ -39,12 +34,12 @@ class Fake(db.Document):
39
34
  metrics = db.DictField()
40
35
 
41
36
  __metrics_keys__ = [
42
- 'fake-metric-int',
43
- 'fake-metric-float',
37
+ "fake-metric-int",
38
+ "fake-metric-float",
44
39
  ]
45
40
 
46
41
  def __str__(self):
47
- return 'fake'
42
+ return "fake"
48
43
 
49
44
  def get_metrics(self):
50
45
  return self.metrics
@@ -64,57 +59,56 @@ class FakeFactory(MongoEngineFactory):
64
59
 
65
60
  title = factory.LazyAttribute(lambda o: faker.sentence())
66
61
  description = factory.LazyAttribute(lambda o: faker.paragraph())
67
- tags = factory.LazyAttribute(
68
- lambda o: [faker.word() for _ in range(1, randint(1, 4))])
62
+ tags = factory.LazyAttribute(lambda o: [faker.word() for _ in range(1, randint(1, 4))])
69
63
  sub = factory.SubFactory(NestedFactory)
70
64
 
71
65
 
72
66
  class NestedAdapter(csv.NestedAdapter):
73
- attribute = 'nested'
67
+ attribute = "nested"
74
68
  fields = (
75
- 'title',
76
- 'description',
69
+ "title",
70
+ "description",
77
71
  )
78
72
  nested_fields = (
79
- 'key',
80
- ('alias', 'value'),
73
+ "key",
74
+ ("alias", "value"),
81
75
  )
82
76
 
83
77
 
84
- @blueprint.route('/adapter.csv')
78
+ @blueprint.route("/adapter.csv")
85
79
  def from_adapter():
86
80
  cls = csv.get_adapter(Fake)
87
81
  adapter = cls(Fake.objects)
88
82
  return csv.stream(adapter)
89
83
 
90
84
 
91
- @blueprint.route('/list.csv')
85
+ @blueprint.route("/list.csv")
92
86
  def from_list():
93
87
  return csv.stream(list(Fake.objects))
94
88
 
95
89
 
96
- @blueprint.route('/queryset.csv')
90
+ @blueprint.route("/queryset.csv")
97
91
  def from_queryset():
98
92
  qs = Fake.objects
99
93
  assert isinstance(qs, db.BaseQuerySet)
100
94
  return csv.stream(qs)
101
95
 
102
96
 
103
- @blueprint.route('/nested.csv')
97
+ @blueprint.route("/nested.csv")
104
98
  def from_nested():
105
99
  qs = Fake.objects
106
100
  return csv.stream(NestedAdapter(qs))
107
101
 
108
102
 
109
- @blueprint.route('/with-basename.csv')
103
+ @blueprint.route("/with-basename.csv")
110
104
  def with_basename():
111
105
  cls = csv.get_adapter(Fake)
112
106
  adapter = cls(Fake.objects)
113
- return csv.stream(adapter, 'test')
107
+ return csv.stream(adapter, "test")
114
108
 
115
109
 
116
110
  class CsvTest(FrontTestCase):
117
- modules = ['admin']
111
+ modules = ["admin"]
118
112
 
119
113
  def create_app(self):
120
114
  app = super(CsvTest, self).create_app()
@@ -124,13 +118,13 @@ class CsvTest(FrontTestCase):
124
118
  def test_adapter_fields_as_list(self):
125
119
  @csv.adapter(Fake)
126
120
  class Adapter(csv.Adapter):
127
- fields = ['title', 'description']
121
+ fields = ["title", "description"]
128
122
 
129
123
  objects = FakeFactory.build_batch(3)
130
124
  adapter = Adapter(objects)
131
125
 
132
126
  header = adapter.header()
133
- self.assertEqual(header, ['title', 'description'])
127
+ self.assertEqual(header, ["title", "description"])
134
128
 
135
129
  rows = list(adapter.rows())
136
130
  self.assertEqual(len(rows), len(objects))
@@ -142,13 +136,13 @@ class CsvTest(FrontTestCase):
142
136
  def test_adapter_fields_as_list_with_nested(self):
143
137
  @csv.adapter(Fake)
144
138
  class Adapter(csv.Adapter):
145
- fields = ['title', 'description', 'sub.key']
139
+ fields = ["title", "description", "sub.key"]
146
140
 
147
141
  objects = FakeFactory.build_batch(3)
148
142
  adapter = Adapter(objects)
149
143
 
150
144
  header = adapter.header()
151
- self.assertEqual(header, ['title', 'description', 'sub.key'])
145
+ self.assertEqual(header, ["title", "description", "sub.key"])
152
146
 
153
147
  rows = list(adapter.rows())
154
148
  self.assertEqual(len(rows), len(objects))
@@ -162,17 +156,17 @@ class CsvTest(FrontTestCase):
162
156
  @csv.adapter(Fake)
163
157
  class Adapter(csv.Adapter):
164
158
  fields = (
165
- 'title',
166
- 'description',
167
- ('tags', lambda o: ','.join(o.tags)),
168
- ('alias', 'title'),
159
+ "title",
160
+ "description",
161
+ ("tags", lambda o: ",".join(o.tags)),
162
+ ("alias", "title"),
169
163
  )
170
164
 
171
165
  objects = FakeFactory.build_batch(3)
172
166
  adapter = Adapter(objects)
173
167
 
174
168
  header = adapter.header()
175
- self.assertEqual(header, ['title', 'description', 'tags', 'alias'])
169
+ self.assertEqual(header, ["title", "description", "tags", "alias"])
176
170
 
177
171
  rows = list(adapter.rows())
178
172
  self.assertEqual(len(rows), len(objects))
@@ -180,26 +174,22 @@ class CsvTest(FrontTestCase):
180
174
  self.assertEqual(len(row), len(header))
181
175
  self.assertEqual(row[0], obj.title)
182
176
  self.assertEqual(row[1], obj.description)
183
- self.assertEqual(row[2], ','.join(obj.tags))
177
+ self.assertEqual(row[2], ",".join(obj.tags))
184
178
  self.assertEqual(row[3], obj.title)
185
179
 
186
180
  def test_adapter_fields_with_method(self):
187
181
  @csv.adapter(Fake)
188
182
  class Adapter(csv.Adapter):
189
- fields = (
190
- 'title',
191
- 'description',
192
- 'tags'
193
- )
183
+ fields = ("title", "description", "tags")
194
184
 
195
185
  def field_tags(self, obj):
196
- return ','.join(obj.tags)
186
+ return ",".join(obj.tags)
197
187
 
198
188
  objects = FakeFactory.build_batch(3)
199
189
  adapter = Adapter(objects)
200
190
 
201
191
  header = adapter.header()
202
- self.assertEqual(header, ['title', 'description', 'tags'])
192
+ self.assertEqual(header, ["title", "description", "tags"])
203
193
 
204
194
  rows = list(adapter.rows())
205
195
  self.assertEqual(len(rows), len(objects))
@@ -207,27 +197,25 @@ class CsvTest(FrontTestCase):
207
197
  self.assertEqual(len(row), len(header))
208
198
  self.assertEqual(row[0], obj.title)
209
199
  self.assertEqual(row[1], obj.description)
210
- self.assertEqual(row[2], ','.join(obj.tags))
200
+ self.assertEqual(row[2], ",".join(obj.tags))
211
201
 
212
202
  def test_adapter_fields_with_dyanmic_fields(self):
213
203
  @csv.adapter(Fake)
214
204
  class Adapter(csv.Adapter):
215
- fields = (
216
- 'title',
217
- )
205
+ fields = ("title",)
218
206
 
219
207
  def dynamic_fields(self):
220
208
  return (
221
- 'description',
222
- ('alias', 'title'),
223
- ('tags', lambda o: ','.join(o.tags)),
209
+ "description",
210
+ ("alias", "title"),
211
+ ("tags", lambda o: ",".join(o.tags)),
224
212
  )
225
213
 
226
214
  objects = FakeFactory.build_batch(3)
227
215
  adapter = Adapter(objects)
228
216
 
229
217
  header = adapter.header()
230
- self.assertEqual(header, ['title', 'description', 'alias', 'tags'])
218
+ self.assertEqual(header, ["title", "description", "alias", "tags"])
231
219
 
232
220
  rows = list(adapter.rows())
233
221
  self.assertEqual(len(rows), len(objects))
@@ -236,15 +224,14 @@ class CsvTest(FrontTestCase):
236
224
  self.assertEqual(row[0], obj.title)
237
225
  self.assertEqual(row[1], obj.description)
238
226
  self.assertEqual(row[2], obj.title)
239
- self.assertEqual(row[3], ','.join(obj.tags))
227
+ self.assertEqual(row[3], ",".join(obj.tags))
240
228
 
241
229
  def test_metric_fields(self):
242
230
  expected = {
243
- 'metric.fake-metric-int': 5,
244
- 'metric.fake-metric-float': 0.5,
231
+ "metric.fake-metric-int": 5,
232
+ "metric.fake-metric-float": 0.5,
245
233
  }
246
- fake = FakeFactory(
247
- metrics={'fake-metric-int': 5, 'fake-metric-float': 0.5})
234
+ fake = FakeFactory(metrics={"fake-metric-int": 5, "fake-metric-float": 0.5})
248
235
 
249
236
  fields = csv.metric_fields(Fake)
250
237
  self.assertEqual(len(fields), len(expected))
@@ -255,13 +242,13 @@ class CsvTest(FrontTestCase):
255
242
  def test_unicode(self):
256
243
  @csv.adapter(Fake)
257
244
  class Adapter(csv.Adapter):
258
- fields = ['title', 'description']
245
+ fields = ["title", "description"]
259
246
 
260
- objects = FakeFactory.build_batch(3, description='é\xe9')
247
+ objects = FakeFactory.build_batch(3, description="é\xe9")
261
248
  adapter = Adapter(objects)
262
249
 
263
250
  header = adapter.header()
264
- self.assertEqual(header, ['title', 'description'])
251
+ self.assertEqual(header, ["title", "description"])
265
252
 
266
253
  rows = list(adapter.rows())
267
254
  self.assertEqual(len(rows), len(objects))
@@ -279,18 +266,18 @@ class CsvTest(FrontTestCase):
279
266
  def assert_csv(self, endpoint, objects):
280
267
  @csv.adapter(Fake)
281
268
  class Adapter(csv.Adapter):
282
- fields = ['title', 'description']
269
+ fields = ["title", "description"]
283
270
 
284
271
  response = self.get(url_for(endpoint))
285
272
 
286
273
  self.assert200(response)
287
- self.assertEqual(response.mimetype, 'text/csv')
288
- self.assertEqual(response.charset, 'utf-8')
274
+ self.assertEqual(response.mimetype, "text/csv")
275
+ self.assertEqual(response.charset, "utf-8")
289
276
 
290
- csvfile = StringIO(response.data.decode('utf8'))
277
+ csvfile = StringIO(response.data.decode("utf8"))
291
278
  reader = csv.get_reader(csvfile)
292
279
  header = next(reader)
293
- self.assertEqual(header, ['title', 'description'])
280
+ self.assertEqual(header, ["title", "description"])
294
281
 
295
282
  rows = list(reader)
296
283
  self.assertEqual(len(rows), len(objects))
@@ -302,55 +289,53 @@ class CsvTest(FrontTestCase):
302
289
  return response
303
290
 
304
291
  def assert_filename(self, response, basename):
305
- header = response.headers['Content-Disposition']
292
+ header = response.headers["Content-Disposition"]
306
293
  m = RE_ATTACHMENT.match(header)
307
- self.assertIsNotNone(
308
- m,
309
- 'Content-Disposition header should specify a filename attachment')
310
- filename = m.group('filename')
294
+ self.assertIsNotNone(m, "Content-Disposition header should specify a filename attachment")
295
+ filename = m.group("filename")
311
296
  m = RE_FILENAME.match(filename)
312
- self.assertIsNotNone(m, 'filename should have the right pattern')
313
- self.assertEqual(m.group('basename'), basename)
297
+ self.assertIsNotNone(m, "filename should have the right pattern")
298
+ self.assertEqual(m.group("basename"), basename)
314
299
 
315
300
  def test_stream_from_adapter(self):
316
- response = self.assert_stream_csv('testcsv.from_adapter')
317
- self.assert_filename(response, 'export')
301
+ response = self.assert_stream_csv("testcsv.from_adapter")
302
+ self.assert_filename(response, "export")
318
303
 
319
304
  def test_stream_from_queryset(self):
320
- response = self.assert_stream_csv('testcsv.from_queryset')
321
- self.assert_filename(response, 'export')
305
+ response = self.assert_stream_csv("testcsv.from_queryset")
306
+ self.assert_filename(response, "export")
322
307
 
323
308
  def test_stream_from_list(self):
324
- response = self.assert_stream_csv('testcsv.from_list')
325
- self.assert_filename(response, 'export')
309
+ response = self.assert_stream_csv("testcsv.from_list")
310
+ self.assert_filename(response, "export")
326
311
 
327
312
  def test_stream_with_basename(self):
328
- response = self.assert_stream_csv('testcsv.with_basename')
329
- self.assert_filename(response, 'test')
313
+ response = self.assert_stream_csv("testcsv.with_basename")
314
+ self.assert_filename(response, "test")
330
315
 
331
316
  def test_empty_stream_from_adapter(self):
332
- response = self.assert_empty_stream_csv('testcsv.from_adapter')
333
- self.assert_filename(response, 'export')
317
+ response = self.assert_empty_stream_csv("testcsv.from_adapter")
318
+ self.assert_filename(response, "export")
334
319
 
335
320
  def test_empty_stream_from_queryset(self):
336
- response = self.assert_empty_stream_csv('testcsv.from_queryset')
337
- self.assert_filename(response, 'export')
321
+ response = self.assert_empty_stream_csv("testcsv.from_queryset")
322
+ self.assert_filename(response, "export")
338
323
 
339
324
  def test_stream_nested_from_adapter(self):
340
325
  fake = FakeFactory.build()
341
326
  for i in range(3):
342
327
  fake.nested.append(NestedFake(key=faker.word(), value=i))
343
328
  fake.save()
344
- response = self.get(url_for('testcsv.from_nested'))
329
+ response = self.get(url_for("testcsv.from_nested"))
345
330
 
346
331
  self.assert200(response)
347
- self.assertEqual(response.mimetype, 'text/csv')
348
- self.assertEqual(response.charset, 'utf-8')
332
+ self.assertEqual(response.mimetype, "text/csv")
333
+ self.assertEqual(response.charset, "utf-8")
349
334
 
350
- csvfile = StringIO(response.data.decode('utf8'))
335
+ csvfile = StringIO(response.data.decode("utf8"))
351
336
  reader = csv.get_reader(csvfile)
352
337
  header = next(reader)
353
- self.assertEqual(header, ['title', 'description', 'key', 'alias'])
338
+ self.assertEqual(header, ["title", "description", "key", "alias"])
354
339
 
355
340
  rows = list(reader)
356
341
  self.assertEqual(len(rows), len(fake.nested))
@@ -362,17 +347,17 @@ class CsvTest(FrontTestCase):
362
347
  self.assertEqual(row[3], str(obj.value))
363
348
 
364
349
  def test_stream_unicode(self):
365
- fake = FakeFactory(title='é\xe9')
366
- response = self.get(url_for('testcsv.from_adapter'))
350
+ fake = FakeFactory(title="é\xe9")
351
+ response = self.get(url_for("testcsv.from_adapter"))
367
352
 
368
353
  self.assert200(response)
369
- self.assertEqual(response.mimetype, 'text/csv')
370
- self.assertEqual(response.charset, 'utf-8')
354
+ self.assertEqual(response.mimetype, "text/csv")
355
+ self.assertEqual(response.charset, "utf-8")
371
356
 
372
- csvfile = StringIO(response.data.decode('utf8'))
357
+ csvfile = StringIO(response.data.decode("utf8"))
373
358
  reader = csv.get_reader(csvfile)
374
359
  header = next(reader)
375
- self.assertEqual(header, ['title', 'description'])
360
+ self.assertEqual(header, ["title", "description"])
376
361
 
377
362
  row = next(reader)
378
363
  self.assertEqual(len(row), len(header))
@@ -1,93 +1,93 @@
1
1
  import pytest
2
-
3
2
  from flask import Blueprint, render_template_string, url_for
3
+
4
4
  from udata.frontend import template_hook
5
5
  from udata.tests.helpers import assert200
6
6
 
7
- bp = Blueprint('hooks_tests', __name__, url_prefix='/hooks_tests')
7
+ bp = Blueprint("hooks_tests", __name__, url_prefix="/hooks_tests")
8
8
 
9
9
 
10
10
  @template_hook
11
11
  def single(ctx):
12
- return 'single'
12
+ return "single"
13
13
 
14
14
 
15
15
  @template_hook
16
16
  def hello(ctx, name):
17
- return 'Hello {}'.format(name)
17
+ return "Hello {}".format(name)
18
18
 
19
19
 
20
20
  @template_hook
21
21
  def kwargs(ctx, **kwargs):
22
- return ', '.join(sorted('{0}={1}'.format(k, v) for k, v in kwargs.items()))
22
+ return ", ".join(sorted("{0}={1}".format(k, v) for k, v in kwargs.items()))
23
23
 
24
24
 
25
- @template_hook('multiple')
25
+ @template_hook("multiple")
26
26
  def first(ctx):
27
- return 'first'
27
+ return "first"
28
28
 
29
29
 
30
- @template_hook('multiple')
30
+ @template_hook("multiple")
31
31
  def second(ctx):
32
- return 'second'
32
+ return "second"
33
33
 
34
34
 
35
- @template_hook('conditionnal', when=lambda ctx: True)
35
+ @template_hook("conditionnal", when=lambda ctx: True)
36
36
  def true(ctx):
37
- return 'true'
37
+ return "true"
38
38
 
39
39
 
40
- @template_hook('conditionnal', when=lambda ctx: False)
40
+ @template_hook("conditionnal", when=lambda ctx: False)
41
41
  def false(ctx):
42
- return 'false'
42
+ return "false"
43
43
 
44
44
 
45
- @bp.route('/empty/render')
45
+ @bp.route("/empty/render")
46
46
  def render_empty():
47
47
  return render_template_string('{{ hook("empty") }}')
48
48
 
49
49
 
50
- @bp.route('/empty/iter')
50
+ @bp.route("/empty/iter")
51
51
  def iter_empty():
52
52
  return render_template_string('{% for w in hook("empty") %}<{{ w }}>{% endfor %}')
53
53
 
54
54
 
55
- @bp.route('/hello')
55
+ @bp.route("/hello")
56
56
  def render_hello():
57
57
  return render_template_string('{{ hook("hello", "world") }}')
58
58
 
59
59
 
60
- @bp.route('/kwargs')
60
+ @bp.route("/kwargs")
61
61
  def render_kwargs():
62
62
  return render_template_string('{{ hook("kwargs", key="value", other=42) }}')
63
63
 
64
64
 
65
- @bp.route('/single/render')
65
+ @bp.route("/single/render")
66
66
  def render_single():
67
67
  return render_template_string('{{ hook("single") }}')
68
68
 
69
69
 
70
- @bp.route('/single/iter')
70
+ @bp.route("/single/iter")
71
71
  def iter_single():
72
72
  return render_template_string('{% for w in hook("single") %}<{{ w }}>{% endfor %}')
73
73
 
74
74
 
75
- @bp.route('/multiple/render')
75
+ @bp.route("/multiple/render")
76
76
  def render_multiple():
77
77
  return render_template_string('{{ hook("multiple") }}')
78
78
 
79
79
 
80
- @bp.route('/multiple/iter')
80
+ @bp.route("/multiple/iter")
81
81
  def iter_multiple():
82
82
  return render_template_string('{% for w in hook("multiple") %}<{{ w }}>{% endfor %}')
83
83
 
84
84
 
85
- @bp.route('/conditionnal/render')
85
+ @bp.route("/conditionnal/render")
86
86
  def render_conditionnal():
87
87
  return render_template_string('{{ hook("conditionnal") }}')
88
88
 
89
89
 
90
- @bp.route('/conditionnal/iter')
90
+ @bp.route("/conditionnal/iter")
91
91
  def iter_conditionnal():
92
92
  return render_template_string('{% for w in hook("conditionnal") %}<{{ w }}>{% endfor %}')
93
93
 
@@ -101,51 +101,51 @@ def app(app):
101
101
  @pytest.mark.frontend
102
102
  class HooksTest:
103
103
  def test_empty_template_hook(self, client):
104
- response = client.get(url_for('hooks_tests.render_empty'))
104
+ response = client.get(url_for("hooks_tests.render_empty"))
105
105
  assert200(response)
106
- assert b'' == response.data
106
+ assert b"" == response.data
107
107
 
108
108
  def test_iter_empty_template_hook(self, client):
109
- response = client.get(url_for('hooks_tests.iter_empty'))
109
+ response = client.get(url_for("hooks_tests.iter_empty"))
110
110
  assert200(response)
111
- assert b'' == response.data
111
+ assert b"" == response.data
112
112
 
113
113
  def test_single_template_hook(self, client):
114
- response = client.get(url_for('hooks_tests.render_single'))
114
+ response = client.get(url_for("hooks_tests.render_single"))
115
115
  assert200(response)
116
- assert b'single' == response.data
116
+ assert b"single" == response.data
117
117
 
118
118
  def test_iter_single_template_hook(self, client):
119
- response = client.get(url_for('hooks_tests.iter_single'))
119
+ response = client.get(url_for("hooks_tests.iter_single"))
120
120
  assert200(response)
121
- assert b'<single>' == response.data
121
+ assert b"<single>" == response.data
122
122
 
123
123
  def test_multiple_template_hooks(self, client):
124
- response = client.get(url_for('hooks_tests.render_multiple'))
124
+ response = client.get(url_for("hooks_tests.render_multiple"))
125
125
  assert200(response)
126
- assert b'firstsecond' == response.data
126
+ assert b"firstsecond" == response.data
127
127
 
128
128
  def test_iter_multiple_template_hooks(self, client):
129
- response = client.get(url_for('hooks_tests.iter_multiple'))
129
+ response = client.get(url_for("hooks_tests.iter_multiple"))
130
130
  assert200(response)
131
- assert b'<first><second>' == response.data
131
+ assert b"<first><second>" == response.data
132
132
 
133
133
  def test_conditionnal_template_hooks(self, client):
134
- response = client.get(url_for('hooks_tests.render_conditionnal'))
134
+ response = client.get(url_for("hooks_tests.render_conditionnal"))
135
135
  assert200(response)
136
- assert b'true' == response.data
136
+ assert b"true" == response.data
137
137
 
138
138
  def test_iter_conditionnal_template_hooks(self, client):
139
- response = client.get(url_for('hooks_tests.iter_conditionnal'))
139
+ response = client.get(url_for("hooks_tests.iter_conditionnal"))
140
140
  assert200(response)
141
- assert b'<true>' == response.data
141
+ assert b"<true>" == response.data
142
142
 
143
143
  def test_arguments(self, client):
144
- response = client.get(url_for('hooks_tests.render_hello'))
144
+ response = client.get(url_for("hooks_tests.render_hello"))
145
145
  assert200(response)
146
- assert b'Hello world' == response.data
146
+ assert b"Hello world" == response.data
147
147
 
148
148
  def test_kwargs(self, client):
149
- response = client.get(url_for('hooks_tests.render_kwargs'))
149
+ response = client.get(url_for("hooks_tests.render_kwargs"))
150
150
  assert200(response)
151
- assert b'key=value, other=42' == response.data
151
+ assert b"key=value, other=42" == response.data