WuttaWeb 0.26.0__tar.gz → 0.27.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 (248) hide show
  1. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/CHANGELOG.md +17 -0
  2. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/PKG-INFO +3 -2
  3. wuttaweb-0.27.0/docs/api/wuttaweb.views.views.rst +6 -0
  4. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/index.rst +1 -0
  5. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/pyproject.toml +3 -3
  6. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/app.py +5 -0
  7. wuttaweb-0.27.0/src/wuttaweb/code-templates/new-master-view.mako +116 -0
  8. wuttaweb-0.27.0/src/wuttaweb/conf.py +89 -0
  9. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/db/continuum.py +8 -4
  10. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/forms/widgets.py +1 -1
  11. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/grids/base.py +1 -1
  12. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/alembic/dashboard.mako +4 -0
  13. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/appinfo/index.mako +11 -0
  14. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/base.mako +4 -0
  15. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/form.mako +4 -0
  16. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/tables/app/index.mako +8 -0
  17. wuttaweb-0.27.0/src/wuttaweb/templates/views/master/configure.mako +31 -0
  18. wuttaweb-0.27.0/src/wuttaweb/templates/views/master/create.mako +846 -0
  19. wuttaweb-0.27.0/src/wuttaweb/templates/views/master/index.mako +17 -0
  20. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/testing.py +55 -1
  21. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/views/essential.py +2 -0
  22. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/views/master.py +17 -26
  23. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/views/reports.py +1 -0
  24. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/views/tables.py +95 -15
  25. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/views/upgrades.py +0 -6
  26. wuttaweb-0.27.0/src/wuttaweb/views/views.py +469 -0
  27. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tasks.py +2 -1
  28. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/db/test_continuum.py +8 -4
  29. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/forms/test_widgets.py +2 -1
  30. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/grids/test_base.py +2 -2
  31. wuttaweb-0.27.0/tests/test_conf.py +61 -0
  32. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/views/test_tables.py +43 -0
  33. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/views/test_users.py +180 -1
  34. wuttaweb-0.27.0/tests/views/test_views.py +370 -0
  35. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tox.ini +8 -4
  36. wuttaweb-0.26.0/src/wuttaweb/conf.py +0 -46
  37. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/.gitignore +0 -0
  38. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/.hgignore +0 -0
  39. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/.pylintrc +0 -0
  40. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/COPYING.txt +0 -0
  41. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/README.md +0 -0
  42. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/Makefile +0 -0
  43. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/_static/.keepme +0 -0
  44. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/api/wuttaweb.app.rst +0 -0
  45. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/api/wuttaweb.auth.rst +0 -0
  46. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/api/wuttaweb.cli.rst +0 -0
  47. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/api/wuttaweb.cli.webapp.rst +0 -0
  48. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/api/wuttaweb.conf.rst +0 -0
  49. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/api/wuttaweb.db.continuum.rst +0 -0
  50. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/api/wuttaweb.db.rst +0 -0
  51. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/api/wuttaweb.db.sess.rst +0 -0
  52. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/api/wuttaweb.diffs.rst +0 -0
  53. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/api/wuttaweb.emails.rst +0 -0
  54. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/api/wuttaweb.forms.base.rst +0 -0
  55. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/api/wuttaweb.forms.rst +0 -0
  56. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/api/wuttaweb.forms.schema.rst +0 -0
  57. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/api/wuttaweb.forms.widgets.rst +0 -0
  58. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/api/wuttaweb.grids.base.rst +0 -0
  59. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/api/wuttaweb.grids.filters.rst +0 -0
  60. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/api/wuttaweb.grids.rst +0 -0
  61. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/api/wuttaweb.handler.rst +0 -0
  62. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/api/wuttaweb.helpers.rst +0 -0
  63. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/api/wuttaweb.menus.rst +0 -0
  64. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/api/wuttaweb.progress.rst +0 -0
  65. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/api/wuttaweb.rst +0 -0
  66. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/api/wuttaweb.static.rst +0 -0
  67. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/api/wuttaweb.subscribers.rst +0 -0
  68. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/api/wuttaweb.util.rst +0 -0
  69. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/api/wuttaweb.views.alembic.rst +0 -0
  70. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/api/wuttaweb.views.auth.rst +0 -0
  71. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/api/wuttaweb.views.base.rst +0 -0
  72. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/api/wuttaweb.views.batch.rst +0 -0
  73. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/api/wuttaweb.views.common.rst +0 -0
  74. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/api/wuttaweb.views.email.rst +0 -0
  75. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/api/wuttaweb.views.essential.rst +0 -0
  76. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/api/wuttaweb.views.master.rst +0 -0
  77. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/api/wuttaweb.views.people.rst +0 -0
  78. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/api/wuttaweb.views.progress.rst +0 -0
  79. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/api/wuttaweb.views.reports.rst +0 -0
  80. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/api/wuttaweb.views.roles.rst +0 -0
  81. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/api/wuttaweb.views.rst +0 -0
  82. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/api/wuttaweb.views.settings.rst +0 -0
  83. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/api/wuttaweb.views.tables.rst +0 -0
  84. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/api/wuttaweb.views.upgrades.rst +0 -0
  85. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/api/wuttaweb.views.users.rst +0 -0
  86. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/conf.py +0 -0
  87. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/glossary.rst +0 -0
  88. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/make.bat +0 -0
  89. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/narr/cli/builtin.rst +0 -0
  90. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/narr/cli/index.rst +0 -0
  91. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/narr/templates/base.rst +0 -0
  92. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/narr/templates/index.rst +0 -0
  93. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/narr/templates/lookup.rst +0 -0
  94. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/docs/narr/templates/overview.rst +0 -0
  95. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/__init__.py +0 -0
  96. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/_version.py +0 -0
  97. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/auth.py +0 -0
  98. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/cli/__init__.py +0 -0
  99. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/cli/webapp.py +0 -0
  100. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/code-templates/new-table.mako +0 -0
  101. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/db/__init__.py +0 -0
  102. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/db/sess.py +0 -0
  103. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/diffs.py +0 -0
  104. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/email-templates/feedback.html.mako +0 -0
  105. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/email-templates/feedback.txt.mako +0 -0
  106. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/emails.py +0 -0
  107. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/forms/__init__.py +0 -0
  108. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/forms/base.py +0 -0
  109. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/forms/schema.py +0 -0
  110. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/grids/__init__.py +0 -0
  111. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/grids/filters.py +0 -0
  112. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/handler.py +0 -0
  113. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/helpers.py +0 -0
  114. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/menus.py +0 -0
  115. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/progress.py +0 -0
  116. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/static/__init__.py +0 -0
  117. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/static/img/favicon.ico +0 -0
  118. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/static/img/logo.png +0 -0
  119. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/static/img/testing.png +0 -0
  120. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/subscribers.py +0 -0
  121. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/alembic/migrations/configure.mako +0 -0
  122. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/alembic/migrations/create.mako +0 -0
  123. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/alembic/migrations/index.mako +0 -0
  124. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/alembic/migrations/view.mako +0 -0
  125. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/appinfo/configure.mako +0 -0
  126. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/auth/change_password.mako +0 -0
  127. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/auth/login.mako +0 -0
  128. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/base_meta.mako +0 -0
  129. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/batch/view.mako +0 -0
  130. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/configure.mako +0 -0
  131. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/deform/checkbox.pt +0 -0
  132. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/deform/checkbox_choice.pt +0 -0
  133. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/deform/checked_password.pt +0 -0
  134. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/deform/dateinput.pt +0 -0
  135. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/deform/datetimeinput.pt +0 -0
  136. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/deform/moneyinput.pt +0 -0
  137. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/deform/password.pt +0 -0
  138. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/deform/permissions.pt +0 -0
  139. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/deform/readonly/checkbox.pt +0 -0
  140. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/deform/readonly/email_recips.pt +0 -0
  141. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/deform/readonly/filedownload.pt +0 -0
  142. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/deform/readonly/notes.pt +0 -0
  143. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/deform/readonly/objectref.pt +0 -0
  144. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/deform/readonly/permissions.pt +0 -0
  145. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/deform/readonly/rolerefs.pt +0 -0
  146. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/deform/select.pt +0 -0
  147. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/deform/textarea.pt +0 -0
  148. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/deform/textinput.pt +0 -0
  149. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/deform/wutta_checked_password.pt +0 -0
  150. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/diff.mako +0 -0
  151. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/email/settings/view.mako +0 -0
  152. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/forbidden.mako +0 -0
  153. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/forms/vue_buttons.mako +0 -0
  154. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/forms/vue_fields.mako +0 -0
  155. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/forms/vue_template.mako +0 -0
  156. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/grids/table_element.mako +0 -0
  157. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/grids/vue_template.mako +0 -0
  158. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/home.mako +0 -0
  159. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/master/configure.mako +0 -0
  160. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/master/create.mako +0 -0
  161. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/master/create_row.mako +0 -0
  162. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/master/delete.mako +0 -0
  163. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/master/edit.mako +0 -0
  164. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/master/form.mako +0 -0
  165. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/master/index.mako +0 -0
  166. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/master/view.mako +0 -0
  167. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/master/view_version.mako +0 -0
  168. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/master/view_versions.mako +0 -0
  169. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/notfound.mako +0 -0
  170. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/page.mako +0 -0
  171. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/people/view_profile.mako +0 -0
  172. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/progress.mako +0 -0
  173. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/reports/view.mako +0 -0
  174. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/setup.mako +0 -0
  175. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/tables/app/create.mako +0 -0
  176. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/themes/butterfly/base.mako +0 -0
  177. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/themes/butterfly/buefy-components.mako +0 -0
  178. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/themes/butterfly/buefy-plugin.mako +0 -0
  179. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/themes/butterfly/http-plugin.mako +0 -0
  180. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/upgrade.mako +0 -0
  181. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/upgrades/configure.mako +0 -0
  182. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/upgrades/index.mako +0 -0
  183. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/upgrades/view.mako +0 -0
  184. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/users/view.mako +0 -0
  185. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/templates/wutta-components.mako +0 -0
  186. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/util.py +0 -0
  187. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/views/__init__.py +0 -0
  188. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/views/alembic.py +0 -0
  189. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/views/auth.py +0 -0
  190. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/views/base.py +0 -0
  191. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/views/batch.py +0 -0
  192. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/views/common.py +0 -0
  193. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/views/email.py +0 -0
  194. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/views/people.py +0 -0
  195. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/views/progress.py +0 -0
  196. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/views/roles.py +0 -0
  197. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/views/settings.py +0 -0
  198. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/src/wuttaweb/views/users.py +0 -0
  199. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/__init__.py +0 -0
  200. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/cli/__init__.py +0 -0
  201. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/cli/test_webapp.py +0 -0
  202. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/db/__init__.py +0 -0
  203. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/forms/main_template.mako +0 -0
  204. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/forms/main_template_with_fields.mako +0 -0
  205. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/forms/test_base.py +0 -0
  206. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/forms/test_schema.py +0 -0
  207. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/grids/__init__.py +0 -0
  208. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/grids/test_filters.py +0 -0
  209. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/libcache/bb_fontawesome_svg_core.js +0 -0
  210. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/libcache/bb_free_solid_svg_icons.js +0 -0
  211. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/libcache/bb_oruga.js +0 -0
  212. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/libcache/bb_oruga_bulma.css +0 -0
  213. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/libcache/bb_oruga_bulma.js +0 -0
  214. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/libcache/bb_vue.js +0 -0
  215. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/libcache/bb_vue_fontawesome.js +0 -0
  216. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/libcache/buefy.css +0 -0
  217. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/libcache/buefy.js +0 -0
  218. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/libcache/fontawesome.js +0 -0
  219. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/libcache/vue.js +0 -0
  220. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/libcache/vue_resource.js +0 -0
  221. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/test_app.py +0 -0
  222. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/test_auth.py +0 -0
  223. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/test_diffs.py +0 -0
  224. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/test_emails.py +0 -0
  225. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/test_handler.py +0 -0
  226. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/test_helpers.py +0 -0
  227. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/test_menus.py +0 -0
  228. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/test_progress.py +0 -0
  229. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/test_static.py +0 -0
  230. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/test_subscribers.py +0 -0
  231. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/test_util.py +0 -0
  232. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/util.py +0 -0
  233. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/views/__init__.py +0 -0
  234. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/views/test___init__.py +0 -0
  235. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/views/test_alembic.py +0 -0
  236. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/views/test_auth.py +0 -0
  237. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/views/test_base.py +0 -0
  238. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/views/test_batch.py +0 -0
  239. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/views/test_common.py +0 -0
  240. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/views/test_email.py +0 -0
  241. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/views/test_essential.py +0 -0
  242. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/views/test_master.py +0 -0
  243. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/views/test_people.py +0 -0
  244. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/views/test_progress.py +0 -0
  245. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/views/test_reports.py +0 -0
  246. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/views/test_roles.py +0 -0
  247. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/views/test_settings.py +0 -0
  248. {wuttaweb-0.26.0 → wuttaweb-0.27.0}/tests/views/test_upgrades.py +0 -0
