WuttaWeb 0.25.1__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 (249) hide show
  1. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/CHANGELOG.md +36 -0
  2. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/PKG-INFO +4 -2
  3. wuttaweb-0.27.0/docs/api/wuttaweb.views.alembic.rst +6 -0
  4. wuttaweb-0.27.0/docs/api/wuttaweb.views.tables.rst +6 -0
  5. wuttaweb-0.27.0/docs/api/wuttaweb.views.views.rst +6 -0
  6. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/conf.py +1 -0
  7. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/index.rst +3 -0
  8. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/pyproject.toml +4 -3
  9. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/app.py +5 -0
  10. wuttaweb-0.27.0/src/wuttaweb/code-templates/new-master-view.mako +116 -0
  11. wuttaweb-0.27.0/src/wuttaweb/code-templates/new-table.mako +68 -0
  12. wuttaweb-0.27.0/src/wuttaweb/conf.py +89 -0
  13. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/db/continuum.py +8 -4
  14. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/forms/base.py +175 -24
  15. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/forms/widgets.py +75 -2
  16. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/grids/base.py +13 -8
  17. wuttaweb-0.27.0/src/wuttaweb/templates/alembic/dashboard.mako +238 -0
  18. wuttaweb-0.27.0/src/wuttaweb/templates/alembic/migrations/configure.mako +31 -0
  19. wuttaweb-0.27.0/src/wuttaweb/templates/alembic/migrations/create.mako +70 -0
  20. wuttaweb-0.27.0/src/wuttaweb/templates/alembic/migrations/index.mako +25 -0
  21. wuttaweb-0.27.0/src/wuttaweb/templates/alembic/migrations/view.mako +17 -0
  22. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/appinfo/index.mako +31 -0
  23. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/base.mako +4 -0
  24. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/deform/checkbox.pt +4 -2
  25. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/form.mako +12 -6
  26. wuttaweb-0.27.0/src/wuttaweb/templates/forms/vue_buttons.mako +43 -0
  27. wuttaweb-0.27.0/src/wuttaweb/templates/forms/vue_fields.mako +4 -0
  28. wuttaweb-0.27.0/src/wuttaweb/templates/forms/vue_template.mako +54 -0
  29. wuttaweb-0.27.0/src/wuttaweb/templates/tables/app/create.mako +1035 -0
  30. wuttaweb-0.27.0/src/wuttaweb/templates/tables/app/index.mako +33 -0
  31. wuttaweb-0.27.0/src/wuttaweb/templates/upgrades/index.mako +14 -0
  32. wuttaweb-0.27.0/src/wuttaweb/templates/views/master/configure.mako +31 -0
  33. wuttaweb-0.27.0/src/wuttaweb/templates/views/master/create.mako +846 -0
  34. wuttaweb-0.27.0/src/wuttaweb/templates/views/master/index.mako +17 -0
  35. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/wutta-components.mako +67 -0
  36. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/testing.py +60 -4
  37. wuttaweb-0.27.0/src/wuttaweb/views/alembic.py +565 -0
  38. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/views/batch.py +2 -2
  39. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/views/common.py +3 -3
  40. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/views/essential.py +25 -1
  41. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/views/master.py +285 -172
  42. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/views/reports.py +1 -0
  43. wuttaweb-0.27.0/src/wuttaweb/views/tables.py +486 -0
  44. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/views/upgrades.py +0 -6
  45. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/views/users.py +1 -0
  46. wuttaweb-0.27.0/src/wuttaweb/views/views.py +469 -0
  47. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tasks.py +2 -1
  48. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/db/test_continuum.py +8 -4
  49. wuttaweb-0.27.0/tests/forms/main_template.mako +9 -0
  50. wuttaweb-0.27.0/tests/forms/main_template_with_fields.mako +11 -0
  51. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/forms/test_base.py +43 -29
  52. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/forms/test_widgets.py +129 -1
  53. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/grids/test_base.py +15 -2
  54. wuttaweb-0.27.0/tests/test_conf.py +61 -0
  55. wuttaweb-0.27.0/tests/views/test_alembic.py +460 -0
  56. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/views/test_master.py +127 -48
  57. wuttaweb-0.27.0/tests/views/test_tables.py +369 -0
  58. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/views/test_users.py +180 -1
  59. wuttaweb-0.27.0/tests/views/test_views.py +370 -0
  60. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tox.ini +8 -4
  61. wuttaweb-0.25.1/src/wuttaweb/conf.py +0 -46
  62. wuttaweb-0.25.1/src/wuttaweb/templates/forms/vue_template.mako +0 -99
  63. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/.gitignore +0 -0
  64. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/.hgignore +0 -0
  65. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/.pylintrc +0 -0
  66. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/COPYING.txt +0 -0
  67. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/README.md +0 -0
  68. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/Makefile +0 -0
  69. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/_static/.keepme +0 -0
  70. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/api/wuttaweb.app.rst +0 -0
  71. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/api/wuttaweb.auth.rst +0 -0
  72. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/api/wuttaweb.cli.rst +0 -0
  73. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/api/wuttaweb.cli.webapp.rst +0 -0
  74. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/api/wuttaweb.conf.rst +0 -0
  75. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/api/wuttaweb.db.continuum.rst +0 -0
  76. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/api/wuttaweb.db.rst +0 -0
  77. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/api/wuttaweb.db.sess.rst +0 -0
  78. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/api/wuttaweb.diffs.rst +0 -0
  79. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/api/wuttaweb.emails.rst +0 -0
  80. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/api/wuttaweb.forms.base.rst +0 -0
  81. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/api/wuttaweb.forms.rst +0 -0
  82. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/api/wuttaweb.forms.schema.rst +0 -0
  83. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/api/wuttaweb.forms.widgets.rst +0 -0
  84. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/api/wuttaweb.grids.base.rst +0 -0
  85. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/api/wuttaweb.grids.filters.rst +0 -0
  86. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/api/wuttaweb.grids.rst +0 -0
  87. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/api/wuttaweb.handler.rst +0 -0
  88. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/api/wuttaweb.helpers.rst +0 -0
  89. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/api/wuttaweb.menus.rst +0 -0
  90. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/api/wuttaweb.progress.rst +0 -0
  91. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/api/wuttaweb.rst +0 -0
  92. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/api/wuttaweb.static.rst +0 -0
  93. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/api/wuttaweb.subscribers.rst +0 -0
  94. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/api/wuttaweb.util.rst +0 -0
  95. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/api/wuttaweb.views.auth.rst +0 -0
  96. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/api/wuttaweb.views.base.rst +0 -0
  97. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/api/wuttaweb.views.batch.rst +0 -0
  98. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/api/wuttaweb.views.common.rst +0 -0
  99. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/api/wuttaweb.views.email.rst +0 -0
  100. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/api/wuttaweb.views.essential.rst +0 -0
  101. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/api/wuttaweb.views.master.rst +0 -0
  102. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/api/wuttaweb.views.people.rst +0 -0
  103. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/api/wuttaweb.views.progress.rst +0 -0
  104. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/api/wuttaweb.views.reports.rst +0 -0
  105. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/api/wuttaweb.views.roles.rst +0 -0
  106. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/api/wuttaweb.views.rst +0 -0
  107. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/api/wuttaweb.views.settings.rst +0 -0
  108. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/api/wuttaweb.views.upgrades.rst +0 -0
  109. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/api/wuttaweb.views.users.rst +0 -0
  110. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/glossary.rst +0 -0
  111. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/make.bat +0 -0
  112. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/narr/cli/builtin.rst +0 -0
  113. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/narr/cli/index.rst +0 -0
  114. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/narr/templates/base.rst +0 -0
  115. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/narr/templates/index.rst +0 -0
  116. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/narr/templates/lookup.rst +0 -0
  117. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/docs/narr/templates/overview.rst +0 -0
  118. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/__init__.py +0 -0
  119. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/_version.py +0 -0
  120. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/auth.py +0 -0
  121. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/cli/__init__.py +0 -0
  122. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/cli/webapp.py +0 -0
  123. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/db/__init__.py +0 -0
  124. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/db/sess.py +0 -0
  125. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/diffs.py +0 -0
  126. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/email-templates/feedback.html.mako +0 -0
  127. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/email-templates/feedback.txt.mako +0 -0
  128. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/emails.py +0 -0
  129. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/forms/__init__.py +0 -0
  130. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/forms/schema.py +0 -0
  131. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/grids/__init__.py +0 -0
  132. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/grids/filters.py +0 -0
  133. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/handler.py +0 -0
  134. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/helpers.py +0 -0
  135. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/menus.py +0 -0
  136. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/progress.py +0 -0
  137. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/static/__init__.py +0 -0
  138. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/static/img/favicon.ico +0 -0
  139. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/static/img/logo.png +0 -0
  140. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/static/img/testing.png +0 -0
  141. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/subscribers.py +0 -0
  142. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/appinfo/configure.mako +0 -0
  143. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/auth/change_password.mako +0 -0
  144. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/auth/login.mako +0 -0
  145. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/base_meta.mako +0 -0
  146. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/batch/view.mako +0 -0
  147. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/configure.mako +0 -0
  148. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/deform/checkbox_choice.pt +0 -0
  149. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/deform/checked_password.pt +0 -0
  150. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/deform/dateinput.pt +0 -0
  151. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/deform/datetimeinput.pt +0 -0
  152. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/deform/moneyinput.pt +0 -0
  153. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/deform/password.pt +0 -0
  154. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/deform/permissions.pt +0 -0
  155. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/deform/readonly/checkbox.pt +0 -0
  156. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/deform/readonly/email_recips.pt +0 -0
  157. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/deform/readonly/filedownload.pt +0 -0
  158. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/deform/readonly/notes.pt +0 -0
  159. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/deform/readonly/objectref.pt +0 -0
  160. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/deform/readonly/permissions.pt +0 -0
  161. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/deform/readonly/rolerefs.pt +0 -0
  162. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/deform/select.pt +0 -0
  163. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/deform/textarea.pt +0 -0
  164. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/deform/textinput.pt +0 -0
  165. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/deform/wutta_checked_password.pt +0 -0
  166. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/diff.mako +0 -0
  167. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/email/settings/view.mako +0 -0
  168. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/forbidden.mako +0 -0
  169. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/grids/table_element.mako +0 -0
  170. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/grids/vue_template.mako +0 -0
  171. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/home.mako +0 -0
  172. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/master/configure.mako +0 -0
  173. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/master/create.mako +0 -0
  174. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/master/create_row.mako +0 -0
  175. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/master/delete.mako +0 -0
  176. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/master/edit.mako +0 -0
  177. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/master/form.mako +0 -0
  178. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/master/index.mako +0 -0
  179. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/master/view.mako +0 -0
  180. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/master/view_version.mako +0 -0
  181. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/master/view_versions.mako +0 -0
  182. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/notfound.mako +0 -0
  183. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/page.mako +0 -0
  184. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/people/view_profile.mako +0 -0
  185. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/progress.mako +0 -0
  186. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/reports/view.mako +0 -0
  187. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/setup.mako +0 -0
  188. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/themes/butterfly/base.mako +0 -0
  189. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/themes/butterfly/buefy-components.mako +0 -0
  190. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/themes/butterfly/buefy-plugin.mako +0 -0
  191. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/themes/butterfly/http-plugin.mako +0 -0
  192. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/upgrade.mako +0 -0
  193. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/upgrades/configure.mako +0 -0
  194. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/upgrades/view.mako +0 -0
  195. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/templates/users/view.mako +0 -0
  196. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/util.py +0 -0
  197. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/views/__init__.py +0 -0
  198. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/views/auth.py +0 -0
  199. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/views/base.py +0 -0
  200. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/views/email.py +0 -0
  201. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/views/people.py +0 -0
  202. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/views/progress.py +0 -0
  203. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/views/roles.py +0 -0
  204. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/src/wuttaweb/views/settings.py +0 -0
  205. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/__init__.py +0 -0
  206. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/cli/__init__.py +0 -0
  207. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/cli/test_webapp.py +0 -0
  208. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/db/__init__.py +0 -0
  209. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/forms/test_schema.py +0 -0
  210. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/grids/__init__.py +0 -0
  211. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/grids/test_filters.py +0 -0
  212. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/libcache/bb_fontawesome_svg_core.js +0 -0
  213. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/libcache/bb_free_solid_svg_icons.js +0 -0
  214. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/libcache/bb_oruga.js +0 -0
  215. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/libcache/bb_oruga_bulma.css +0 -0
  216. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/libcache/bb_oruga_bulma.js +0 -0
  217. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/libcache/bb_vue.js +0 -0
  218. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/libcache/bb_vue_fontawesome.js +0 -0
  219. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/libcache/buefy.css +0 -0
  220. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/libcache/buefy.js +0 -0
  221. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/libcache/fontawesome.js +0 -0
  222. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/libcache/vue.js +0 -0
  223. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/libcache/vue_resource.js +0 -0
  224. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/test_app.py +0 -0
  225. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/test_auth.py +0 -0
  226. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/test_diffs.py +0 -0
  227. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/test_emails.py +0 -0
  228. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/test_handler.py +0 -0
  229. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/test_helpers.py +0 -0
  230. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/test_menus.py +0 -0
  231. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/test_progress.py +0 -0
  232. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/test_static.py +0 -0
  233. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/test_subscribers.py +0 -0
  234. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/test_util.py +0 -0
  235. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/util.py +0 -0
  236. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/views/__init__.py +0 -0
  237. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/views/test___init__.py +0 -0
  238. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/views/test_auth.py +0 -0
  239. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/views/test_base.py +0 -0
  240. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/views/test_batch.py +0 -0
  241. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/views/test_common.py +0 -0
  242. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/views/test_email.py +0 -0
  243. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/views/test_essential.py +0 -0
  244. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/views/test_people.py +0 -0
  245. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/views/test_progress.py +0 -0
  246. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/views/test_reports.py +0 -0
  247. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/views/test_roles.py +0 -0
  248. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/views/test_settings.py +0 -0
  249. {wuttaweb-0.25.1 → wuttaweb-0.27.0}/tests/views/test_upgrades.py +0 -0
