kinto 19.4.0__tar.gz → 19.6.0__tar.gz

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.
Files changed (415) hide show
  1. {kinto-19.4.0 → kinto-19.6.0}/.github/workflows/publish.yml +9 -0
  2. kinto-19.6.0/.github/workflows/scheduled.yml +85 -0
  3. {kinto-19.4.0 → kinto-19.6.0}/.github/workflows/test.yml +7 -4
  4. kinto-19.6.0/.readthedocs.yaml +12 -0
  5. {kinto-19.4.0 → kinto-19.6.0}/CONTRIBUTORS.rst +1 -0
  6. {kinto-19.4.0 → kinto-19.6.0}/Dockerfile +0 -1
  7. {kinto-19.4.0 → kinto-19.6.0}/Makefile +1 -1
  8. {kinto-19.4.0/kinto.egg-info → kinto-19.6.0}/PKG-INFO +3 -4
  9. {kinto-19.4.0 → kinto-19.6.0}/constraints.in +1 -3
  10. {kinto-19.4.0 → kinto-19.6.0}/constraints.txt +8 -22
  11. {kinto-19.4.0 → kinto-19.6.0}/docs/conf.py +1 -2
  12. {kinto-19.4.0 → kinto-19.6.0}/docs/requirements.txt +2 -3
  13. {kinto-19.4.0 → kinto-19.6.0}/docs/troubleshooting.rst +1 -1
  14. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/__init__.py +3 -3
  15. kinto-19.6.0/kinto/core/cornice/__init__.py +93 -0
  16. kinto-19.6.0/kinto/core/cornice/cors.py +144 -0
  17. kinto-19.6.0/kinto/core/cornice/errors.py +40 -0
  18. kinto-19.6.0/kinto/core/cornice/pyramidhook.py +373 -0
  19. kinto-19.6.0/kinto/core/cornice/renderer.py +89 -0
  20. kinto-19.6.0/kinto/core/cornice/resource.py +205 -0
  21. kinto-19.6.0/kinto/core/cornice/service.py +641 -0
  22. kinto-19.6.0/kinto/core/cornice/util.py +138 -0
  23. kinto-19.6.0/kinto/core/cornice/validators/__init__.py +94 -0
  24. kinto-19.6.0/kinto/core/cornice/validators/_colander.py +142 -0
  25. kinto-19.6.0/kinto/core/cornice/validators/_marshmallow.py +182 -0
  26. kinto-19.6.0/kinto/core/cornice_swagger/__init__.py +92 -0
  27. kinto-19.6.0/kinto/core/cornice_swagger/converters/__init__.py +21 -0
  28. kinto-19.6.0/kinto/core/cornice_swagger/converters/exceptions.py +6 -0
  29. kinto-19.6.0/kinto/core/cornice_swagger/converters/parameters.py +90 -0
  30. kinto-19.6.0/kinto/core/cornice_swagger/converters/schema.py +249 -0
  31. kinto-19.6.0/kinto/core/cornice_swagger/swagger.py +725 -0
  32. kinto-19.6.0/kinto/core/cornice_swagger/templates/index.html +73 -0
  33. kinto-19.6.0/kinto/core/cornice_swagger/templates/index_script_template.html +21 -0
  34. kinto-19.6.0/kinto/core/cornice_swagger/util.py +42 -0
  35. kinto-19.6.0/kinto/core/cornice_swagger/views.py +78 -0
  36. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/errors.py +6 -4
  37. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/openapi.py +2 -3
  38. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/permission/memory.py +3 -2
  39. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/permission/testing.py +6 -0
  40. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/resource/viewset.py +1 -1
  41. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/testing.py +1 -1
  42. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/utils.py +3 -2
  43. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/views/batch.py +1 -1
  44. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/views/openapi.py +1 -1
  45. kinto-19.6.0/kinto/plugins/admin/VERSION +1 -0
  46. kinto-19.6.0/kinto/plugins/admin/build/VERSION +1 -0
  47. kinto-19.4.0/kinto/plugins/admin/build/assets/index-D8oiN37x.css → kinto-19.6.0/kinto/plugins/admin/build/assets/index-BdpYyatM.css +1 -1
  48. kinto-19.4.0/kinto/plugins/admin/build/assets/index-BKIg2XW8.js → kinto-19.6.0/kinto/plugins/admin/build/assets/index-n-QM_iZE.js +65 -65
  49. {kinto-19.4.0 → kinto-19.6.0}/kinto/plugins/admin/build/index.html +2 -2
  50. {kinto-19.4.0 → kinto-19.6.0}/kinto/plugins/flush.py +1 -1
  51. {kinto-19.4.0 → kinto-19.6.0}/kinto/plugins/openid/views.py +1 -1
  52. {kinto-19.4.0 → kinto-19.6.0}/kinto/views/contribute.py +2 -1
  53. {kinto-19.4.0 → kinto-19.6.0/kinto.egg-info}/PKG-INFO +3 -4
  54. {kinto-19.4.0 → kinto-19.6.0}/kinto.egg-info/SOURCES.txt +25 -2
  55. {kinto-19.4.0 → kinto-19.6.0}/kinto.egg-info/requires.txt +1 -3
  56. {kinto-19.4.0 → kinto-19.6.0}/pyproject.toml +5 -3
  57. {kinto-19.4.0 → kinto-19.6.0}/tests/core/resource/test_viewset.py +1 -1
  58. {kinto-19.4.0 → kinto-19.6.0}/tests/core/test_openapi.py +1 -2
  59. {kinto-19.4.0 → kinto-19.6.0}/tests/test_views_buckets.py +8 -0
  60. kinto-19.4.0/kinto/plugins/admin/VERSION +0 -1
  61. kinto-19.4.0/kinto/plugins/admin/build/VERSION +0 -1
  62. {kinto-19.4.0 → kinto-19.6.0}/.dockerignore +0 -0
  63. {kinto-19.4.0 → kinto-19.6.0}/.github/CODE_OF_CONDUCT.md +0 -0
  64. {kinto-19.4.0 → kinto-19.6.0}/.github/CONTRIBUTING.md +0 -0
  65. {kinto-19.4.0 → kinto-19.6.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  66. {kinto-19.4.0 → kinto-19.6.0}/.github/dependabot.yml +0 -0
  67. {kinto-19.4.0 → kinto-19.6.0}/.github/release.yml +0 -0
  68. {kinto-19.4.0 → kinto-19.6.0}/.github/workflows/labels.yaml +0 -0
  69. {kinto-19.4.0 → kinto-19.6.0}/.gitignore +0 -0
  70. {kinto-19.4.0 → kinto-19.6.0}/CHANGELOG.rst +0 -0
  71. {kinto-19.4.0 → kinto-19.6.0}/LICENSE +0 -0
  72. {kinto-19.4.0 → kinto-19.6.0}/README.rst +0 -0
  73. {kinto-19.4.0 → kinto-19.6.0}/SECURITY.md +0 -0
  74. {kinto-19.4.0 → kinto-19.6.0}/SUPPORT.md +0 -0
  75. {kinto-19.4.0 → kinto-19.6.0}/app.wsgi +0 -0
  76. {kinto-19.4.0 → kinto-19.6.0}/contribute.json +0 -0
  77. {kinto-19.4.0 → kinto-19.6.0}/docker-compose.yml +0 -0
  78. {kinto-19.4.0 → kinto-19.6.0}/docs/_static/piwik.js +0 -0
  79. {kinto-19.4.0 → kinto-19.6.0}/docs/_static/theme_overrides.css +0 -0
  80. {kinto-19.4.0 → kinto-19.6.0}/docs/_templates/footer.html +0 -0
  81. {kinto-19.4.0 → kinto-19.6.0}/docs/_templates/indexcontent.html +0 -0
  82. {kinto-19.4.0 → kinto-19.6.0}/docs/_templates/layout.html +0 -0
  83. {kinto-19.4.0 → kinto-19.6.0}/docs/api/1.x/_details-delete-list.rst +0 -0
  84. {kinto-19.4.0 → kinto-19.6.0}/docs/api/1.x/_details-delete-object.rst +0 -0
  85. {kinto-19.4.0 → kinto-19.6.0}/docs/api/1.x/_details-get-list.rst +0 -0
  86. {kinto-19.4.0 → kinto-19.6.0}/docs/api/1.x/_details-get-object.rst +0 -0
  87. {kinto-19.4.0 → kinto-19.6.0}/docs/api/1.x/_details-head-list.rst +0 -0
  88. {kinto-19.4.0 → kinto-19.6.0}/docs/api/1.x/_details-patch-object.rst +0 -0
  89. {kinto-19.4.0 → kinto-19.6.0}/docs/api/1.x/_details-post-list.rst +0 -0
  90. {kinto-19.4.0 → kinto-19.6.0}/docs/api/1.x/_details-put-object.rst +0 -0
  91. {kinto-19.4.0 → kinto-19.6.0}/docs/api/1.x/_status-delete-list.rst +0 -0
  92. {kinto-19.4.0 → kinto-19.6.0}/docs/api/1.x/_status-delete-object.rst +0 -0
  93. {kinto-19.4.0 → kinto-19.6.0}/docs/api/1.x/_status-get-list.rst +0 -0
  94. {kinto-19.4.0 → kinto-19.6.0}/docs/api/1.x/_status-get-object.rst +0 -0
  95. {kinto-19.4.0 → kinto-19.6.0}/docs/api/1.x/_status-patch-object.rst +0 -0
  96. {kinto-19.4.0 → kinto-19.6.0}/docs/api/1.x/_status-post-list.rst +0 -0
  97. {kinto-19.4.0 → kinto-19.6.0}/docs/api/1.x/_status-put-object.rst +0 -0
  98. {kinto-19.4.0 → kinto-19.6.0}/docs/api/1.x/accounts.rst +0 -0
  99. {kinto-19.4.0 → kinto-19.6.0}/docs/api/1.x/admin.rst +0 -0
  100. {kinto-19.4.0 → kinto-19.6.0}/docs/api/1.x/authentication.rst +0 -0
  101. {kinto-19.4.0 → kinto-19.6.0}/docs/api/1.x/backoff.rst +0 -0
  102. {kinto-19.4.0 → kinto-19.6.0}/docs/api/1.x/batch.rst +0 -0
  103. {kinto-19.4.0 → kinto-19.6.0}/docs/api/1.x/buckets.rst +0 -0
  104. {kinto-19.4.0 → kinto-19.6.0}/docs/api/1.x/collections.rst +0 -0
  105. {kinto-19.4.0 → kinto-19.6.0}/docs/api/1.x/deprecation.rst +0 -0
  106. {kinto-19.4.0 → kinto-19.6.0}/docs/api/1.x/errors.rst +0 -0
  107. {kinto-19.4.0 → kinto-19.6.0}/docs/api/1.x/filtering.rst +0 -0
  108. {kinto-19.4.0 → kinto-19.6.0}/docs/api/1.x/flush.rst +0 -0
  109. {kinto-19.4.0 → kinto-19.6.0}/docs/api/1.x/groups.rst +0 -0
  110. {kinto-19.4.0 → kinto-19.6.0}/docs/api/1.x/history.rst +0 -0
  111. {kinto-19.4.0 → kinto-19.6.0}/docs/api/1.x/index.rst +0 -0
  112. {kinto-19.4.0 → kinto-19.6.0}/docs/api/1.x/openapi.rst +0 -0
  113. {kinto-19.4.0 → kinto-19.6.0}/docs/api/1.x/openid.rst +0 -0
  114. {kinto-19.4.0 → kinto-19.6.0}/docs/api/1.x/pagination.rst +0 -0
  115. {kinto-19.4.0 → kinto-19.6.0}/docs/api/1.x/permissions.rst +0 -0
  116. {kinto-19.4.0 → kinto-19.6.0}/docs/api/1.x/quotas.rst +0 -0
  117. {kinto-19.4.0 → kinto-19.6.0}/docs/api/1.x/records.rst +0 -0
  118. {kinto-19.4.0 → kinto-19.6.0}/docs/api/1.x/selecting_fields.rst +0 -0
  119. {kinto-19.4.0 → kinto-19.6.0}/docs/api/1.x/sorting.rst +0 -0
  120. {kinto-19.4.0 → kinto-19.6.0}/docs/api/1.x/timestamps.rst +0 -0
  121. {kinto-19.4.0 → kinto-19.6.0}/docs/api/1.x/utilities.rst +0 -0
  122. {kinto-19.4.0 → kinto-19.6.0}/docs/api/index.rst +0 -0
  123. {kinto-19.4.0 → kinto-19.6.0}/docs/api/versioning.rst +0 -0
  124. {kinto-19.4.0 → kinto-19.6.0}/docs/changelog.rst +0 -0
  125. {kinto-19.4.0 → kinto-19.6.0}/docs/commandline.rst +0 -0
  126. {kinto-19.4.0 → kinto-19.6.0}/docs/community.rst +0 -0
  127. {kinto-19.4.0 → kinto-19.6.0}/docs/concepts.rst +0 -0
  128. {kinto-19.4.0 → kinto-19.6.0}/docs/configuration/good-practices.rst +0 -0
  129. {kinto-19.4.0 → kinto-19.6.0}/docs/configuration/index.rst +0 -0
  130. {kinto-19.4.0 → kinto-19.6.0}/docs/configuration/production.rst +0 -0
  131. {kinto-19.4.0 → kinto-19.6.0}/docs/configuration/settings.rst +0 -0
  132. {kinto-19.4.0 → kinto-19.6.0}/docs/core/_static/theme_overrides.css +0 -0
  133. {kinto-19.4.0 → kinto-19.6.0}/docs/core/api.rst +0 -0
  134. {kinto-19.4.0 → kinto-19.6.0}/docs/core/cache.rst +0 -0
  135. {kinto-19.4.0 → kinto-19.6.0}/docs/core/decorators.rst +0 -0
  136. {kinto-19.4.0 → kinto-19.6.0}/docs/core/errors.rst +0 -0
  137. {kinto-19.4.0 → kinto-19.6.0}/docs/core/glossary.rst +0 -0
  138. {kinto-19.4.0 → kinto-19.6.0}/docs/core/images/cliquet-base.png +0 -0
  139. {kinto-19.4.0 → kinto-19.6.0}/docs/core/images/cliquet-mozilla.png +0 -0
  140. {kinto-19.4.0 → kinto-19.6.0}/docs/core/index.rst +0 -0
  141. {kinto-19.4.0 → kinto-19.6.0}/docs/core/notifications.rst +0 -0
  142. {kinto-19.4.0 → kinto-19.6.0}/docs/core/permission.rst +0 -0
  143. {kinto-19.4.0 → kinto-19.6.0}/docs/core/quickstart.rst +0 -0
  144. {kinto-19.4.0 → kinto-19.6.0}/docs/core/rationale.rst +0 -0
  145. {kinto-19.4.0 → kinto-19.6.0}/docs/core/resource.rst +0 -0
  146. {kinto-19.4.0 → kinto-19.6.0}/docs/core/storage.rst +0 -0
  147. {kinto-19.4.0 → kinto-19.6.0}/docs/core/testing.rst +0 -0
  148. {kinto-19.4.0 → kinto-19.6.0}/docs/core/utils.rst +0 -0
  149. {kinto-19.4.0 → kinto-19.6.0}/docs/core/viewsets.rst +0 -0
  150. {kinto-19.4.0 → kinto-19.6.0}/docs/faq.rst +0 -0
  151. {kinto-19.4.0 → kinto-19.6.0}/docs/images/alwaysdata-button.svg +0 -0
  152. {kinto-19.4.0 → kinto-19.6.0}/docs/images/architecture.svg +0 -0
  153. {kinto-19.4.0 → kinto-19.6.0}/docs/images/color-formatter.png +0 -0
  154. {kinto-19.4.0 → kinto-19.6.0}/docs/images/concepts-general.png +0 -0
  155. {kinto-19.4.0 → kinto-19.6.0}/docs/images/concepts-permissions.png +0 -0
  156. {kinto-19.4.0 → kinto-19.6.0}/docs/images/heroku-button.png +0 -0
  157. {kinto-19.4.0 → kinto-19.6.0}/docs/images/kinto-logo.png +0 -0
  158. {kinto-19.4.0 → kinto-19.6.0}/docs/images/kinto-logo.svg +0 -0
  159. {kinto-19.4.0 → kinto-19.6.0}/docs/images/logo-admin.svg +0 -0
  160. {kinto-19.4.0 → kinto-19.6.0}/docs/images/logo-attachment.svg +0 -0
  161. {kinto-19.4.0 → kinto-19.6.0}/docs/images/logo-community.svg +0 -0
  162. {kinto-19.4.0 → kinto-19.6.0}/docs/images/logo-demos.svg +0 -0
  163. {kinto-19.4.0 → kinto-19.6.0}/docs/images/logo-history.svg +0 -0
  164. {kinto-19.4.0 → kinto-19.6.0}/docs/images/logo-indexing.svg +0 -0
  165. {kinto-19.4.0 → kinto-19.6.0}/docs/images/logo-javascript.svg +0 -0
  166. {kinto-19.4.0 → kinto-19.6.0}/docs/images/logo-jsonschema.svg +0 -0
  167. {kinto-19.4.0 → kinto-19.6.0}/docs/images/logo-livesync.svg +0 -0
  168. {kinto-19.4.0 → kinto-19.6.0}/docs/images/logo-multiapps.svg +0 -0
  169. {kinto-19.4.0 → kinto-19.6.0}/docs/images/logo-offline.svg +0 -0
  170. {kinto-19.4.0 → kinto-19.6.0}/docs/images/logo-permissions.svg +0 -0
  171. {kinto-19.4.0 → kinto-19.6.0}/docs/images/logo-python.svg +0 -0
  172. {kinto-19.4.0 → kinto-19.6.0}/docs/images/logo-quotas.svg +0 -0
  173. {kinto-19.4.0 → kinto-19.6.0}/docs/images/logo-selfhostable.svg +0 -0
  174. {kinto-19.4.0 → kinto-19.6.0}/docs/images/logo-signature.svg +0 -0
  175. {kinto-19.4.0 → kinto-19.6.0}/docs/images/logo-synchronisation.svg +0 -0
  176. {kinto-19.4.0 → kinto-19.6.0}/docs/images/overview-deployonce-selfhost.png +0 -0
  177. {kinto-19.4.0 → kinto-19.6.0}/docs/images/overview-features.png +0 -0
  178. {kinto-19.4.0 → kinto-19.6.0}/docs/images/overview-synchronisation.png +0 -0
  179. {kinto-19.4.0 → kinto-19.6.0}/docs/images/overview-use-cases.png +0 -0
  180. {kinto-19.4.0 → kinto-19.6.0}/docs/images/scalingo-button.svg +0 -0
  181. {kinto-19.4.0 → kinto-19.6.0}/docs/images/screenshot-kinto-admin-1.png +0 -0
  182. {kinto-19.4.0 → kinto-19.6.0}/docs/images/screenshot-kinto-admin-2.png +0 -0
  183. {kinto-19.4.0 → kinto-19.6.0}/docs/images/screenshot-kinto-admin-3.png +0 -0
  184. {kinto-19.4.0 → kinto-19.6.0}/docs/images/screenshot-kinto-admin-4.png +0 -0
  185. {kinto-19.4.0 → kinto-19.6.0}/docs/images/sequence-storage.png +0 -0
  186. {kinto-19.4.0 → kinto-19.6.0}/docs/images/sync-both.svg +0 -0
  187. {kinto-19.4.0 → kinto-19.6.0}/docs/images/sync-newest.svg +0 -0
  188. {kinto-19.4.0 → kinto-19.6.0}/docs/images/sync-oldest.svg +0 -0
  189. {kinto-19.4.0 → kinto-19.6.0}/docs/index.rst +0 -0
  190. {kinto-19.4.0 → kinto-19.6.0}/docs/kinto-admin.rst +0 -0
  191. {kinto-19.4.0 → kinto-19.6.0}/docs/overview.rst +0 -0
  192. {kinto-19.4.0 → kinto-19.6.0}/docs/tutorials/app-examples.rst +0 -0
  193. {kinto-19.4.0 → kinto-19.6.0}/docs/tutorials/authentication-github.rst +0 -0
  194. {kinto-19.4.0 → kinto-19.6.0}/docs/tutorials/client-side-encryption.rst +0 -0
  195. {kinto-19.4.0 → kinto-19.6.0}/docs/tutorials/custom-id-generator.rst +0 -0
  196. {kinto-19.4.0 → kinto-19.6.0}/docs/tutorials/first-steps.rst +0 -0
  197. {kinto-19.4.0 → kinto-19.6.0}/docs/tutorials/index.rst +0 -0
  198. {kinto-19.4.0 → kinto-19.6.0}/docs/tutorials/install.rst +0 -0
  199. {kinto-19.4.0 → kinto-19.6.0}/docs/tutorials/notifications-custom.rst +0 -0
  200. {kinto-19.4.0 → kinto-19.6.0}/docs/tutorials/notifications-websockets.rst +0 -0
  201. {kinto-19.4.0 → kinto-19.6.0}/docs/tutorials/permission-setups.rst +0 -0
  202. {kinto-19.4.0 → kinto-19.6.0}/docs/tutorials/permissions.rst +0 -0
  203. {kinto-19.4.0 → kinto-19.6.0}/docs/tutorials/synchronisation.rst +0 -0
  204. {kinto-19.4.0 → kinto-19.6.0}/docs/tutorials/write-plugin.rst +0 -0
  205. {kinto-19.4.0 → kinto-19.6.0}/kinto/__init__.py +0 -0
  206. {kinto-19.4.0 → kinto-19.6.0}/kinto/__main__.py +0 -0
  207. {kinto-19.4.0 → kinto-19.6.0}/kinto/authorization.py +0 -0
  208. {kinto-19.4.0 → kinto-19.6.0}/kinto/config/__init__.py +0 -0
  209. {kinto-19.4.0 → kinto-19.6.0}/kinto/config/kinto.tpl +0 -0
  210. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/authentication.py +0 -0
  211. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/authorization.py +0 -0
  212. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/cache/__init__.py +0 -0
  213. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/cache/memcached.py +0 -0
  214. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/cache/memory.py +0 -0
  215. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/cache/postgresql/__init__.py +0 -0
  216. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/cache/postgresql/schema.sql +0 -0
  217. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/cache/testing.py +0 -0
  218. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/decorators.py +0 -0
  219. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/events.py +0 -0
  220. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/initialization.py +0 -0
  221. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/listeners/__init__.py +0 -0
  222. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/metrics.py +0 -0
  223. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/permission/__init__.py +0 -0
  224. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/permission/postgresql/__init__.py +0 -0
  225. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/permission/postgresql/migrations/migration_001_002.sql +0 -0
  226. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/permission/postgresql/schema.sql +0 -0
  227. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/resource/__init__.py +0 -0
  228. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/resource/model.py +0 -0
  229. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/resource/schema.py +0 -0
  230. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/schema.py +0 -0
  231. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/scripts.py +0 -0
  232. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/statsd.py +0 -0
  233. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/storage/__init__.py +0 -0
  234. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/storage/exceptions.py +0 -0
  235. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/storage/generators.py +0 -0
  236. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/storage/memory.py +0 -0
  237. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/storage/postgresql/__init__.py +0 -0
  238. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/storage/postgresql/client.py +0 -0
  239. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/storage/postgresql/migrations/migration_001_002.sql +0 -0
  240. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/storage/postgresql/migrations/migration_002_003.sql +0 -0
  241. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/storage/postgresql/migrations/migration_003_004.sql +0 -0
  242. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/storage/postgresql/migrations/migration_004_005.sql +0 -0
  243. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/storage/postgresql/migrations/migration_005_006.sql +0 -0
  244. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/storage/postgresql/migrations/migration_006_007.sql +0 -0
  245. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/storage/postgresql/migrations/migration_007_008.sql +0 -0
  246. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/storage/postgresql/migrations/migration_008_009.sql +0 -0
  247. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/storage/postgresql/migrations/migration_009_010.sql +0 -0
  248. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/storage/postgresql/migrations/migration_010_011.sql +0 -0
  249. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/storage/postgresql/migrations/migration_011_012.sql +0 -0
  250. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/storage/postgresql/migrations/migration_012_013.sql +0 -0
  251. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/storage/postgresql/migrations/migration_013_014.sql +0 -0
  252. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/storage/postgresql/migrations/migration_014_015.sql +0 -0
  253. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/storage/postgresql/migrations/migration_015_016.sql +0 -0
  254. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/storage/postgresql/migrations/migration_016_017.sql +0 -0
  255. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/storage/postgresql/migrations/migration_017_018.sql +0 -0
  256. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/storage/postgresql/migrations/migration_018_019.sql +0 -0
  257. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/storage/postgresql/migrations/migration_019_020.sql +0 -0
  258. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/storage/postgresql/migrations/migration_020_021.sql +0 -0
  259. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/storage/postgresql/migrations/migration_021_022.sql +0 -0
  260. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/storage/postgresql/migrator.py +0 -0
  261. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/storage/postgresql/pool.py +0 -0
  262. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/storage/postgresql/schema.sql +0 -0
  263. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/storage/testing.py +0 -0
  264. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/storage/utils.py +0 -0
  265. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/views/__init__.py +0 -0
  266. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/views/errors.py +0 -0
  267. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/views/heartbeat.py +0 -0
  268. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/views/hello.py +0 -0
  269. {kinto-19.4.0 → kinto-19.6.0}/kinto/core/views/version.py +0 -0
  270. {kinto-19.4.0 → kinto-19.6.0}/kinto/events.py +0 -0
  271. {kinto-19.4.0 → kinto-19.6.0}/kinto/plugins/__init__.py +0 -0
  272. {kinto-19.4.0 → kinto-19.6.0}/kinto/plugins/accounts/__init__.py +0 -0
  273. {kinto-19.4.0 → kinto-19.6.0}/kinto/plugins/accounts/authentication.py +0 -0
  274. {kinto-19.4.0 → kinto-19.6.0}/kinto/plugins/accounts/mails.py +0 -0
  275. {kinto-19.4.0 → kinto-19.6.0}/kinto/plugins/accounts/scripts.py +0 -0
  276. {kinto-19.4.0 → kinto-19.6.0}/kinto/plugins/accounts/utils.py +0 -0
  277. {kinto-19.4.0 → kinto-19.6.0}/kinto/plugins/accounts/views/__init__.py +0 -0
  278. {kinto-19.4.0 → kinto-19.6.0}/kinto/plugins/accounts/views/validation.py +0 -0
  279. {kinto-19.4.0 → kinto-19.6.0}/kinto/plugins/admin/README.md +0 -0
  280. {kinto-19.4.0 → kinto-19.6.0}/kinto/plugins/admin/__init__.py +0 -0
  281. {kinto-19.4.0 → kinto-19.6.0}/kinto/plugins/admin/build/assets/asn1-CGOzndHr.js +0 -0
  282. {kinto-19.4.0 → kinto-19.6.0}/kinto/plugins/admin/build/assets/clojure-BMjYHr_A.js +0 -0
  283. {kinto-19.4.0 → kinto-19.6.0}/kinto/plugins/admin/build/assets/css-BnMrqG3P.js +0 -0
  284. {kinto-19.4.0 → kinto-19.6.0}/kinto/plugins/admin/build/assets/javascript-iSgyE4tI.js +0 -0
  285. {kinto-19.4.0 → kinto-19.6.0}/kinto/plugins/admin/build/assets/logo-VBRiKSPX.png +0 -0
  286. {kinto-19.4.0 → kinto-19.6.0}/kinto/plugins/admin/build/assets/mllike-C_8OmSiT.js +0 -0
  287. {kinto-19.4.0 → kinto-19.6.0}/kinto/plugins/admin/build/assets/python-BuPzkPfP.js +0 -0
  288. {kinto-19.4.0 → kinto-19.6.0}/kinto/plugins/admin/build/assets/rpm-CTu-6PCP.js +0 -0
  289. {kinto-19.4.0 → kinto-19.6.0}/kinto/plugins/admin/build/assets/sql-C4g8LzGK.js +0 -0
  290. {kinto-19.4.0 → kinto-19.6.0}/kinto/plugins/admin/build/assets/ttcn-cfg-BIkV9KBc.js +0 -0
  291. {kinto-19.4.0 → kinto-19.6.0}/kinto/plugins/admin/public/help.html +0 -0
  292. {kinto-19.4.0 → kinto-19.6.0}/kinto/plugins/admin/views.py +0 -0
  293. {kinto-19.4.0 → kinto-19.6.0}/kinto/plugins/default_bucket/__init__.py +0 -0
  294. {kinto-19.4.0 → kinto-19.6.0}/kinto/plugins/history/__init__.py +0 -0
  295. {kinto-19.4.0 → kinto-19.6.0}/kinto/plugins/history/listener.py +0 -0
  296. {kinto-19.4.0 → kinto-19.6.0}/kinto/plugins/history/views.py +0 -0
  297. {kinto-19.4.0 → kinto-19.6.0}/kinto/plugins/openid/__init__.py +0 -0
  298. {kinto-19.4.0 → kinto-19.6.0}/kinto/plugins/openid/utils.py +0 -0
  299. {kinto-19.4.0 → kinto-19.6.0}/kinto/plugins/prometheus.py +0 -0
  300. {kinto-19.4.0 → kinto-19.6.0}/kinto/plugins/quotas/__init__.py +0 -0
  301. {kinto-19.4.0 → kinto-19.6.0}/kinto/plugins/quotas/listener.py +0 -0
  302. {kinto-19.4.0 → kinto-19.6.0}/kinto/plugins/quotas/scripts.py +0 -0
  303. {kinto-19.4.0 → kinto-19.6.0}/kinto/plugins/quotas/utils.py +0 -0
  304. {kinto-19.4.0 → kinto-19.6.0}/kinto/plugins/statsd.py +0 -0
  305. {kinto-19.4.0 → kinto-19.6.0}/kinto/schema_validation.py +0 -0
  306. {kinto-19.4.0 → kinto-19.6.0}/kinto/scripts.py +0 -0
  307. {kinto-19.4.0 → kinto-19.6.0}/kinto/views/__init__.py +0 -0
  308. {kinto-19.4.0 → kinto-19.6.0}/kinto/views/admin.py +0 -0
  309. {kinto-19.4.0 → kinto-19.6.0}/kinto/views/buckets.py +0 -0
  310. {kinto-19.4.0 → kinto-19.6.0}/kinto/views/collections.py +0 -0
  311. {kinto-19.4.0 → kinto-19.6.0}/kinto/views/groups.py +0 -0
  312. {kinto-19.4.0 → kinto-19.6.0}/kinto/views/permissions.py +0 -0
  313. {kinto-19.4.0 → kinto-19.6.0}/kinto/views/records.py +0 -0
  314. {kinto-19.4.0 → kinto-19.6.0}/kinto.egg-info/dependency_links.txt +0 -0
  315. {kinto-19.4.0 → kinto-19.6.0}/kinto.egg-info/entry_points.txt +0 -0
  316. {kinto-19.4.0 → kinto-19.6.0}/kinto.egg-info/top_level.txt +0 -0
  317. {kinto-19.4.0 → kinto-19.6.0}/scripts/pull-kinto-admin.sh +0 -0
  318. {kinto-19.4.0 → kinto-19.6.0}/setup.cfg +0 -0
  319. {kinto-19.4.0 → kinto-19.6.0}/tests/__init__.py +0 -0
  320. {kinto-19.4.0 → kinto-19.6.0}/tests/browser.ini +0 -0
  321. {kinto-19.4.0 → kinto-19.6.0}/tests/browser.py +0 -0
  322. {kinto-19.4.0 → kinto-19.6.0}/tests/core/__init__.py +0 -0
  323. {kinto-19.4.0 → kinto-19.6.0}/tests/core/listeners.py +0 -0
  324. {kinto-19.4.0 → kinto-19.6.0}/tests/core/resource/__init__.py +0 -0
  325. {kinto-19.4.0 → kinto-19.6.0}/tests/core/resource/test_base.py +0 -0
  326. {kinto-19.4.0 → kinto-19.6.0}/tests/core/resource/test_cache_expires.py +0 -0
  327. {kinto-19.4.0 → kinto-19.6.0}/tests/core/resource/test_events.py +0 -0
  328. {kinto-19.4.0 → kinto-19.6.0}/tests/core/resource/test_filter.py +0 -0
  329. {kinto-19.4.0 → kinto-19.6.0}/tests/core/resource/test_model.py +0 -0
  330. {kinto-19.4.0 → kinto-19.6.0}/tests/core/resource/test_object.py +0 -0
  331. {kinto-19.4.0 → kinto-19.6.0}/tests/core/resource/test_object_permissions.py +0 -0
  332. {kinto-19.4.0 → kinto-19.6.0}/tests/core/resource/test_pagination.py +0 -0
  333. {kinto-19.4.0 → kinto-19.6.0}/tests/core/resource/test_partial_response.py +0 -0
  334. {kinto-19.4.0 → kinto-19.6.0}/tests/core/resource/test_preconditions.py +0 -0
  335. {kinto-19.4.0 → kinto-19.6.0}/tests/core/resource/test_schema.py +0 -0
  336. {kinto-19.4.0 → kinto-19.6.0}/tests/core/resource/test_sort.py +0 -0
  337. {kinto-19.4.0 → kinto-19.6.0}/tests/core/resource/test_sync.py +0 -0
  338. {kinto-19.4.0 → kinto-19.6.0}/tests/core/resource/test_views.py +0 -0
  339. {kinto-19.4.0 → kinto-19.6.0}/tests/core/resource/test_views_cors.py +0 -0
  340. {kinto-19.4.0 → kinto-19.6.0}/tests/core/schema/postgresql-permission-1.sql +0 -0
  341. {kinto-19.4.0 → kinto-19.6.0}/tests/core/schema/postgresql-storage-1.6.sql +0 -0
  342. {kinto-19.4.0 → kinto-19.6.0}/tests/core/schema/postgresql-storage-11.sql +0 -0
  343. {kinto-19.4.0 → kinto-19.6.0}/tests/core/support.py +0 -0
  344. {kinto-19.4.0 → kinto-19.6.0}/tests/core/test_authentication.py +0 -0
  345. {kinto-19.4.0 → kinto-19.6.0}/tests/core/test_authorization.py +0 -0
  346. {kinto-19.4.0 → kinto-19.6.0}/tests/core/test_cache.py +0 -0
  347. {kinto-19.4.0 → kinto-19.6.0}/tests/core/test_decorators.py +0 -0
  348. {kinto-19.4.0 → kinto-19.6.0}/tests/core/test_deprecation.py +0 -0
  349. {kinto-19.4.0 → kinto-19.6.0}/tests/core/test_errors.py +0 -0
  350. {kinto-19.4.0 → kinto-19.6.0}/tests/core/test_initialization.py +0 -0
  351. {kinto-19.4.0 → kinto-19.6.0}/tests/core/test_listeners.py +0 -0
  352. {kinto-19.4.0 → kinto-19.6.0}/tests/core/test_logging.py +0 -0
  353. {kinto-19.4.0 → kinto-19.6.0}/tests/core/test_metrics.py +0 -0
  354. {kinto-19.4.0 → kinto-19.6.0}/tests/core/test_permission.py +0 -0
  355. {kinto-19.4.0 → kinto-19.6.0}/tests/core/test_schema.py +0 -0
  356. {kinto-19.4.0 → kinto-19.6.0}/tests/core/test_scripts.py +0 -0
  357. {kinto-19.4.0 → kinto-19.6.0}/tests/core/test_storage.py +0 -0
  358. {kinto-19.4.0 → kinto-19.6.0}/tests/core/test_storage_migrations.py +0 -0
  359. {kinto-19.4.0 → kinto-19.6.0}/tests/core/test_storage_pool.py +0 -0
  360. {kinto-19.4.0 → kinto-19.6.0}/tests/core/test_utils.py +0 -0
  361. {kinto-19.4.0 → kinto-19.6.0}/tests/core/test_views_batch.py +0 -0
  362. {kinto-19.4.0 → kinto-19.6.0}/tests/core/test_views_errors.py +0 -0
  363. {kinto-19.4.0 → kinto-19.6.0}/tests/core/test_views_heartbeat.py +0 -0
  364. {kinto-19.4.0 → kinto-19.6.0}/tests/core/test_views_hello.py +0 -0
  365. {kinto-19.4.0 → kinto-19.6.0}/tests/core/test_views_openapi.py +0 -0
  366. {kinto-19.4.0 → kinto-19.6.0}/tests/core/test_views_postgresql.py +0 -0
  367. {kinto-19.4.0 → kinto-19.6.0}/tests/core/test_views_transaction.py +0 -0
  368. {kinto-19.4.0 → kinto-19.6.0}/tests/core/testapp/__init__.py +0 -0
  369. {kinto-19.4.0 → kinto-19.6.0}/tests/core/testapp/static/index.html +0 -0
  370. {kinto-19.4.0 → kinto-19.6.0}/tests/core/testapp/views.py +0 -0
  371. {kinto-19.4.0 → kinto-19.6.0}/tests/core/testplugin/__init__.py +0 -0
  372. {kinto-19.4.0 → kinto-19.6.0}/tests/functional.ini +0 -0
  373. {kinto-19.4.0 → kinto-19.6.0}/tests/functional.py +0 -0
  374. {kinto-19.4.0 → kinto-19.6.0}/tests/openapi/__init__.py +0 -0
  375. {kinto-19.4.0 → kinto-19.6.0}/tests/openapi/support.py +0 -0
  376. {kinto-19.4.0 → kinto-19.6.0}/tests/openapi/test_plugins.py +0 -0
  377. {kinto-19.4.0 → kinto-19.6.0}/tests/openapi/test_resources.py +0 -0
  378. {kinto-19.4.0 → kinto-19.6.0}/tests/openapi/test_responses_buckets.py +0 -0
  379. {kinto-19.4.0 → kinto-19.6.0}/tests/openapi/test_responses_collections.py +0 -0
  380. {kinto-19.4.0 → kinto-19.6.0}/tests/openapi/test_responses_errors.py +0 -0
  381. {kinto-19.4.0 → kinto-19.6.0}/tests/openapi/test_responses_groups.py +0 -0
  382. {kinto-19.4.0 → kinto-19.6.0}/tests/openapi/test_responses_records.py +0 -0
  383. {kinto-19.4.0 → kinto-19.6.0}/tests/openapi/test_validation.py +0 -0
  384. {kinto-19.4.0 → kinto-19.6.0}/tests/plugins/__init__.py +0 -0
  385. {kinto-19.4.0 → kinto-19.6.0}/tests/plugins/test_accounts.py +0 -0
  386. {kinto-19.4.0 → kinto-19.6.0}/tests/plugins/test_admin.py +0 -0
  387. {kinto-19.4.0 → kinto-19.6.0}/tests/plugins/test_default_bucket.py +0 -0
  388. {kinto-19.4.0 → kinto-19.6.0}/tests/plugins/test_flush.py +0 -0
  389. {kinto-19.4.0 → kinto-19.6.0}/tests/plugins/test_history.py +0 -0
  390. {kinto-19.4.0 → kinto-19.6.0}/tests/plugins/test_openid.py +0 -0
  391. {kinto-19.4.0 → kinto-19.6.0}/tests/plugins/test_prometheus.py +0 -0
  392. {kinto-19.4.0 → kinto-19.6.0}/tests/plugins/test_quotas.py +0 -0
  393. {kinto-19.4.0 → kinto-19.6.0}/tests/plugins/test_statsd.py +0 -0
  394. {kinto-19.4.0 → kinto-19.6.0}/tests/support.py +0 -0
  395. {kinto-19.4.0 → kinto-19.6.0}/tests/test_authorization.py +0 -0
  396. {kinto-19.4.0 → kinto-19.6.0}/tests/test_config.py +0 -0
  397. {kinto-19.4.0 → kinto-19.6.0}/tests/test_configuration/test.ini +0 -0
  398. {kinto-19.4.0 → kinto-19.6.0}/tests/test_init.py +0 -0
  399. {kinto-19.4.0 → kinto-19.6.0}/tests/test_main.py +0 -0
  400. {kinto-19.4.0 → kinto-19.6.0}/tests/test_scripts.py +0 -0
  401. {kinto-19.4.0 → kinto-19.6.0}/tests/test_views_admin.py +0 -0
  402. {kinto-19.4.0 → kinto-19.6.0}/tests/test_views_collections.py +0 -0
  403. {kinto-19.4.0 → kinto-19.6.0}/tests/test_views_collections_cache.py +0 -0
  404. {kinto-19.4.0 → kinto-19.6.0}/tests/test_views_contribute.py +0 -0
  405. {kinto-19.4.0 → kinto-19.6.0}/tests/test_views_disable_default.py +0 -0
  406. {kinto-19.4.0 → kinto-19.6.0}/tests/test_views_groups.py +0 -0
  407. {kinto-19.4.0 → kinto-19.6.0}/tests/test_views_hello.py +0 -0
  408. {kinto-19.4.0 → kinto-19.6.0}/tests/test_views_metrics.py +0 -0
  409. {kinto-19.4.0 → kinto-19.6.0}/tests/test_views_objects_permissions.py +0 -0
  410. {kinto-19.4.0 → kinto-19.6.0}/tests/test_views_permissions.py +0 -0
  411. {kinto-19.4.0 → kinto-19.6.0}/tests/test_views_records.py +0 -0
  412. {kinto-19.4.0 → kinto-19.6.0}/tests/test_views_schema_collection.py +0 -0
  413. {kinto-19.4.0 → kinto-19.6.0}/tests/test_views_schema_group.py +0 -0
  414. {kinto-19.4.0 → kinto-19.6.0}/tests/test_views_schema_record.py +0 -0
  415. {kinto-19.4.0 → kinto-19.6.0}/tests/test_views_version.py +0 -0
@@ -73,6 +73,14 @@ jobs:
73
73
  - name: Check out the repo
74
74
  uses: actions/checkout@v4
75
75
 
76
+ - name: Set up QEMU
77
+ uses: docker/setup-qemu-action@v3
78
+
79
+ - name: Enable multiplatform builds
80
+ uses: docker/setup-buildx-action@v3
81
+ with:
82
+ buildkitd-flags: "--debug" # Enable detailed logging
83
+
76
84
  - name: Log in to Docker Hub
77
85
  uses: docker/login-action@v3
78
86
  with:
@@ -93,3 +101,4 @@ jobs:
93
101
  push: true
94
102
  tags: ${{ steps.meta.outputs.tags }}
95
103
  labels: ${{ steps.meta.outputs.labels }}
104
+ platforms: linux/amd64,linux/arm64
@@ -0,0 +1,85 @@
1
+ name: Run scheduled jobs
2
+
3
+ on:
4
+ schedule:
5
+ - cron: '0 0 * * *' # Runs daily at midnight
6
+
7
+ jobs:
8
+ update-kinto-admin:
9
+ runs-on: ubuntu-latest
10
+ defaults:
11
+ run:
12
+ shell: bash
13
+
14
+ steps:
15
+ - name: Checkout repository
16
+ uses: actions/checkout@v4
17
+
18
+ - name: Get current version
19
+ id: current_version
20
+ run: |
21
+ CURRENT_VERSION="$(cat kinto/plugins/admin/VERSION)"
22
+ echo "Current Version: $CURRENT_VERSION"
23
+ echo "version=$CURRENT_VERSION" >> "$GITHUB_OUTPUT"
24
+
25
+ - name: Get latest release version
26
+ id: latest_release_version
27
+ run: |
28
+ LATEST_RELEASE_VERSION=$(curl -s https://api.github.com/repos/Kinto/kinto-admin/releases/latest | jq -r .tag_name)
29
+ echo "Latest Version: $LATEST_RELEASE_VERSION"
30
+ echo "version=${LATEST_RELEASE_VERSION#v}" >> "$GITHUB_OUTPUT"
31
+
32
+ - name: Compare versions
33
+ id: compare_versions
34
+ env:
35
+ LATEST_RELEASE_VERSION: ${{ steps.latest_release_version.outputs.version }}
36
+ CURRENT_VERSION: ${{ steps.current_version.outputs.version }}
37
+ run: |
38
+ LATEST_VERSION=$(npx --yes semver "$CURRENT_VERSION" "$LATEST_RELEASE_VERSION" | tail -n 1)
39
+ if [ "$LATEST_VERSION" != "$CURRENT_VERSION" ]; then
40
+ echo "Kinto Admin update ready"
41
+ echo "update_needed=true" >> "$GITHUB_OUTPUT"
42
+ else
43
+ echo "Kinto Admin up to date"
44
+ echo "update_needed=false" >> "$GITHUB_OUTPUT"
45
+ fi
46
+
47
+ - name: Configure git
48
+ if: ${{ steps.compare_versions.outputs.update_needed == 'true' }}
49
+ # https://github.com/orgs/community/discussions/26560
50
+ run: |
51
+ git config user.name github-actions[bot]
52
+ git config user.email 41898282+github-actions[bot]@users.noreply.github.com
53
+
54
+ - name: Create branch
55
+ id: create_branch
56
+ if: ${{ steps.compare_versions.outputs.update_needed == 'true' }}
57
+ env:
58
+ BRANCH_NAME: updates/kinto-admin-${{ steps.latest_release_version.outputs.version }}
59
+ LATEST_RELEASE: ${{ steps.latest_release_version.outputs.version }}
60
+ run: |
61
+ git fetch origin --no-tags --quiet "refs/heads/updates/*:refs/remotes/origin/updates/*"
62
+
63
+ if [ "$(git rev-parse --quiet --verify origin/$"BRANCH_NAME")" ]; then
64
+ echo "Branch $BRANCH_NAME already exists on origin."
65
+ echo "pr_needed=false" >> "$GITHUB_OUTPUT"
66
+ else
67
+ git checkout -b "$BRANCH_NAME"
68
+ echo "$LATEST_RELEASE" > kinto/plugins/admin/VERSION
69
+ git commit -am "Update Kinto Admin to $LATEST_RELEASE"
70
+ git push origin "$BRANCH_NAME"
71
+ echo "pr_needed=true" >> "$GITHUB_OUTPUT"
72
+ fi
73
+
74
+ - name: Create pull request
75
+ if: ${{ steps.compare_versions.outputs.update_needed == 'true' && steps.create_branch.outputs.pr_needed == 'true'}}
76
+ env:
77
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
78
+ BRANCH_NAME: updates/kinto-admin-${{ steps.latest_release_version.outputs.version }}
79
+ run: |
80
+ gh pr create \
81
+ --title "Update Kinto Admin version to ${{ steps.latest_release_version.outputs.version }}" \
82
+ --body "" \
83
+ --base "main" \
84
+ --head "$BRANCH_NAME" \
85
+ --label "dependencies"
@@ -16,6 +16,9 @@ jobs:
16
16
  steps:
17
17
  - uses: actions/checkout@v4
18
18
 
19
+ - name: Actions Lint
20
+ uses: raven-actions/actionlint@v2
21
+
19
22
  - uses: actions/setup-python@v5
20
23
 
21
24
  - name: make lint
@@ -158,11 +161,11 @@ jobs:
158
161
  run: |
159
162
  psql -c "CREATE DATABASE testdb ENCODING 'UTF8' TEMPLATE template0;" -U postgres -h localhost
160
163
 
161
- - run: mkdir ${DOCKER_CACHE}
164
+ - run: mkdir "${DOCKER_CACHE}"
162
165
 
163
166
  - name: Compute cache key
164
167
  # Create hash of hashes of checked in files not in Dockerignore
165
- run: echo "CACHE_KEY=$(git ls-tree --full-tree -r HEAD | grep -v -f .dockerignore | awk '{print $3}' | git hash-object --stdin)" >> $GITHUB_ENV
168
+ run: echo "CACHE_KEY=$(git ls-tree --full-tree -r HEAD | grep -v -f .dockerignore | awk '{print $3}' | git hash-object --stdin)" >> "$GITHUB_ENV"
166
169
 
167
170
  - uses: actions/cache@v4
168
171
  with:
@@ -190,9 +193,9 @@ jobs:
190
193
  run: |
191
194
  docker run --net=host --detach --rm \
192
195
  -p 8888:8888 \
193
- -v `pwd`/tests/functional.ini:/etc/functional.ini \
196
+ -v "$(pwd)"/tests/functional.ini:/etc/functional.ini \
194
197
  -e KINTO_INI=/etc/functional.ini \
195
- ${{ env.TEST_TAG }} && sleep 5
198
+ "${{ env.TEST_TAG }}" && sleep 5
196
199
 
197
200
  - name: Functional Tests
198
201
  run: |
@@ -0,0 +1,12 @@
1
+ version: 2
2
+
3
+ build:
4
+ os: "ubuntu-22.04"
5
+ tools:
6
+ python: "3.12"
7
+ jobs:
8
+ install:
9
+ - make install-docs
10
+ build:
11
+ html:
12
+ - SPHINX_BUILDDIR=$READTHEDOCS_OUTPUT make docs
@@ -17,6 +17,7 @@ Contributors
17
17
  * Balthazar Rouberol <br@imap.cc>
18
18
  * Boris Feld <lothiraldan@gmail.com>
19
19
  * Brady Dufresne <dufresnebrady@gmail.com>
20
+ * Can Berk Güder <cbguder@mozilla.com>
20
21
  * Castro
21
22
  * Chirag B. Jadwani <chirag.jadwani@gmail.com>
22
23
  * Christophe Gragnic <cgragnic@protonmail.com>
@@ -20,7 +20,6 @@ RUN cp -r /kinto-admin/kinto/plugins/admin/build kinto/plugins/admin/
20
20
  RUN pip install ".[postgresql,memcached,monitoring]" -c constraints.txt && pip install kinto-attachment kinto-emailer httpie
21
21
 
22
22
  FROM python:3.10-slim-bullseye
23
- RUN apt-get update && apt-get install -y --no-install-recommends libpq-dev
24
23
  RUN groupadd --gid 10001 app && \
25
24
  useradd --uid 10001 --gid 10001 --home /app --create-home app
26
25
 
@@ -1,6 +1,6 @@
1
1
  SERVER_CONFIG = config/kinto.ini
2
2
 
3
- SPHINX_BUILDDIR = docs/_build
3
+ SPHINX_BUILDDIR := $(shell echo $${SPHINX_BUILDDIR-docs/_build})
4
4
  VENV := $(shell echo $${VIRTUAL_ENV-.venv})
5
5
  PYTHON = $(VENV)/bin/python3
6
6
  DEV_STAMP = $(VENV)/.dev_env_installed.stamp
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: kinto
3
- Version: 19.4.0
3
+ Version: 19.6.0
4
4
  Summary: Kinto Web Service - Store, Sync, Share, and Self-Host.
5
5
  Author-email: Mozilla Services <developers@kinto-storage.org>
6
6
  License: Copyright 2012 - Mozilla Foundation
@@ -33,8 +33,6 @@ Description-Content-Type: text/x-rst
33
33
  License-File: LICENSE
34
34
  Requires-Dist: bcrypt
35
35
  Requires-Dist: colander
36
- Requires-Dist: cornice
37
- Requires-Dist: cornice_swagger
38
36
  Requires-Dist: dockerflow
39
37
  Requires-Dist: jsonschema
40
38
  Requires-Dist: jsonpatch
@@ -54,7 +52,7 @@ Provides-Extra: memcached
54
52
  Requires-Dist: python-memcached; extra == "memcached"
55
53
  Provides-Extra: postgresql
56
54
  Requires-Dist: SQLAlchemy<3; extra == "postgresql"
57
- Requires-Dist: psycopg2; extra == "postgresql"
55
+ Requires-Dist: psycopg2-binary; extra == "postgresql"
58
56
  Requires-Dist: zope.sqlalchemy; extra == "postgresql"
59
57
  Provides-Extra: monitoring
60
58
  Requires-Dist: newrelic; extra == "monitoring"
@@ -136,6 +134,7 @@ Contributors
136
134
  * Balthazar Rouberol <br@imap.cc>
137
135
  * Boris Feld <lothiraldan@gmail.com>
138
136
  * Brady Dufresne <dufresnebrady@gmail.com>
137
+ * Can Berk Güder <cbguder@mozilla.com>
139
138
  * Castro
140
139
  * Chirag B. Jadwani <chirag.jadwani@gmail.com>
141
140
  * Christophe Gragnic <cgragnic@protonmail.com>
@@ -1,8 +1,6 @@
1
1
  # main dependencies
2
2
  bcrypt
3
3
  colander
4
- cornice
5
- cornice_swagger
6
4
  dockerflow
7
5
  jsonschema
8
6
  jsonpatch
@@ -21,7 +19,7 @@ python-rapidjson
21
19
  python-memcached
22
20
  # postgresql
23
21
  SQLAlchemy < 3
24
- psycopg2
22
+ psycopg2-binary
25
23
  zope.sqlalchemy
26
24
  # monitoring
27
25
  newrelic
@@ -25,17 +25,9 @@ certifi==2024.7.4
25
25
  charset-normalizer==3.3.2
26
26
  # via requests
27
27
  colander==2.0
28
- # via
29
- # -r constraints.in
30
- # cornice-swagger
28
+ # via -r constraints.in
31
29
  colorama==0.4.6
32
30
  # via logging-color-formatter
33
- cornice==6.0.1
34
- # via
35
- # -r constraints.in
36
- # cornice-swagger
37
- cornice-swagger==1.0.1
38
- # via -r constraints.in
39
31
  coverage==7.6.4
40
32
  # via pytest-cov
41
33
  dockerflow==2024.4.2
@@ -45,9 +37,7 @@ execnet==2.0.2
45
37
  fqdn==1.5.1
46
38
  # via jsonschema
47
39
  greenlet==3.1.1
48
- # via
49
- # playwright
50
- # sqlalchemy
40
+ # via playwright
51
41
  hupper==1.12
52
42
  # via pyramid
53
43
  idna==3.7
@@ -81,7 +71,7 @@ markupsafe==2.1.4
81
71
  # via werkzeug
82
72
  msgpack==1.0.7
83
73
  # via bravado-core
84
- newrelic==10.4.0
74
+ newrelic==10.6.0
85
75
  # via -r constraints.in
86
76
  packaging==23.2
87
77
  # via
@@ -96,13 +86,13 @@ plaster==1.1.2
96
86
  # pyramid
97
87
  plaster-pastedeploy==1.0.1
98
88
  # via pyramid
99
- playwright==1.49.1
89
+ playwright==1.50.0
100
90
  # via -r constraints.in
101
91
  pluggy==1.5.0
102
92
  # via pytest
103
93
  prometheus-client==0.21.1
104
94
  # via -r constraints.in
105
- psycopg2==2.9.10
95
+ psycopg2-binary==2.9.10
106
96
  # via -r constraints.in
107
97
  pyee==12.0.0
108
98
  # via playwright
@@ -111,7 +101,6 @@ pyproject-hooks==1.0.0
111
101
  pyramid==2.0.2
112
102
  # via
113
103
  # -r constraints.in
114
- # cornice
115
104
  # pyramid-mailer
116
105
  # pyramid-multiauth
117
106
  # pyramid-tm
@@ -163,7 +152,7 @@ rpds-py==0.17.1
163
152
  # via
164
153
  # jsonschema
165
154
  # referencing
166
- ruff==0.9.1
155
+ ruff==0.9.6
167
156
  # via -r constraints.in
168
157
  sentry-sdk==2.8.0
169
158
  # via -r constraints.in
@@ -172,12 +161,11 @@ simplejson==3.19.2
172
161
  six==1.16.0
173
162
  # via
174
163
  # bravado-core
175
- # cornice-swagger
176
164
  # python-dateutil
177
165
  # rfc3339-validator
178
166
  soupsieve==2.5
179
167
  # via beautifulsoup4
180
- sqlalchemy==2.0.36
168
+ sqlalchemy==2.0.38
181
169
  # via
182
170
  # -r constraints.in
183
171
  # sentry-sdk
@@ -211,9 +199,7 @@ urllib3==2.2.2
211
199
  # requests
212
200
  # sentry-sdk
213
201
  venusian==3.1.0
214
- # via
215
- # cornice
216
- # pyramid
202
+ # via pyramid
217
203
  waitress==3.0.2
218
204
  # via
219
205
  # -r constraints.in
@@ -109,7 +109,7 @@ nitpick_ignore = [
109
109
  ("py:class", "str"),
110
110
  ("py:class", "tuple"),
111
111
  ("py:class", "Exception"),
112
- ("py:class", "cornice.Service"),
112
+ ("py:class", "kinto.core.cornice.Service"),
113
113
  # Member autodoc fails with those:
114
114
  # kinto.core.resource.schema
115
115
  ("py:class", "Integer"),
@@ -163,7 +163,6 @@ def setup(app):
163
163
 
164
164
  intersphinx_mapping = {
165
165
  "colander": ("https://colander.readthedocs.io/en/latest/", None),
166
- "cornice": ("https://cornice.readthedocs.io/en/latest/", None),
167
166
  "pyramid": ("https://pyramid.readthedocs.io/en/latest/", None),
168
167
  }
169
168
 
@@ -5,8 +5,7 @@ sphinxcontrib-httpdomain==1.8.1
5
5
  sphinx-github-changelog==1.4.0
6
6
  kinto
7
7
  mock==5.1.0
8
- webtest==3.0.2
9
- cornice==6.1.0
8
+ webtest==3.0.4
10
9
  pyramid==2.0.2
11
10
  python-rapidjson==1.20
12
- SQLAlchemy==2.0.37
11
+ SQLAlchemy==2.0.38
@@ -104,7 +104,7 @@ You might get some error like::
104
104
  File "./kinto/__init__.py", line 4, in <module>
105
105
  import kinto.core
106
106
  File "./kinto/core/__init__.py", line 5, in <module>
107
- from cornice import Service as CorniceService
107
+ from kinto.core.cornice import Service as CorniceService
108
108
  ImportError: No module named cornice
109
109
  unable to load app 0 (mountpoint='') (callable not found or import error)
110
110
 
@@ -4,11 +4,11 @@ import logging
4
4
  import tempfile
5
5
 
6
6
  import pkg_resources
7
- from cornice import Service as CorniceService
8
7
  from dockerflow import logging as dockerflow_logging
9
8
  from pyramid.settings import aslist
10
9
 
11
10
  from kinto.core import errors, events
11
+ from kinto.core.cornice import Service as CorniceService
12
12
  from kinto.core.initialization import ( # NOQA
13
13
  initialize,
14
14
  install_middlewares,
@@ -186,10 +186,10 @@ def includeme(config):
186
186
  config.add_request_method(events.notify_resource_event, name="notify_resource_event")
187
187
 
188
188
  # Setup cornice.
189
- config.include("cornice")
189
+ config.include("kinto.core.cornice")
190
190
 
191
191
  # Setup cornice api documentation
192
- config.include("cornice_swagger")
192
+ config.include("kinto.core.cornice_swagger")
193
193
 
194
194
  # Per-request transaction.
195
195
  config.include("pyramid_tm")
@@ -0,0 +1,93 @@
1
+ # This Source Code Form is subject to the terms of the Mozilla Public
2
+ # License, v. 2.0. If a copy of the MPL was not distributed with this file,
3
+ # You can obtain one at http://mozilla.org/MPL/2.0/.
4
+ import logging
5
+ from functools import partial
6
+
7
+ from pyramid.events import NewRequest
8
+ from pyramid.httpexceptions import HTTPForbidden, HTTPNotFound
9
+ from pyramid.security import NO_PERMISSION_REQUIRED
10
+ from pyramid.settings import asbool, aslist
11
+
12
+ from kinto.core.cornice.errors import Errors # NOQA
13
+ from kinto.core.cornice.pyramidhook import (
14
+ handle_exceptions,
15
+ register_resource_views,
16
+ register_service_views,
17
+ wrap_request,
18
+ )
19
+ from kinto.core.cornice.renderer import CorniceRenderer
20
+ from kinto.core.cornice.service import Service # NOQA
21
+ from kinto.core.cornice.util import ContentTypePredicate, current_service
22
+
23
+
24
+ logger = logging.getLogger("cornice")
25
+
26
+
27
+ def set_localizer_for_languages(event, available_languages, default_locale_name):
28
+ """
29
+ Sets the current locale based on the incoming Accept-Language header, if
30
+ present, and sets a localizer attribute on the request object based on
31
+ the current locale.
32
+
33
+ To be used as an event handler, this function needs to be partially applied
34
+ with the available_languages and default_locale_name arguments. The
35
+ resulting function will be an event handler which takes an event object as
36
+ its only argument.
37
+ """
38
+ request = event.request
39
+ if request.accept_language:
40
+ accepted = request.accept_language.lookup(available_languages, default=default_locale_name)
41
+ request._LOCALE_ = accepted
42
+
43
+
44
+ def setup_localization(config):
45
+ """
46
+ Setup localization based on the available_languages and
47
+ pyramid.default_locale_name settings.
48
+
49
+ These settings are named after suggestions from the "Internationalization
50
+ and Localization" section of the Pyramid documentation.
51
+ """
52
+ try:
53
+ config.add_translation_dirs("colander:locale/")
54
+ settings = config.get_settings()
55
+ available_languages = aslist(settings["available_languages"])
56
+ default_locale_name = settings.get("pyramid.default_locale_name", "en")
57
+ set_localizer = partial(
58
+ set_localizer_for_languages,
59
+ available_languages=available_languages,
60
+ default_locale_name=default_locale_name,
61
+ )
62
+ config.add_subscriber(set_localizer, NewRequest)
63
+ except ImportError: # pragma: no cover
64
+ # add_translation_dirs raises an ImportError if colander is not
65
+ # installed
66
+ pass
67
+
68
+
69
+ def includeme(config):
70
+ """Include the Cornice definitions"""
71
+ # attributes required to maintain services
72
+ config.registry.cornice_services = {}
73
+
74
+ settings = config.get_settings()
75
+
76
+ # localization request subscriber must be set before first call
77
+ # for request.localizer (in wrap_request)
78
+ if settings.get("available_languages"):
79
+ setup_localization(config)
80
+
81
+ config.add_directive("add_cornice_service", register_service_views)
82
+ config.add_directive("add_cornice_resource", register_resource_views)
83
+ config.add_subscriber(wrap_request, NewRequest)
84
+ config.add_renderer("cornicejson", CorniceRenderer())
85
+ config.add_view_predicate("content_type", ContentTypePredicate)
86
+ config.add_request_method(current_service, reify=True)
87
+
88
+ if asbool(settings.get("handle_exceptions", True)):
89
+ config.add_view(handle_exceptions, context=Exception, permission=NO_PERMISSION_REQUIRED)
90
+ config.add_view(handle_exceptions, context=HTTPNotFound, permission=NO_PERMISSION_REQUIRED)
91
+ config.add_view(
92
+ handle_exceptions, context=HTTPForbidden, permission=NO_PERMISSION_REQUIRED
93
+ )
@@ -0,0 +1,144 @@
1
+ # This Source Code Form is subject to the terms of the Mozilla Public
2
+ # License, v. 2.0. If a copy of the MPL was not distributed with this file,
3
+ # You can obtain one at http://mozilla.org/MPL/2.0/.
4
+ import fnmatch
5
+ import functools
6
+
7
+ from pyramid.settings import asbool
8
+
9
+
10
+ CORS_PARAMETERS = (
11
+ "cors_headers",
12
+ "cors_enabled",
13
+ "cors_origins",
14
+ "cors_credentials",
15
+ "cors_max_age",
16
+ "cors_expose_all_headers",
17
+ )
18
+
19
+
20
+ def get_cors_preflight_view(service):
21
+ """Return a view for the OPTION method.
22
+
23
+ Checks that the User-Agent is authorized to do a request to the server, and
24
+ to this particular service, and add the various checks that are specified
25
+ in http://www.w3.org/TR/cors/#resource-processing-model.
26
+ """
27
+
28
+ def _preflight_view(request):
29
+ response = request.response
30
+ origin = request.headers.get("Origin")
31
+ supported_headers = service.cors_supported_headers_for()
32
+
33
+ if not origin:
34
+ request.errors.add("header", "Origin", "this header is mandatory")
35
+
36
+ requested_method = request.headers.get("Access-Control-Request-Method")
37
+ if not requested_method:
38
+ request.errors.add(
39
+ "header", "Access-Control-Request-Method", "this header is mandatory"
40
+ )
41
+
42
+ if not (requested_method and origin):
43
+ return
44
+
45
+ requested_headers = request.headers.get("Access-Control-Request-Headers", ())
46
+
47
+ if requested_headers:
48
+ requested_headers = map(str.strip, requested_headers.split(","))
49
+
50
+ if requested_method not in service.cors_supported_methods:
51
+ request.errors.add("header", "Access-Control-Request-Method", "Method not allowed")
52
+
53
+ if not service.cors_expose_all_headers:
54
+ for h in requested_headers:
55
+ if h.lower() not in [s.lower() for s in supported_headers]:
56
+ request.errors.add(
57
+ "header", "Access-Control-Request-Headers", 'Header "%s" not allowed' % h
58
+ )
59
+
60
+ supported_headers = set(supported_headers) | set(requested_headers)
61
+
62
+ response.headers["Access-Control-Allow-Headers"] = ",".join(supported_headers)
63
+
64
+ response.headers["Access-Control-Allow-Methods"] = ",".join(service.cors_supported_methods)
65
+
66
+ max_age = service.cors_max_age_for(requested_method)
67
+ if max_age is not None:
68
+ response.headers["Access-Control-Max-Age"] = str(max_age)
69
+
70
+ return None
71
+
72
+ return _preflight_view
73
+
74
+
75
+ def _get_method(request):
76
+ """Return what's supposed to be the method for CORS operations.
77
+ (e.g if the verb is options, look at the A-C-Request-Method header,
78
+ otherwise return the HTTP verb).
79
+ """
80
+ if request.method == "OPTIONS":
81
+ method = request.headers.get("Access-Control-Request-Method", request.method)
82
+ else:
83
+ method = request.method
84
+ return method
85
+
86
+
87
+ def ensure_origin(service, request, response=None, **kwargs):
88
+ """Ensure that the origin header is set and allowed."""
89
+ response = response or request.response
90
+
91
+ # Don't check this twice.
92
+ if not request.info.get("cors_checked", False):
93
+ method = _get_method(request)
94
+
95
+ origin = request.headers.get("Origin")
96
+
97
+ if not origin:
98
+ always_cors = asbool(request.registry.settings.get("cornice.always_cors"))
99
+ # With this setting, if the service origins has "*", then
100
+ # always return CORS headers.
101
+ origins = getattr(service, "cors_origins", [])
102
+ if always_cors and "*" in origins:
103
+ origin = "*"
104
+
105
+ if origin:
106
+ if not any([fnmatch.fnmatchcase(origin, o) for o in service.cors_origins_for(method)]):
107
+ request.errors.add("header", "Origin", "%s not allowed" % origin)
108
+ elif service.cors_support_credentials_for(method):
109
+ response.headers["Access-Control-Allow-Origin"] = origin
110
+ else:
111
+ if any([o == "*" for o in service.cors_origins_for(method)]):
112
+ response.headers["Access-Control-Allow-Origin"] = "*"
113
+ else:
114
+ response.headers["Access-Control-Allow-Origin"] = origin
115
+ request.info["cors_checked"] = True
116
+ return response
117
+
118
+
119
+ def get_cors_validator(service):
120
+ return functools.partial(ensure_origin, service)
121
+
122
+
123
+ def apply_cors_post_request(service, request, response):
124
+ """Handles CORS-related post-request things.
125
+
126
+ Add some response headers, such as the Expose-Headers and the
127
+ Allow-Credentials ones.
128
+ """
129
+ response = ensure_origin(service, request, response)
130
+ method = _get_method(request)
131
+
132
+ if (
133
+ service.cors_support_credentials_for(method)
134
+ and "Access-Control-Allow-Credentials" not in response.headers
135
+ ):
136
+ response.headers["Access-Control-Allow-Credentials"] = "true"
137
+
138
+ if request.method != "OPTIONS":
139
+ # Which headers are exposed?
140
+ supported_headers = service.cors_supported_headers_for(request.method)
141
+ if supported_headers:
142
+ response.headers["Access-Control-Expose-Headers"] = ", ".join(supported_headers)
143
+
144
+ return response
@@ -0,0 +1,40 @@
1
+ # This Source Code Form is subject to the terms of the Mozilla Public
2
+ # License, v. 2.0. If a copy of the MPL was not distributed with this file,
3
+ # You can obtain one at http://mozilla.org/MPL/2.0/.
4
+ import json
5
+
6
+ from pyramid.i18n import TranslationString
7
+
8
+
9
+ class Errors(list):
10
+ """Holds Request errors"""
11
+
12
+ def __init__(self, status=400, localizer=None):
13
+ self.status = status
14
+ self.localizer = localizer
15
+ super(Errors, self).__init__()
16
+
17
+ def add(self, location, name=None, description=None, **kw):
18
+ """Registers a new error."""
19
+ allowed = ("body", "querystring", "url", "header", "path", "cookies", "method")
20
+ if location != "" and location not in allowed:
21
+ raise ValueError("%r not in %s" % (location, allowed))
22
+
23
+ if isinstance(description, TranslationString) and self.localizer:
24
+ description = self.localizer.translate(description)
25
+
26
+ self.append(dict(location=location, name=name, description=description, **kw))
27
+
28
+ @classmethod
29
+ def from_json(cls, string):
30
+ """Transforms a json string into an `Errors` instance"""
31
+ obj = json.loads(string.decode())
32
+ return Errors.from_list(obj.get("errors", []))
33
+
34
+ @classmethod
35
+ def from_list(cls, obj):
36
+ """Transforms a python list into an `Errors` instance"""
37
+ errors = Errors()
38
+ for error in obj:
39
+ errors.add(**error)
40
+ return errors