@@ -5,6 +5,23 @@ 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.27.0 (2025-12-31)
9
+
10
+ ### Feat
11
+
12
+ - add wizard for generating new master view code
13
+ - add basic MasterView to show all registered master views
14
+ - add MasterView registry/discovery mechanism
15
+
16
+ ### Fix
17
+
18
+ - show db backend (dialect name) on App Info page
19
+ - prevent whitespace wrap for tool panel header
20
+ - render datetimes with tooltip showing time delta from now
21
+ - fallback to default continuum plugin logic, when no request
22
+ - flush session when creating new object via MasterView
23
+ - fix page title for Alembic Dashboard
24
+
8
25
  ## v0.26.0 (2025-12-28)
9
26
 
10
27
  ### Feat
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: WuttaWeb
3
- Version: 0.26.0
3
+ Version: 0.27.0
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
@@ -40,7 +40,7 @@ Requires-Dist: pyramid>=2
40
40
  Requires-Dist: sqlalchemy-utils
41
41
  Requires-Dist: waitress
42
42
  Requires-Dist: webhelpers2
43
- Requires-Dist: wuttjamaican[db]>=0.28.0
43
+ Requires-Dist: wuttjamaican[db]>=0.28.1
44
44
  Requires-Dist: zope-sqlalchemy>=1.5
