WuttaWeb 0.13.1__tar.gz → 0.14.1__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 (182) hide show
  1. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/CHANGELOG.md +14 -0
  2. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/PKG-INFO +4 -2
  3. wuttaweb-0.14.1/docs/api/wuttaweb.conf.rst +6 -0
  4. wuttaweb-0.14.1/docs/api/wuttaweb.db.continuum.rst +6 -0
  5. wuttaweb-0.14.1/docs/api/wuttaweb.db.sess.rst +6 -0
  6. wuttaweb-0.14.1/docs/api/wuttaweb.rst +6 -0
  7. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/docs/conf.py +1 -0
  8. wuttaweb-0.14.1/docs/index.rst +68 -0
  9. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/pyproject.toml +7 -2
  10. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/auth.py +2 -1
  11. wuttaweb-0.14.1/src/wuttaweb/conf.py +43 -0
  12. wuttaweb-0.14.1/src/wuttaweb/db/__init__.py +31 -0
  13. wuttaweb-0.14.1/src/wuttaweb/db/continuum.py +56 -0
  14. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/forms/schema.py +1 -1
  15. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/forms/widgets.py +6 -3
  16. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/subscribers.py +1 -1
  17. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/templates/base.mako +3 -3
  18. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/templates/configure.mako +1 -1
  19. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/util.py +12 -6
  20. wuttaweb-0.14.1/tests/db/test_continuum.py +38 -0
  21. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/tests/forms/test_widgets.py +19 -3
  22. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/tests/test_util.py +30 -9
  23. wuttaweb-0.14.1/tests/views/__init__.py +0 -0
  24. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/tox.ini +5 -2
  25. wuttaweb-0.13.1/docs/api/index.rst +0 -10
  26. wuttaweb-0.13.1/docs/api/wuttaweb/index.rst +0 -38
  27. wuttaweb-0.13.1/docs/index.rst +0 -28
  28. wuttaweb-0.13.1/docs/narr/index.rst +0 -8
  29. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/.gitignore +0 -0
  30. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/COPYING.txt +0 -0
  31. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/README.md +0 -0
  32. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/docs/Makefile +0 -0
  33. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/docs/_static/.keepme +0 -0
  34. /wuttaweb-0.13.1/docs/api/wuttaweb/app.rst → /wuttaweb-0.14.1/docs/api/wuttaweb.app.rst +0 -0
  35. /wuttaweb-0.13.1/docs/api/wuttaweb/auth.rst → /wuttaweb-0.14.1/docs/api/wuttaweb.auth.rst +0 -0
  36. /wuttaweb-0.13.1/docs/api/wuttaweb/db.rst → /wuttaweb-0.14.1/docs/api/wuttaweb.db.rst +0 -0
  37. /wuttaweb-0.13.1/docs/api/wuttaweb/forms.base.rst → /wuttaweb-0.14.1/docs/api/wuttaweb.forms.base.rst +0 -0
  38. /wuttaweb-0.13.1/docs/api/wuttaweb/forms.rst → /wuttaweb-0.14.1/docs/api/wuttaweb.forms.rst +0 -0
  39. /wuttaweb-0.13.1/docs/api/wuttaweb/forms.schema.rst → /wuttaweb-0.14.1/docs/api/wuttaweb.forms.schema.rst +0 -0
  40. /wuttaweb-0.13.1/docs/api/wuttaweb/forms.widgets.rst → /wuttaweb-0.14.1/docs/api/wuttaweb.forms.widgets.rst +0 -0
  41. /wuttaweb-0.13.1/docs/api/wuttaweb/grids.base.rst → /wuttaweb-0.14.1/docs/api/wuttaweb.grids.base.rst +0 -0
  42. /wuttaweb-0.13.1/docs/api/wuttaweb/grids.filters.rst → /wuttaweb-0.14.1/docs/api/wuttaweb.grids.filters.rst +0 -0
  43. /wuttaweb-0.13.1/docs/api/wuttaweb/grids.rst → /wuttaweb-0.14.1/docs/api/wuttaweb.grids.rst +0 -0
  44. /wuttaweb-0.13.1/docs/api/wuttaweb/handler.rst → /wuttaweb-0.14.1/docs/api/wuttaweb.handler.rst +0 -0
  45. /wuttaweb-0.13.1/docs/api/wuttaweb/helpers.rst → /wuttaweb-0.14.1/docs/api/wuttaweb.helpers.rst +0 -0
  46. /wuttaweb-0.13.1/docs/api/wuttaweb/menus.rst → /wuttaweb-0.14.1/docs/api/wuttaweb.menus.rst +0 -0
  47. /wuttaweb-0.13.1/docs/api/wuttaweb/progress.rst → /wuttaweb-0.14.1/docs/api/wuttaweb.progress.rst +0 -0
  48. /wuttaweb-0.13.1/docs/api/wuttaweb/static.rst → /wuttaweb-0.14.1/docs/api/wuttaweb.static.rst +0 -0
  49. /wuttaweb-0.13.1/docs/api/wuttaweb/subscribers.rst → /wuttaweb-0.14.1/docs/api/wuttaweb.subscribers.rst +0 -0
  50. /wuttaweb-0.13.1/docs/api/wuttaweb/util.rst → /wuttaweb-0.14.1/docs/api/wuttaweb.util.rst +0 -0
  51. /wuttaweb-0.13.1/docs/api/wuttaweb/views.auth.rst → /wuttaweb-0.14.1/docs/api/wuttaweb.views.auth.rst +0 -0
  52. /wuttaweb-0.13.1/docs/api/wuttaweb/views.base.rst → /wuttaweb-0.14.1/docs/api/wuttaweb.views.base.rst +0 -0
  53. /wuttaweb-0.13.1/docs/api/wuttaweb/views.common.rst → /wuttaweb-0.14.1/docs/api/wuttaweb.views.common.rst +0 -0
  54. /wuttaweb-0.13.1/docs/api/wuttaweb/views.essential.rst → /wuttaweb-0.14.1/docs/api/wuttaweb.views.essential.rst +0 -0
  55. /wuttaweb-0.13.1/docs/api/wuttaweb/views.master.rst → /wuttaweb-0.14.1/docs/api/wuttaweb.views.master.rst +0 -0
  56. /wuttaweb-0.13.1/docs/api/wuttaweb/views.people.rst → /wuttaweb-0.14.1/docs/api/wuttaweb.views.people.rst +0 -0
  57. /wuttaweb-0.13.1/docs/api/wuttaweb/views.progress.rst → /wuttaweb-0.14.1/docs/api/wuttaweb.views.progress.rst +0 -0
  58. /wuttaweb-0.13.1/docs/api/wuttaweb/views.roles.rst → /wuttaweb-0.14.1/docs/api/wuttaweb.views.roles.rst +0 -0
  59. /wuttaweb-0.13.1/docs/api/wuttaweb/views.rst → /wuttaweb-0.14.1/docs/api/wuttaweb.views.rst +0 -0
  60. /wuttaweb-0.13.1/docs/api/wuttaweb/views.settings.rst → /wuttaweb-0.14.1/docs/api/wuttaweb.views.settings.rst +0 -0
  61. /wuttaweb-0.13.1/docs/api/wuttaweb/views.upgrades.rst → /wuttaweb-0.14.1/docs/api/wuttaweb.views.upgrades.rst +0 -0
  62. /wuttaweb-0.13.1/docs/api/wuttaweb/views.users.rst → /wuttaweb-0.14.1/docs/api/wuttaweb.views.users.rst +0 -0
  63. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/docs/glossary.rst +0 -0
  64. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/docs/make.bat +0 -0
  65. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/docs/narr/templates/base.rst +0 -0
  66. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/docs/narr/templates/index.rst +0 -0
  67. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/docs/narr/templates/lookup.rst +0 -0
  68. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/docs/narr/templates/overview.rst +0 -0
  69. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/__init__.py +0 -0
  70. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/_version.py +0 -0
  71. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/app.py +0 -0
  72. /wuttaweb-0.13.1/src/wuttaweb/db.py → /wuttaweb-0.14.1/src/wuttaweb/db/sess.py +0 -0
  73. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/email/templates/feedback.html.mako +0 -0
  74. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/email/templates/feedback.txt.mako +0 -0
  75. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/forms/__init__.py +0 -0
  76. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/forms/base.py +0 -0
  77. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/grids/__init__.py +0 -0
  78. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/grids/base.py +0 -0
  79. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/grids/filters.py +0 -0
  80. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/handler.py +0 -0
  81. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/helpers.py +0 -0
  82. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/menus.py +0 -0
  83. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/progress.py +0 -0
  84. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/static/__init__.py +0 -0
  85. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/static/img/favicon.ico +0 -0
  86. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/static/img/logo.png +0 -0
  87. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/static/img/testing.png +0 -0
  88. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/templates/appinfo/configure.mako +0 -0
  89. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/templates/appinfo/index.mako +0 -0
  90. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/templates/auth/change_password.mako +0 -0
  91. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/templates/auth/login.mako +0 -0
  92. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/templates/base_meta.mako +0 -0
  93. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/templates/deform/checkbox.pt +0 -0
  94. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/templates/deform/checkbox_choice.pt +0 -0
  95. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/templates/deform/checked_password.pt +0 -0
  96. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/templates/deform/moneyinput.pt +0 -0
  97. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/templates/deform/password.pt +0 -0
  98. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/templates/deform/permissions.pt +0 -0
  99. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/templates/deform/readonly/checkbox.pt +0 -0
  100. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/templates/deform/readonly/filedownload.pt +0 -0
  101. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/templates/deform/readonly/notes.pt +0 -0
  102. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/templates/deform/readonly/objectref.pt +0 -0
  103. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/templates/deform/readonly/permissions.pt +0 -0
  104. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/templates/deform/readonly/rolerefs.pt +0 -0
  105. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/templates/deform/select.pt +0 -0
  106. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/templates/deform/textarea.pt +0 -0
  107. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/templates/deform/textinput.pt +0 -0
  108. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/templates/forbidden.mako +0 -0
  109. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/templates/form.mako +0 -0
  110. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/templates/forms/vue_template.mako +0 -0
  111. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/templates/grids/table_element.mako +0 -0
  112. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/templates/grids/vue_template.mako +0 -0
  113. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/templates/home.mako +0 -0
  114. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/templates/master/configure.mako +0 -0
  115. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/templates/master/create.mako +0 -0
  116. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/templates/master/delete.mako +0 -0
  117. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/templates/master/edit.mako +0 -0
  118. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/templates/master/form.mako +0 -0
  119. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/templates/master/index.mako +0 -0
  120. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/templates/master/view.mako +0 -0
  121. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/templates/notfound.mako +0 -0
  122. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/templates/page.mako +0 -0
  123. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/templates/people/view_profile.mako +0 -0
  124. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/templates/progress.mako +0 -0
  125. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/templates/setup.mako +0 -0
  126. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/templates/upgrade.mako +0 -0
  127. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/templates/upgrades/configure.mako +0 -0
  128. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/templates/upgrades/view.mako +0 -0
  129. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/templates/wutta-components.mako +0 -0
  130. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/views/__init__.py +0 -0
  131. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/views/auth.py +0 -0
  132. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/views/base.py +0 -0
  133. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/views/common.py +0 -0
  134. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/views/essential.py +0 -0
  135. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/views/master.py +0 -0
  136. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/views/people.py +0 -0
  137. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/views/progress.py +0 -0
  138. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/views/roles.py +0 -0
  139. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/views/settings.py +0 -0
  140. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/views/upgrades.py +0 -0
  141. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/src/wuttaweb/views/users.py +0 -0
  142. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/tasks.py +0 -0
  143. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/tests/__init__.py +0 -0
  144. {wuttaweb-0.13.1/tests/forms → wuttaweb-0.14.1/tests/db}/__init__.py +0 -0
  145. {wuttaweb-0.13.1/tests/grids → wuttaweb-0.14.1/tests/forms}/__init__.py +0 -0
  146. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/tests/forms/test_base.py +0 -0
  147. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/tests/forms/test_schema.py +0 -0
  148. {wuttaweb-0.13.1/tests/views → wuttaweb-0.14.1/tests/grids}/__init__.py +0 -0
  149. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/tests/grids/test_base.py +0 -0
  150. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/tests/grids/test_filters.py +0 -0
  151. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/tests/libcache/bb_fontawesome_svg_core.js +0 -0
  152. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/tests/libcache/bb_free_solid_svg_icons.js +0 -0
  153. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/tests/libcache/bb_oruga.js +0 -0
  154. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/tests/libcache/bb_oruga_bulma.css +0 -0
  155. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/tests/libcache/bb_oruga_bulma.js +0 -0
  156. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/tests/libcache/bb_vue.js +0 -0
  157. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/tests/libcache/bb_vue_fontawesome.js +0 -0
  158. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/tests/libcache/buefy.css +0 -0
  159. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/tests/libcache/buefy.js +0 -0
  160. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/tests/libcache/fontawesome.js +0 -0
  161. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/tests/libcache/vue.js +0 -0
  162. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/tests/libcache/vue_resource.js +0 -0
  163. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/tests/test_app.py +0 -0
  164. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/tests/test_auth.py +0 -0
  165. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/tests/test_handler.py +0 -0
  166. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/tests/test_helpers.py +0 -0
  167. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/tests/test_menus.py +0 -0
  168. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/tests/test_progress.py +0 -0
  169. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/tests/test_static.py +0 -0
  170. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/tests/test_subscribers.py +0 -0
  171. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/tests/util.py +0 -0
  172. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/tests/views/test___init__.py +0 -0
  173. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/tests/views/test_auth.py +0 -0
  174. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/tests/views/test_base.py +0 -0
  175. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/tests/views/test_common.py +0 -0
  176. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/tests/views/test_master.py +0 -0
  177. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/tests/views/test_people.py +0 -0
  178. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/tests/views/test_progress.py +0 -0
  179. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/tests/views/test_roles.py +0 -0
  180. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/tests/views/test_settings.py +0 -0
  181. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/tests/views/test_upgrades.py +0 -0
  182. {wuttaweb-0.13.1 → wuttaweb-0.14.1}/tests/views/test_users.py +0 -0