@@ -5,6 +5,42 @@ 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
+
25
+ ## v0.26.0 (2025-12-28)
26
+
27
+ ### Feat
28
+
29
+ - add "wizard" for creating new table/model/revision
30
+ - add support for Create Alembic Migration
31
+ - add CopyableTextWidget and `<wutta-copyable-text>` component
32
+ - overhaul how form vue template is rendered
33
+ - add basic views for Alembic Migrations, Dashboard
34
+ - add basic Table views
35
+
36
+ ### Fix
37
+
38
+ - let checkbox widget show static text instead of Yes/No
39
+ - rename form-saving methods etc. for consistency in MasterView
40
+ - temporarily avoid make_uuid()
41
+ - remove password filter option for Users grid
42
+ - use smarter default for `grid.sort_multiple` based on model class
43
+
8
44
  ## v0.25.1 (2025-12-20)
9
45
 
10
46
  ### Fix
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: WuttaWeb
3
- Version: 0.25.1
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
@@ -37,9 +37,10 @@ Requires-Dist: pyramid-fanstatic
37
37
  Requires-Dist: pyramid-mako
38
38
  Requires-Dist: pyramid-tm
39
39
  Requires-Dist: pyramid>=2
40
+ Requires-Dist: sqlalchemy-utils
40
41
  Requires-Dist: waitress