45
45
  Provides-Extra: continuum
46
46
  Requires-Dist: wutta-continuum>=0.3.0; extra == 'continuum'
@@ -53,6 +53,7 @@ Requires-Dist: pylint; extra == 'tests'
53
53
  Requires-Dist: pytest; extra == 'tests'
54
54
  Requires-Dist: pytest-cov; extra == 'tests'
55
55
  Requires-Dist: tox; extra == 'tests'
56
+ Requires-Dist: webtest; extra == 'tests'
56
57
  Description-Content-Type: text/markdown
57
58
 
58
59
 
@@ -0,0 +1,6 @@
1
+
2
+ ``wuttaweb.views.views``
3
+ ========================
4
+
5
+ .. automodule:: wuttaweb.views.views
6
+ :members:
@@ -74,6 +74,7 @@ the narrative docs are pretty scant. That will eventually change.
74
74
  api/wuttaweb.views.tables
75
75
  api/wuttaweb.views.upgrades
76
76
  api/wuttaweb.views.users
77
+ api/wuttaweb.views.views
77
78
 
78
79
 
79
80
  Indices and tables
@@ -6,7 +6,7 @@ build-backend = "hatchling.build"
6
6
 
7
7
  [project]
8
8
  name = "WuttaWeb"
9
- version = "0.26.0"
9
+ version = "0.27.0"
10
10
  description = "Web App for Wutta Framework"