@@ -5,6 +5,20 @@ All notable changes to wuttaweb will be documented in this file.
5
5
  The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
6
6
  and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## v0.14.1 (2024-08-30)
9
+
10
+ ### Fix
11
+
12
+ - avoid exit prompt for configure when removing settings
13
+ - freeze default versions for buefy, vue-resource
14
+ - stop auto-trim for feedback message, user name
15
+
16
+ ## v0.14.0 (2024-08-27)
17
+
18
+ ### Feat
19
+
20
+ - add basic support for wutta-continuum
21
+
8
22
  ## v0.13.1 (2024-08-26)
9
23
 
10
24
  ### Fix
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: WuttaWeb
3
- Version: 0.13.1
3
+ Version: 0.14.1
4
4
  Summary: Web App for Wutta Framework
5
5
  Project-URL: Homepage, https://wuttaproject.org/
6
6
  Project-URL: Repository, https://forgejo.wuttaproject.org/wutta/wuttaweb
@@ -36,8 +36,10 @@ Requires-Dist: pyramid-tm
36
36
  Requires-Dist: pyramid>=2
37
37
  Requires-Dist: waitress
38
38
  Requires-Dist: webhelpers2
39
- Requires-Dist: wuttjamaican[db,email]>=0.13.0
39
+ Requires-Dist: wuttjamaican[db,email]>=0.13.2
40
40
  Requires-Dist: zope-sqlalchemy>=1.5