41
42
  Requires-Dist: webhelpers2
42
- Requires-Dist: wuttjamaican[db]>=0.27.0
43
+ Requires-Dist: wuttjamaican[db]>=0.28.1
43
44
  Requires-Dist: zope-sqlalchemy>=1.5
44
45
  Provides-Extra: continuum
45
46
  Requires-Dist: wutta-continuum>=0.3.0; extra == 'continuum'
@@ -52,6 +53,7 @@ Requires-Dist: pylint; extra == 'tests'
52
53
  Requires-Dist: pytest; extra == 'tests'
53
54
  Requires-Dist: pytest-cov; extra == 'tests'
54
55
  Requires-Dist: tox; extra == 'tests'
56
+ Requires-Dist: webtest; extra == 'tests'
55
57
  Description-Content-Type: text/markdown
56
58
 
57
59
 
@@ -0,0 +1,6 @@
1
+
2
+ ``wuttaweb.views.alembic``
3
+ ==========================
4
+
5
+ .. automodule:: wuttaweb.views.alembic
6
+ :members:
@@ -0,0 +1,6 @@
1
+
2
+ ``wuttaweb.views.tables``
3
+ =========================
4
+
5
+ .. automodule:: wuttaweb.views.tables
6
+ :members:
@@ -0,0 +1,6 @@
1
+
2
+ ``wuttaweb.views.views``
3
+ ========================
4
+
5
+ .. automodule:: wuttaweb.views.views
6
+ :members:
@@ -28,6 +28,7 @@ templates_path = ["_templates"]
28
28
  exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