11
11
  readme = "README.md"
12
12
  authors = [{name = "Lance Edgar", email = "lance@wuttaproject.org"}]
@@ -45,7 +45,7 @@ dependencies = [
45
45
  "SQLAlchemy-Utils",
46
46
  "waitress",
47
47
  "WebHelpers2",
48
- "WuttJamaican[db]>=0.28.0",
48
+ "WuttJamaican[db]>=0.28.1",
49
49
  "zope.sqlalchemy>=1.5",
50
50
  ]
51
51
 
@@ -53,7 +53,7 @@ dependencies = [
53
53
  [project.optional-dependencies]
54
54
  continuum = ["Wutta-Continuum>=0.3.0"]
55
55
  docs = ["Sphinx", "furo", "sphinxcontrib-programoutput"]
56
- tests = ["pylint", "pytest", "pytest-cov", "tox"]
56
+ tests = ["pylint", "pytest", "pytest-cov", "tox", "WebTest"]
57
57
 
58
58
 
59
59
  [project.entry-points."fanstatic.libraries"]
@@ -164,6 +164,11 @@ def make_pyramid_config(settings):
164
164
  )
165
165
  pyramid_config.add_directive("add_wutta_permission", "wuttaweb.auth.add_permission")
166
166
 
167
+ # add some more config magic
168
+ pyramid_config.add_directive(
169
+ "add_wutta_master_view", "wuttaweb.conf.add_master_view"
170
+ )
171
+
167
172
  return pyramid_config