41
+ Provides-Extra: continuum
42
+ Requires-Dist: wutta-continuum; extra == 'continuum'
41
43
  Provides-Extra: docs
42
44
  Requires-Dist: furo; extra == 'docs'
43
45
  Requires-Dist: sphinx; extra == 'docs'
@@ -0,0 +1,6 @@
1
+
2
+ ``wuttaweb.conf``
3
+ =================
4
+
5
+ .. automodule:: wuttaweb.conf
6
+ :members:
@@ -0,0 +1,6 @@
1
+
2
+ ``wuttaweb.db.continuum``
3
+ =========================
4
+
5
+ .. automodule:: wuttaweb.db.continuum
6
+ :members:
@@ -0,0 +1,6 @@
1
+
2
+ ``wuttaweb.db.sess``
3
+ ====================
4
+
5
+ .. automodule:: wuttaweb.db.sess
6
+ :members:
@@ -0,0 +1,6 @@
1
+
2
+ ``wuttaweb``
3
+ ============
4
+
5
+ .. automodule:: wuttaweb
6
+ :members:
@@ -34,6 +34,7 @@ intersphinx_mapping = {
34
34
  'rattail-manual': ('https://rattailproject.org/docs/rattail-manual/', None),
35
35
  'webhelpers2': ('https://webhelpers2.readthedocs.io/en/latest/', None),
36
36
  'wuttjamaican': ('https://rattailproject.org/docs/wuttjamaican/', None),
37
+ 'wutta-continuum': ('https://rattailproject.org/docs/wutta-continuum/', None),
37
38
  }