29
29
 
30
30
  intersphinx_mapping = {
31
+ "alembic": ("https://alembic.sqlalchemy.org/en/latest/", None),
31
32
  "colander": ("https://docs.pylonsproject.org/projects/colander/en/latest/", None),
32
33
  "deform": ("https://docs.pylonsproject.org/projects/deform/en/latest/", None),
33
34
  "fanstatic": ("https://www.fanstatic.org/en/latest/", None),
@@ -58,6 +58,7 @@ the narrative docs are pretty scant. That will eventually change.
58
58
  api/wuttaweb.subscribers
59
59
  api/wuttaweb.util
60
60
  api/wuttaweb.views
61
+ api/wuttaweb.views.alembic
61
62
  api/wuttaweb.views.auth
62
63
  api/wuttaweb.views.base
63
64
  api/wuttaweb.views.batch
@@ -70,8 +71,10 @@ the narrative docs are pretty scant. That will eventually change.
70
71
  api/wuttaweb.views.reports
71
72
  api/wuttaweb.views.roles
72
73
  api/wuttaweb.views.settings
74
+ api/wuttaweb.views.tables
73
75
  api/wuttaweb.views.upgrades
74
76
  api/wuttaweb.views.users
77
+ api/wuttaweb.views.views
75
78
 
76
79
 
77
80
  Indices and tables
@@ -6,7 +6,7 @@ build-backend = "hatchling.build"
6
6
 
7
7
  [project]
8
8
  name = "WuttaWeb"
9
- version = "0.25.1"
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"}]
@@ -42,9 +42,10 @@ dependencies = [
42
42
  "pyramid_fanstatic",
43
43
  "pyramid_mako",
44
44
  "pyramid_tm",
45
+ "SQLAlchemy-Utils",
45
46
  "waitress",
46
47
  "WebHelpers2",
47
- "WuttJamaican[db]>=0.27.0",
48
+ "WuttJamaican[db]>=0.28.1",
48
49
  "zope.sqlalchemy>=1.5",
49
50
  ]
50
51
 
@@ -52,7 +53,7 @@ dependencies = [
52
53
  [project.optional-dependencies]
53
54
  continuum = ["Wutta-Continuum>=0.3.0"]
54
55
  docs = ["Sphinx", "furo", "sphinxcontrib-programoutput"]
55
- tests = ["pylint", "pytest", "pytest-cov", "tox"]
56
+ tests = ["pylint", "pytest", "pytest-cov", "tox", "WebTest"]
56
57
 
57
58
 
58
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,68 @@
1
+ ## -*- coding: utf-8; mode: python; -*-
2
+ # -*- coding: utf-8; -*-
3
+ """
4
+ Model definition for ${model_title_plural}
5
+ """
6
+
7
+ import sqlalchemy as sa
8
+ from sqlalchemy import orm
9
+
10
+ from wuttjamaican.db import model
11
+
12
+
13
+ class ${model_name}(model.Base):
14
+ """
15
+ ${description}
16
+ """
17
+ __tablename__ = "${table_name}"
18
+ % if any([c["data_type"]["type"] == "_fk_uuid_" for c in columns]):
19
+ __table_args__ = (
20
+ % for column in columns:
21
+ % if column["data_type"]["type"] == "_fk_uuid_":
22
+ sa.ForeignKeyConstraint(["${column['name']}"], ["${column['data_type']['reference']}.uuid"],
23
+ name="${table_name}_fk_${column['data_type']['reference']}"),
24
+ % endif
25
+ % endfor
26
+ )
27
+ % endif
28
+ % if versioned:
29
+ % if all([c["versioned"] for c in columns]):
30
+ __versioned__ = {}
31
+ % else:
32
+ __versioned__ = {
33
+ "exclude": [
34
+ % for column in columns:
35
+ % if not column["versioned"]:
36
+ "${column['name']}",
37
+ % endif
38
+ % endfor
39
+ ],
40
+ }
41
+ % endif
42
+ % endif
43
+ __wutta_hint__ = {
44
+ "model_title": "${model_title}",
45
+ "model_title_plural": "${model_title_plural}",
46
+ }
47
+ % for column in columns:
48
+
49
+ % if column["name"] == "uuid":
50
+ uuid = model.uuid_column()
51
+ % else:
52
+ ${column["name"]} = sa.Column(${column["formatted_data_type"]}, nullable=${column["nullable"]}, doc="""
53
+ ${column["description"] or ""}
54
+ """)
55
+ % if column["data_type"]["type"] == "_fk_uuid_" and column["relationship"]:
56
+ ${column["relationship"]["name"]} = orm.relationship(
57
+ "${column['relationship']['reference_model']}",
58
+ doc="""
59
+ ${column["description"] or ""}
60
+ """)
61
+ % endif
62
+ % endif
63
+ % endfor
64
+
65
+ # TODO: you usually should define the __str__() method
66
+
67
+ # def __str__(self):
68
+ # return self.name or ""
@@ -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)