168
173
 
169
174
 
@@ -0,0 +1,116 @@
1
+ ## -*- coding: utf-8; mode: python; -*-
2
+ # -*- coding: utf-8; -*-
3
+ """
4
+ Master view for ${model_title_plural}
5
+ """
6
+
7
+ % if model_option == "model_class":
8
+ from ${model_module} import ${model_name}
9
+ % endif
10
+
11
+ from wuttaweb.views import MasterView
12
+
13
+
14
+ class ${class_name}(MasterView):
15
+ """
16
+ Master view for ${model_title_plural}
17
+ """
18
+ % if model_option == "model_class":
19
+ model_class = ${model_name}
20
+ % else:
21
+ model_name = "${model_name}"
22
+ % endif
23
+ model_title = "${model_title}"
24
+ model_title_plural = "${model_title_plural}"
25
+
26
+ route_prefix = "${route_prefix}"
27
+ % if permission_prefix != route_prefix:
28
+ permission_prefix = "${permission_prefix}"
29
+ % endif
30
+ url_prefix = "${url_prefix}"
31
+ % if template_prefix != url_prefix:
32
+ template_prefix = "${template_prefix}"
33
+ % endif
34
+
35
+ % if not listable:
36
+ listable = False
37
+ % endif
38
+ creatable = ${creatable}
39
+ % if not viewable:
40
+ viewable = ${viewable}
41
+ % endif
42
+ editable = ${editable}
43
+ deletable = ${deletable}
44
+
45
+ % if listable and model_option == "model_name":
46
+ filterable = False
47
+ sort_on_backend = False
48
+ paginate_on_backend = False
49
+ % endif
50
+
51
+ % if grid_columns:
52
+ grid_columns = [
53
+ % for field in grid_columns:
54
+ "${field}",
55
+ % endfor
56
+ ]
57
+ % elif model_option == "model_name":
58
+ # TODO: must specify grid columns before the list view will work:
59
+ # grid_columns = [
60
+ # "foo",
61
+ # "bar",
62
+ # ]
63
+ % endif
64
+
65
+ % if form_fields:
66
+ form_fields = [
67
+ % for field in form_fields:
68
+ "${field}",
69
+ % endfor
70
+ ]
71
+ % elif model_option == "model_name":
72
+ # TODO: must specify form fields before create/view/edit/delete will work:
73
+ # form_fields = [
74
+ # "foo",
75
+ # "bar",
76
+ # ]
77
+ % endif
78
+
79
+ % if listable and model_option == "model_name":
80
+ def get_grid_data(self, columns=None, session=None):
81
+ data = []
82
+
83
+ # TODO: you should return whatever data is needed for the grid.
84
+ # it is expected to be a list of dicts, with keys corresponding
85
+ # to grid columns.
86
+ #
87
+ # data = [
88
+ # {"foo": 1, "bar": "abc"},
89
+ # {"foo": 2, "bar": "def"},
90
+ # ]
91
+
92
+ return data
93
+ % endif
94
+
95
+ % if listable:
96
+ def configure_grid(self, grid):
97
+ g = grid
98
+ super().configure_grid(g)
99
+
100
+ # TODO: tweak grid however you need here
101
+ #
102
+ # g.set_label("foo", "FOO")
103
+ # g.set_link("foo")
104
+ # g.set_renderer("foo", self.render_special_field)
105
+ % endif
106
+
107
+
108
+ def defaults(config, **kwargs):
109
+ base = globals()
110
+
111
+ ${class_name} = kwargs.get('${class_name}', base['${class_name}'])
112
+ ${class_name}.defaults(config)
113
+
114
+
115
+ def includeme(config):
116
+ defaults(config)
@@ -0,0 +1,89 @@
1
+ # -*- coding: utf-8; -*-
2
+ ################################################################################
3
+ #
4
+ # wuttaweb -- Web App for Wutta Framework
5
+ # Copyright © 2024-2025 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 used for SQLAlchemy-Continuum, to
35
+ :class:`~wuttaweb.db.continuum.WuttaWebContinuumPlugin`. Which is
36
+ only relevant if Wutta-Continuum is installed and enabled. For
37
+ more info see :doc:`wutta-continuum:index`.
38
+ """
39
+
40
+ key = "wuttaweb"
41
+
42
+ def configure(self, config): # pylint: disable=empty-docstring
43
+ """ """
44
+ config.setdefault(
45
+ "wutta_continuum.wutta_plugin_spec",
46
+ "wuttaweb.db.continuum:WuttaWebContinuumPlugin",
47
+ )
48
+
49
+
50
+ def add_master_view(config, master):
51
+ """
52
+ Pyramid directive to add the given ``MasterView`` subclass to the
53
+ app's registry.
54
+
55
+ This allows the app to dynamically present certain options for
56
+ admin features etc.
57
+
58
+ This is normally called automatically for all master views, within
59
+ the :meth:`~wuttaweb.views.master.MasterView.defaults()` method.
60
+
61
+ Should you need to call this yourself, do not call it directly but
62
+ instead make a similar call via the Pyramid config object::
63
+
64
+ pyramid_config.add_wutta_master_view(PoserWidgetView)
65
+
66
+ :param config: Reference to the Pyramid config object.
67
+
68
+ :param master: Reference to a
69
+ :class:`~wuttaweb.views.master.MasterView` subclass.
70
+
71
+ This function is involved in app startup; once that phase is
72
+ complete you can inspect the master views like so::
73
+
74
+ master_views = request.registry.settings["wuttaweb_master_views"]
75
+
76
+ # find master views for given model class
77
+ user_views = master_views.get(model.User, [])
78
+
79
+ # some master views are registered by model name instead (if no class)
80
+ email_views = master_views.get("email_setting", [])
81
+ """
82
+ key = master.get_model_class() or master.get_model_name()
83
+
84
+ def action():
85
+ master_views = config.get_settings().get("wuttaweb_master_views", {})
86
+ master_views.setdefault(key, []).append(master)
87
+ config.add_settings({"wuttaweb_master_views": master_views})
88
+
89
+ config.action(None, action)
@@ -48,11 +48,15 @@ else:
48
48
  request = get_current_request()
49
49
  if request:
50
50
  return request.client_addr
51
- return None
51
+
52
+ # nb. no request presumably means running as cli
53
+ return super().get_remote_addr(uow, session)
52
54
 
53
55
  def get_user_id(self, uow, session): # pylint: disable=empty-docstring
54
56
  """ """
55
57
  request = get_current_request()
56
- if request and request.user:
57
- return request.user.uuid
58
- return None
58
+ if request:
59
+ return request.user.uuid if request.user else None
60
+
61
+ # nb. no request presumably means running as cli
62
+ return super().get_user_id(uow, session)
@@ -274,7 +274,7 @@ class WuttaDateTimeWidget(DateTimeInputWidget):
274
274
  if not cstruct:
275
275
  return ""
276
276
  dt = datetime.datetime.fromisoformat(cstruct)
277
- return self.app.render_datetime(dt)
277
+ return self.app.render_datetime(dt, html=True)
278
278
 
279
279
  return super().serialize(field, cstruct, **kw)
280
280
 
@@ -2041,7 +2041,7 @@ class Grid: # pylint: disable=too-many-instance-attributes,too-many-public-meth
2041
2041
  grid.set_renderer('foo', 'datetime')
2042
2042
  """