38
39
 
39
40
 
@@ -0,0 +1,68 @@
1
+
2
+ WuttaWeb
3
+ ========
4
+
5
+ This package provides a "web layer" for custom apps.
6
+
7
+ It uses traditional server-side rendering with VueJS on the front-end.
8
+
9
+ Good documentation and 100% `test coverage`_ are priorities for this
10
+ project.
11
+
12
+ .. _test coverage: https://buildbot.rattailproject.org/coverage/wuttaweb/
13
+
14
+ However as you can see..the API should be fairly well documented but
15
+ the narrative docs are pretty scant. That will eventually change.
16
+
17
+ .. toctree::
18
+ :maxdepth: 2
19
+ :caption: Documentation:
20
+
21
+ glossary
22
+ narr/templates/index
23
+
24
+ .. toctree::
25
+ :maxdepth: 1
26
+ :caption: Package API:
27
+
28
+ api/wuttaweb
29
+ api/wuttaweb.app
30
+ api/wuttaweb.auth
31
+ api/wuttaweb.conf
32
+ api/wuttaweb.db
33
+ api/wuttaweb.db.continuum
34
+ api/wuttaweb.db.sess
35
+ api/wuttaweb.forms
36
+ api/wuttaweb.forms.base
37
+ api/wuttaweb.forms.schema
38
+ api/wuttaweb.forms.widgets
39
+ api/wuttaweb.grids
40
+ api/wuttaweb.grids.base
41
+ api/wuttaweb.grids.filters
42
+ api/wuttaweb.handler
43
+ api/wuttaweb.helpers
44
+ api/wuttaweb.menus
45
+ api/wuttaweb.progress
46
+ api/wuttaweb.static
47
+ api/wuttaweb.subscribers
48
+ api/wuttaweb.util
49
+ api/wuttaweb.views
50
+ api/wuttaweb.views.auth
51
+ api/wuttaweb.views.base
52
+ api/wuttaweb.views.common
53
+ api/wuttaweb.views.essential
54
+ api/wuttaweb.views.master
55
+ api/wuttaweb.views.people
56
+ api/wuttaweb.views.progress
57
+ api/wuttaweb.views.roles
58
+ api/wuttaweb.views.settings
59
+ api/wuttaweb.views.upgrades
60
+ api/wuttaweb.views.users
61
+
62
+
63
+ Indices and tables
64
+ ==================
65
+
66
+ * :ref:`genindex`
67
+ * :ref:`modindex`
68
+ * :ref:`search`
@@ -6,7 +6,7 @@ build-backend = "hatchling.build"
6
6
 
7
7
  [project]
8
8
  name = "WuttaWeb"
9
- version = "0.13.1"
9
+ version = "0.14.1"
10
10
  description = "Web App for Wutta Framework"
11
11
  readme = "README.md"
12
12
  authors = [{name = "Lance Edgar", email = "lance@edbob.org"}]
@@ -42,12 +42,13 @@ dependencies = [
42
42
  "pyramid_tm",
43
43
  "waitress",
44
44
  "WebHelpers2",
45
- "WuttJamaican[db,email]>=0.13.0",
45
+ "WuttJamaican[db,email]>=0.13.2",
46
46
  "zope.sqlalchemy>=1.5",
47
47
  ]
48
48
 
49
49
 
50
50
  [project.optional-dependencies]
51
+ continuum = ["Wutta-Continuum"]
51
52
  docs = ["Sphinx", "furo"]
52
53
  tests = ["pytest-cov", "tox"]
53
54
 
@@ -60,6 +61,10 @@ main = "wuttaweb.app:main"
60
61
  wuttaweb = "wuttaweb.app:WebAppProvider"
61
62
 
62
63
 
64
+ [project.entry-points."wutta.config.extensions"]
65
+ wuttaweb = "wuttaweb.conf:WuttaWebConfigExtension"
66
+
67
+
63
68
  [project.urls]