2043
2043
  dt = getattr(obj, key)
2044
- return self.app.render_datetime(dt)
2044
+ return self.app.render_datetime(dt, html=True)
2045
2045
 
2046
2046
  def render_enum(self, obj, key, value, enum=None):
2047
2047
  """
@@ -1,6 +1,10 @@
1
1
  ## -*- coding: utf-8; -*-
2
2
  <%inherit file="/page.mako" />
3
3
 
4
+ <%def name="title()">Alembic Dashboard</%def>
5
+
6
+ <%def name="content_title()"></%def>
7
+
4
8
  <%def name="page_content()">
5
9
  <div style="display: flex; gap: 5rem; align-items: start;">
6
10
 
@@ -19,6 +19,9 @@
19
19
  <b-field horizontal label="Node Title">
20
20
  <span>${app.get_node_title()}</span>
21
21
  </b-field>
22
+ <b-field horizontal label="DB Backend">
23
+ <span>${config.appdb_engine.dialect.name}</span>
24
+ </b-field>
22
25
  <b-field horizontal label="Time Zone">
23
26
  <span>${app.get_timezone_name()}</span>
24
27
  </b-field>
@@ -34,6 +37,14 @@
34
37
 
35
38
  <div class="buttons">
36
39
 
40
+ % if request.has_perm("master_views.list"):
41
+ <wutta-button type="is-primary"
42
+ tag="a" href="${url('master_views')}"
43
+ icon-left="eye"
44
+ label="Master Views"
45
+ once />
46
+ % endif
47
+
37
48
  % if request.has_perm("app_tables.list"):
38
49
  <wutta-button type="is-primary"
39
50
  tag="a" href="${url('app_tables')}"
@@ -212,6 +212,10 @@
212
212
  padding: 1rem;
213
213
  }
214
214
 
215
+ .tool-panels-wrapper .panel-heading {
216
+ white-space: nowrap;
217
+ }
218
+
215
219
  </style>
216
220
  </%def>
217
221
 
@@ -49,6 +49,10 @@
49
49
 
50
50
  <%def name="make_vue_components()">
51
51
  ${parent.make_vue_components()}
52
+ ${self.make_vue_components_form()}
53
+ </%def>
54
+
55
+ <%def name="make_vue_components_form()">
52
56
  % if form is not Undefined:
53
57
  ${form.render_vue_finalize()}
54
58
  % endif
@@ -20,6 +20,14 @@
20
20
  once />
21
21
  % endif
22
22
 
23
+ % if request.has_perm("master_views.list"):
24
+ <wutta-button type="is-primary"
25
+ tag="a" href="${url('master_views')}"
26
+ icon-left="eye"
27
+ label="Master Views"
28
+ once />
29
+ % endif
30
+
23
31
  </div>
24
32
  ${parent.page_content()}
25
33
  </%def>
@@ -0,0 +1,31 @@
1
+ ## -*- coding: utf-8; -*-
2
+ <%inherit file="/configure.mako" />
3
+
4
+ <%def name="form_content()">
5
+
6
+ <h3 class="block is-size-3">Basics</h3>
7
+ <div class="block" style="padding-left: 2rem; width: 50%;">
8
+
9
+ <b-field label="Default location for new Master Views">
10
+ <b-select name="wuttaweb.master_views.default_module_dir"
11
+ v-model="simpleSettings['wuttaweb.master_views.default_module_dir']"
12
+ @input="settingsNeedSaved = true">
13
+ <option :value="null">(none)</option>
14
+ <option v-for="modpath in viewModuleLocations"
15
+ :value="modpath">
16
+ {{ modpath }}
17
+ </option>
18
+ </b-select>
19
+ </b-field>
20
+
21
+ </div>
22
+ </%def>
23
+
24
+ <%def name="modify_vue_vars()">
25
+ ${parent.modify_vue_vars()}
26
+ <script>
27
+
28
+ ThisPageData.viewModuleLocations = ${json.dumps(view_module_locations)|n}
29
+
30
+ </script>
31
+ </%def>