64
69
  Homepage = "https://wuttaproject.org/"
65
70
  Repository = "https://forgejo.wuttaproject.org/wutta/wuttaweb"
@@ -98,7 +98,8 @@ class WuttaSecurityPolicy:
98
98
  for current user
99
99
 
100
100
  :param db_session: Optional :term:`db session` to use, instead of
101
- :class:`wuttaweb.db.Session`. Probably only useful for tests.
101
+ :class:`wuttaweb.db.sess.Session`. Probably only useful for
102
+ tests.
102
103
  """
103
104
 
104
105
  def __init__(self, db_session=None):
@@ -0,0 +1,43 @@
1
+ # -*- coding: utf-8; -*-
2
+ ################################################################################
3
+ #
4
+ # wuttaweb -- Web App for Wutta Framework
5
+ # Copyright © 2024 Lance Edgar
6
+ #
7
+ # This file is part of Wutta Framework.
8
+ #
9
+ # Wutta Framework is free software: you can redistribute it and/or modify it
10
+ # under the terms of the GNU General Public License as published by the Free
11
+ # Software Foundation, either version 3 of the License, or (at your option) any
12
+ # later version.
13
+ #
14
+ # Wutta Framework is distributed in the hope that it will be useful, but
15
+ # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17
+ # more details.
18
+ #
19
+ # You should have received a copy of the GNU General Public License along with
20
+ # Wutta Framework. If not, see <http://www.gnu.org/licenses/>.
21
+ #
22
+ ################################################################################
23
+ """
24
+ Config Extension
25
+ """
26
+
27
+ from wuttjamaican.conf import WuttaConfigExtension
28
+
29
+
30
+ class WuttaWebConfigExtension(WuttaConfigExtension):
31
+ """
32
+ Config extension for WuttaWeb.
33
+
34
+ This sets the default plugin for SQLAlchemy-Continuum. Which is
35
+ only relevant if Wutta-Continuum is installed and enabled. For
36
+ more info see :doc:`wutta-continuum:index`.
37
+ """
38
+ key = 'wuttaweb'
39
+
40
+ def configure(self, config):
41
+ """ """
42
+ config.setdefault('wutta_continuum.wutta_plugin_spec',
43
+ 'wuttaweb.db.continuum:WuttaWebContinuumPlugin')
@@ -0,0 +1,31 @@
1
+ # -*- coding: utf-8; -*-
2
+ ################################################################################
3
+ #
4
+ # wuttaweb -- Web App for Wutta Framework
5
+ # Copyright © 2024 Lance Edgar
6
+ #
7
+ # This file is part of Wutta Framework.
8
+ #
9
+ # Wutta Framework is free software: you can redistribute it and/or modify it
10
+ # under the terms of the GNU General Public License as published by the Free
11
+ # Software Foundation, either version 3 of the License, or (at your option) any
12
+ # later version.
13
+ #
14
+ # Wutta Framework is distributed in the hope that it will be useful, but
15
+ # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17
+ # more details.
18
+ #
19
+ # You should have received a copy of the GNU General Public License along with
20
+ # Wutta Framework. If not, see <http://www.gnu.org/licenses/>.
21
+ #
22
+ ################################################################################
23
+ """
24
+ Database Utilities
25
+
26
+ The following are available from this ``wuttaweb.db`` namespace:
27
+
28
+ * :class:`~wuttaweb.db.sess.Session`
29
+ """
30
+
31
+ from .sess import Session
@@ -0,0 +1,56 @@
1
+ # -*- coding: utf-8; -*-
2
+ ################################################################################
3
+ #
4
+ # wuttaweb -- Web App for Wutta Framework
5
+ # Copyright © 2024 Lance Edgar
6
+ #
7
+ # This file is part of Wutta Framework.
8
+ #
9
+ # Wutta Framework is free software: you can redistribute it and/or modify it
10
+ # under the terms of the GNU General Public License as published by the Free
11
+ # Software Foundation, either version 3 of the License, or (at your option) any
12
+ # later version.
13
+ #
14
+ # Wutta Framework is distributed in the hope that it will be useful, but
15
+ # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17
+ # more details.
18
+ #
19
+ # You should have received a copy of the GNU General Public License along with
20
+ # Wutta Framework. If not, see <http://www.gnu.org/licenses/>.
21
+ #
22
+ ################################################################################
23
+ """
24
+ SQLAlchemy-Continuum Plugin
25
+ """
26
+
27
+ from pyramid.threadlocal import get_current_request
28
+
29
+ try:
30
+ from wutta_continuum.conf import WuttaContinuumPlugin
31
+ except ImportError: # pragma: no cover
32
+ pass
33
+ else:
34
+
35
+ class WuttaWebContinuumPlugin(WuttaContinuumPlugin):
36
+ """
37
+ SQLAlchemy-Continuum manager plugin for WuttaWeb.
38
+
39
+ This tries to use the current request to obtain user and IP
40
+ address for the transaction.
41
+ """
42
+
43
+ # TODO: should find a better way, threadlocals are bad?
44
+ # https://docs.pylonsproject.org/projects/pyramid/en/latest/api/threadlocal.html#pyramid.threadlocal.get_current_request
45
+
46
+ def get_remote_addr(self, uow, session):
47
+ """ """
48
+ request = get_current_request()
49
+ if request:
50
+ return request.client_addr
51
+
52
+ def get_user_id(self, uow, session):
53
+ """ """
54
+ request = get_current_request()
55
+ if request and request.user:
56
+ return request.user.uuid
@@ -128,7 +128,7 @@ class WuttaSet(colander.Set):
128
128
  :param request: Current :term:`request` object.
129
129
 
130
130
  :param session: Optional :term:`db session` to use instead of
131
- :class:`wuttaweb.db.Session`.
131
+ :class:`wuttaweb.db.sess.Session`.
132
132
  """
133
133
 
134
134
  def __init__(self, request, session=None):
@@ -99,8 +99,11 @@ class ObjectRefWidget(SelectWidget):
99
99
  """ """
100
100
  values = super().get_template_values(field, cstruct, kw)
101
101
 
102
- if 'url' not in values and self.url and field.schema.model_instance:
103
- values['url'] = self.url(field.schema.model_instance)
102
+ # add url, only if rendering readonly
103
+ readonly = kw.get('readonly', self.readonly)
104
+ if readonly:
105
+ if 'url' not in values and self.url and field.schema.model_instance:
106
+ values['url'] = self.url(field.schema.model_instance)
104
107
 
105
108
  return values
106
109
 
@@ -134,7 +137,7 @@ class WuttaCheckboxChoiceWidget(CheckboxChoiceWidget):
134
137
  :param request: Current :term:`request` object.
135
138
 
136
139
  :param session: Optional :term:`db session` to use instead of
137
- :class:`wuttaweb.db.Session`.
140
+ :class:`wuttaweb.db.sess.Session`.
138
141
 
139
142
  It uses these Deform templates:
140
143
 
@@ -147,7 +147,7 @@ def new_request_set_user(
147
147
  from database, instead of :func:`default_user_getter()`.
148
148
 
149
149
  :param db_session: Optional :term:`db session` to use,
150
- instead of :class:`wuttaweb.db.Session`.
150
+ instead of :class:`wuttaweb.db.sess.Session`.
151
151
 
152
152
  This will add to the request object:
153
153
 
@@ -452,7 +452,7 @@
452
452
 
453
453
  <b-field label="User Name"
454
454
  :type="userName && userName.trim() ? null : 'is-danger'">
455
- <b-input v-model.trim="userName"
455
+ <b-input v-model="userName"
456
456
  % if request.user:
457
457
  disabled
458
458
  % endif
@@ -467,7 +467,7 @@
467
467
  <b-field label="Message"
468
468
  :type="message && message.trim() ? null : 'is-danger'">
469
469
  <b-input type="textarea"
470
- v-model.trim="message"
470
+ v-model="message"
471
471
  ref="textarea" />
472
472
  </b-field>
473
473
  </section>
@@ -530,7 +530,7 @@
530
530
  return {
531
531
  referrer: this.referrer,
532
532
  user_uuid: this.userUUID,
533
- user_name: this.userName,
533
+ user_name: this.userName.trim(),
534
534
  message: this.message.trim(),
535
535
  ...this.getExtraParams(),
536
536
  }
@@ -190,7 +190,7 @@
190
190
 
191
191
  // cf. https://stackoverflow.com/a/56551646
192
192
  ThisPage.methods.beforeWindowUnload = function(e) {
193
- if (this.settingsNeedSaved && !this.savingSettings && !this.undoChanges) {
193
+ if (this.settingsNeedSaved && !this.savingSettings && !this.undoChanges && !this.purgingSettings) {
194
194
  e.preventDefault()
195
195
  e.returnValue = ''
196
196
  }
@@ -210,7 +210,7 @@ def get_libver(
210
210
  DeprecationWarning)
211
211
  return version
212
212
  if not configured_only:
213
- return 'latest'
213
+ return '0.9.25'
214
214
 
215
215
  elif key == 'buefy.css':
216
216
  # nb. this always returns something
@@ -232,7 +232,7 @@ def get_libver(
232
232
 
233
233
  elif key == 'vue_resource':
234
234
  if not configured_only:
235
- return 'latest'
235
+ return '1.5.3'
236
236
 
237
237
  elif key == 'fontawesome':
238
238
  if not configured_only:
@@ -491,10 +491,16 @@ def get_model_fields(config, model_class=None):
491
491
  try:
492
492
  mapper = sa.inspect(model_class)
493
493
  except sa.exc.NoInspectionAvailable:
494
- pass
495
- else:
496
- fields = [prop.key for prop in mapper.iterate_properties]
497
- return fields
494
+ return
495
+
496
+ fields = [prop.key for prop in mapper.iterate_properties]
497
+
498
+ # nb. we never want the continuum 'versions' prop
499
+ app = config.get_app()
500
+ if app.continuum_is_enabled() and 'versions' in fields:
501
+ fields.remove('versions')
502
+
503
+ return fields
498
504
 
499
505
 
500
506
  def make_json_safe(value, key=None, warn=True):
@@ -0,0 +1,38 @@
1
+ # -*- coding: utf-8; -*-
2
+
3
+ from unittest.mock import patch, MagicMock
4
+
5
+ import pytest
6
+
7
+ from tests.util import WebTestCase
8
+
9
+ from wuttaweb.db import continuum as mod
10
+
11
+
12
+ class TestWuttaWebContinuumPlugin(WebTestCase):
13
+
14
+ def setUp(self):
15
+ if not hasattr(mod, 'WuttaWebContinuumPlugin'):
16
+ pytest.skip("test not relevant without sqlalchemy-continuum")
17
+ self.setup_web()
18
+
19
+ def make_plugin(self):
20
+ return mod.WuttaWebContinuumPlugin()
21
+
22
+ def test_get_remote_addr(self):
23
+ plugin = self.make_plugin()
24
+
25
+ with patch.object(mod, 'get_current_request', return_value=None):
26
+ self.assertIsNone(plugin.get_remote_addr(None, self.session))
27
+
28
+ self.request.client_addr = '127.0.0.1'
29
+ self.assertEqual(plugin.get_remote_addr(None, self.session), '127.0.0.1')
30
+
31
+ def test_get_user_id(self):
32
+ plugin = self.make_plugin()
33
+
34
+ with patch.object(mod, 'get_current_request', return_value=None):
35
+ self.assertIsNone(plugin.get_user_id(None, self.session))
36
+
37
+ self.request.user = MagicMock(uuid='some-random-uuid')
38
+ self.assertEqual(plugin.get_user_id(None, self.session), 'some-random-uuid')
@@ -19,6 +19,9 @@ class TestObjectRefWidget(WebTestCase):
19
19
  kwargs.setdefault('renderer', deform.Form.default_renderer)
20
20
  return deform.Field(node, **kwargs)
21
21
 
22
+ def make_widget(self, **kwargs):
23
+ return mod.ObjectRefWidget(self.request, **kwargs)
24
+
22
25
  def test_serialize(self):
23
26
  model = self.app.model
24
27
  person = model.Person(full_name="Betty Boop")
@@ -27,7 +30,7 @@ class TestObjectRefWidget(WebTestCase):
27
30
 
28
31
  # standard (editable)
29
32
  node = colander.SchemaNode(PersonRef(self.request, session=self.session))
30
- widget = mod.ObjectRefWidget(self.request)
33
+ widget = self.make_widget()
31
34
  field = self.make_field(node)
32
35
  html = widget.serialize(field, person.uuid)
33
36
  self.assertIn('<b-select ', html)
@@ -35,7 +38,7 @@ class TestObjectRefWidget(WebTestCase):
35
38
  # readonly
36
39
  node = colander.SchemaNode(PersonRef(self.request, session=self.session))
37
40
  node.model_instance = person
38
- widget = mod.ObjectRefWidget(self.request)
41
+ widget = self.make_widget()
39
42
  field = self.make_field(node)
40
43
  html = widget.serialize(field, person.uuid, readonly=True)
41
44
  self.assertIn('Betty Boop', html)
@@ -44,13 +47,26 @@ class TestObjectRefWidget(WebTestCase):
44
47
  # with hyperlink
45
48
  node = colander.SchemaNode(PersonRef(self.request, session=self.session))
46
49
  node.model_instance = person
47
- widget = mod.ObjectRefWidget(self.request, url=lambda p: '/foo')
50
+ widget = self.make_widget(url=lambda p: '/foo')
48
51
  field = self.make_field(node)
49
52
  html = widget.serialize(field, person.uuid, readonly=True)
50
53
  self.assertIn('Betty Boop', html)
51
54
  self.assertIn('<a', html)
52
55
  self.assertIn('href="/foo"', html)
53
56
 
57
+ def test_get_template_values(self):
58
+ model = self.app.model
59
+ person = model.Person(full_name="Betty Boop")
60
+ self.session.add(person)
61
+ self.session.commit()
62
+
63
+ node = colander.SchemaNode(PersonRef(self.request, session=self.session))
64
+ widget = self.make_widget()
65
+ field = self.make_field(node)
66
+ values = widget.get_template_values(field, person.uuid, {})
67
+ self.assertIn('cstruct', values)
68
+ self.assertNotIn('url', values)
69
+
54
70
 
55
71
  class TestFileDownloadWidget(WebTestCase):
56
72
 
@@ -60,7 +60,7 @@ class TestGetLibVer(TestCase):
60
60
 
61
61
  def test_buefy_default(self):
62
62
  version = mod.get_libver(self.request, 'buefy')
63
- self.assertEqual(version, 'latest')
63
+ self.assertEqual(version, '0.9.25')
64
64
 
65
65
  def test_buefy_custom_old(self):
66
66
  self.config.setdefault('wuttaweb.buefy_version', '0.9.29')
@@ -84,11 +84,11 @@ class TestGetLibVer(TestCase):
84
84
  def test_buefy_default_only(self):
85
85
  self.config.setdefault('wuttaweb.libver.buefy', '0.9.29')
86
86
  version = mod.get_libver(self.request, 'buefy', default_only=True)
87
- self.assertEqual(version, 'latest')
87
+ self.assertEqual(version, '0.9.25')
88
88
 
89
89
  def test_buefy_css_default(self):
90
90
  version = mod.get_libver(self.request, 'buefy.css')
91
- self.assertEqual(version, 'latest')
91
+ self.assertEqual(version, '0.9.25')
92
92
 
93
93
  def test_buefy_css_custom_old(self):
94
94
  # nb. this uses same setting as buefy (js)
@@ -109,7 +109,7 @@ class TestGetLibVer(TestCase):
109
109
  def test_buefy_css_default_only(self):
110
110
  self.config.setdefault('wuttaweb.libver.buefy', '0.9.29')
111
111
  version = mod.get_libver(self.request, 'buefy.css', default_only=True)
112
- self.assertEqual(version, 'latest')
112
+ self.assertEqual(version, '0.9.25')
113
113
 
114
114
  def test_vue_default(self):
115
115
  version = mod.get_libver(self.request, 'vue')
@@ -136,7 +136,7 @@ class TestGetLibVer(TestCase):
136
136
 
137
137
  def test_vue_resource_default(self):
138
138
  version = mod.get_libver(self.request, 'vue_resource')
139
- self.assertEqual(version, 'latest')
139
+ self.assertEqual(version, '1.5.3')
140
140
 
141
141
  def test_vue_resource_custom(self):
142
142
  self.config.setdefault('wuttaweb.libver.vue_resource', '1.5.3')
@@ -247,7 +247,7 @@ class TestGetLibUrl(TestCase):
247
247
 
248
248
  def test_buefy_default(self):
249
249
  url = mod.get_liburl(self.request, 'buefy')
250
- self.assertEqual(url, 'https://unpkg.com/buefy@latest/dist/buefy.min.js')
250
+ self.assertEqual(url, 'https://unpkg.com/buefy@0.9.25/dist/buefy.min.js')
251
251
 
252
252
  def test_buefy_custom(self):
253
253
  self.config.setdefault('wuttaweb.liburl.buefy', '/lib/buefy.js')
@@ -262,7 +262,7 @@ class TestGetLibUrl(TestCase):
262
262
  def test_buefy_default_only(self):
263
263
  self.config.setdefault('wuttaweb.liburl.buefy', '/lib/buefy.js')
264
264
  url = mod.get_liburl(self.request, 'buefy', default_only=True)
265
- self.assertEqual(url, 'https://unpkg.com/buefy@latest/dist/buefy.min.js')
265
+ self.assertEqual(url, 'https://unpkg.com/buefy@0.9.25/dist/buefy.min.js')
266
266
 
267
267
  def test_buefy_configured_only(self):
268
268
  url = mod.get_liburl(self.request, 'buefy', configured_only=True)
@@ -281,7 +281,7 @@ class TestGetLibUrl(TestCase):
281
281
 
282
282
  def test_buefy_css_default(self):
283
283
  url = mod.get_liburl(self.request, 'buefy.css')
284
- self.assertEqual(url, 'https://unpkg.com/buefy@latest/dist/buefy.min.css')
284
+ self.assertEqual(url, 'https://unpkg.com/buefy@0.9.25/dist/buefy.min.css')
285
285
 
286
286
  def test_buefy_css_custom(self):
287
287
  self.config.setdefault('wuttaweb.liburl.buefy.css', '/lib/buefy.css')
@@ -309,7 +309,7 @@ class TestGetLibUrl(TestCase):
309
309
 
310
310
  def test_vue_resource_default(self):
311
311
  url = mod.get_liburl(self.request, 'vue_resource')
312
- self.assertEqual(url, 'https://cdn.jsdelivr.net/npm/vue-resource@latest')
312
+ self.assertEqual(url, 'https://cdn.jsdelivr.net/npm/vue-resource@1.5.3')
313
313
 
314
314
  def test_vue_resource_custom(self):
315
315
  self.config.setdefault('wuttaweb.liburl.vue_resource', '/lib/vue-resource.js')
@@ -480,6 +480,27 @@ class TestGetModelFields(TestCase):
480
480
  fields = mod.get_model_fields(self.config, model.Setting)
481
481
  self.assertEqual(fields, ['name', 'value'])
482
482
 
483
+ def test_avoid_versions(self):
484
+ model = self.app.model
485
+
486
+ mapper = MagicMock(iterate_properties = [
487
+ MagicMock(key='uuid'),
488
+ MagicMock(key='full_name'),
489
+ MagicMock(key='first_name'),
490
+ MagicMock(key='middle_name'),
491
+ MagicMock(key='last_name'),
492
+ MagicMock(key='versions'),
493
+ ])
494
+
495
+ with patch.object(mod, 'sa') as sa:
496
+ sa.inspect.return_value = mapper
497
+
498
+ with patch.object(self.app, 'continuum_is_enabled', return_value=True):
499
+ fields = mod.get_model_fields(self.config, model.Person)
500
+ # nb. no versions field
501
+ self.assertEqual(set(fields), set(['uuid', 'full_name', 'first_name',
502
+ 'middle_name', 'last_name']))
503
+
483
504
 
484
505
  class TestGetCsrfToken(TestCase):
485
506
 
File without changes
@@ -1,11 +1,14 @@
1
1
 
2
2
  [tox]
3
- envlist = py38, py39, py310, py311
3
+ envlist = py38, py39, py310, py311, nox
4
4
 
5
5
  [testenv]
6
- extras = tests
6
+ extras = continuum,tests
7
7
  commands = pytest {posargs}
8
8
 
9
+ [testenv:nox]
10
+ extras = tests
11
+
9
12
  [testenv:coverage]
10
13
  basepython = python3.11
11
14
  commands = pytest --cov=wuttaweb --cov-report=html --cov-fail-under=100