WuttaWeb 0.20.5__tar.gz → 0.20.6__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.
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/CHANGELOG.md +12 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/PKG-INFO +1 -1
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/pyproject.toml +1 -1
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/cli/webapp.py +1 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/grids/base.py +16 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/menus.py +3 -1
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/base.mako +10 -6
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/views/common.py +13 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/views/roles.py +35 -4
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/cli/test_webapp.py +4 -2
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/grids/test_base.py +18 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/views/test_roles.py +22 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/.gitignore +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/COPYING.txt +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/README.md +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/Makefile +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/_static/.keepme +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/api/wuttaweb.app.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/api/wuttaweb.auth.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/api/wuttaweb.cli.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/api/wuttaweb.cli.webapp.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/api/wuttaweb.conf.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/api/wuttaweb.db.continuum.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/api/wuttaweb.db.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/api/wuttaweb.db.sess.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/api/wuttaweb.emails.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/api/wuttaweb.forms.base.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/api/wuttaweb.forms.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/api/wuttaweb.forms.schema.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/api/wuttaweb.forms.widgets.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/api/wuttaweb.grids.base.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/api/wuttaweb.grids.filters.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/api/wuttaweb.grids.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/api/wuttaweb.handler.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/api/wuttaweb.helpers.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/api/wuttaweb.menus.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/api/wuttaweb.progress.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/api/wuttaweb.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/api/wuttaweb.static.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/api/wuttaweb.subscribers.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/api/wuttaweb.util.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/api/wuttaweb.views.auth.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/api/wuttaweb.views.base.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/api/wuttaweb.views.batch.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/api/wuttaweb.views.common.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/api/wuttaweb.views.email.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/api/wuttaweb.views.essential.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/api/wuttaweb.views.master.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/api/wuttaweb.views.people.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/api/wuttaweb.views.progress.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/api/wuttaweb.views.reports.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/api/wuttaweb.views.roles.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/api/wuttaweb.views.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/api/wuttaweb.views.settings.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/api/wuttaweb.views.upgrades.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/api/wuttaweb.views.users.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/conf.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/glossary.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/index.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/make.bat +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/narr/cli/builtin.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/narr/cli/index.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/narr/templates/base.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/narr/templates/index.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/narr/templates/lookup.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/docs/narr/templates/overview.rst +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/__init__.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/_version.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/app.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/auth.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/cli/__init__.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/conf.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/db/__init__.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/db/continuum.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/db/sess.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/email-templates/feedback.html.mako +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/email-templates/feedback.txt.mako +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/emails.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/forms/__init__.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/forms/base.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/forms/schema.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/forms/widgets.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/grids/__init__.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/grids/filters.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/handler.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/helpers.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/progress.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/static/__init__.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/static/img/favicon.ico +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/static/img/logo.png +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/static/img/testing.png +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/subscribers.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/appinfo/configure.mako +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/appinfo/index.mako +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/auth/change_password.mako +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/auth/login.mako +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/base_meta.mako +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/batch/view.mako +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/configure.mako +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/deform/checkbox.pt +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/deform/checkbox_choice.pt +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/deform/checked_password.pt +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/deform/dateinput.pt +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/deform/datetimeinput.pt +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/deform/moneyinput.pt +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/deform/password.pt +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/deform/permissions.pt +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/deform/readonly/checkbox.pt +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/deform/readonly/email_recips.pt +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/deform/readonly/filedownload.pt +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/deform/readonly/notes.pt +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/deform/readonly/objectref.pt +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/deform/readonly/permissions.pt +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/deform/readonly/rolerefs.pt +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/deform/select.pt +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/deform/textarea.pt +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/deform/textinput.pt +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/email/settings/view.mako +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/forbidden.mako +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/form.mako +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/forms/vue_template.mako +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/grids/table_element.mako +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/grids/vue_template.mako +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/home.mako +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/master/configure.mako +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/master/create.mako +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/master/delete.mako +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/master/edit.mako +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/master/form.mako +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/master/index.mako +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/master/view.mako +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/notfound.mako +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/page.mako +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/people/view_profile.mako +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/progress.mako +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/reports/view.mako +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/setup.mako +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/upgrade.mako +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/upgrades/configure.mako +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/upgrades/view.mako +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/templates/wutta-components.mako +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/testing.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/util.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/views/__init__.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/views/auth.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/views/base.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/views/batch.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/views/email.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/views/essential.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/views/master.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/views/people.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/views/progress.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/views/reports.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/views/settings.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/views/upgrades.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/src/wuttaweb/views/users.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tasks.py +0 -0
- {wuttaweb-0.20.5/tests/views → wuttaweb-0.20.6/tests}/__init__.py +0 -0
- {wuttaweb-0.20.5/tests/grids → wuttaweb-0.20.6/tests/cli}/__init__.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/db/__init__.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/db/test_continuum.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/forms/test_base.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/forms/test_schema.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/forms/test_widgets.py +0 -0
- {wuttaweb-0.20.5/tests/cli → wuttaweb-0.20.6/tests/grids}/__init__.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/grids/test_filters.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/libcache/bb_fontawesome_svg_core.js +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/libcache/bb_free_solid_svg_icons.js +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/libcache/bb_oruga.js +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/libcache/bb_oruga_bulma.css +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/libcache/bb_oruga_bulma.js +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/libcache/bb_vue.js +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/libcache/bb_vue_fontawesome.js +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/libcache/buefy.css +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/libcache/buefy.js +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/libcache/fontawesome.js +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/libcache/vue.js +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/libcache/vue_resource.js +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/test_app.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/test_auth.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/test_emails.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/test_handler.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/test_helpers.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/test_menus.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/test_progress.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/test_static.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/test_subscribers.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/test_util.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/util.py +0 -0
- {wuttaweb-0.20.5/tests → wuttaweb-0.20.6/tests/views}/__init__.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/views/test___init__.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/views/test_auth.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/views/test_base.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/views/test_batch.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/views/test_common.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/views/test_email.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/views/test_essential.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/views/test_master.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/views/test_people.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/views/test_progress.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/views/test_reports.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/views/test_settings.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/views/test_upgrades.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tests/views/test_users.py +0 -0
- {wuttaweb-0.20.5 → wuttaweb-0.20.6}/tox.ini +0 -0
|
@@ -5,6 +5,18 @@ 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.20.6 (2025-01-26)
|
|
9
|
+
|
|
10
|
+
### Fix
|
|
11
|
+
|
|
12
|
+
- add `setup_enhance_admin_user()` method for initial setup
|
|
13
|
+
- add `render_percent()` method for Grid
|
|
14
|
+
- allow override for Admin menu title
|
|
15
|
+
- add `index_title_controls()` def block for base template
|
|
16
|
+
- add `make_users_grid()` method for RoleView
|
|
17
|
+
- fallback to empty string for uvicorn `root_path`
|
|
18
|
+
- add `root_path` config setting for running webapp via uvicorn
|
|
19
|
+
|
|
8
20
|
## v0.20.5 (2025-01-23)
|
|
9
21
|
|
|
10
22
|
### Fix
|
|
@@ -74,6 +74,7 @@ def webapp(
|
|
|
74
74
|
'reload_dirs': config.get_list(f'{config.appname}.web.app.reload_dirs'),
|
|
75
75
|
'factory': config.get_bool(f'{config.appname}.web.app.factory', default=False),
|
|
76
76
|
'interface': config.get(f'{config.appname}.web.app.interface', default='auto'),
|
|
77
|
+
'root_path': config.get(f'{config.appname}.web.app.root_path', default=''),
|
|
77
78
|
}
|
|
78
79
|
|
|
79
80
|
# also must inject our config files to env, since there is no
|
|
@@ -612,6 +612,7 @@ class Grid:
|
|
|
612
612
|
* ``'date'`` -> :meth:`render_date()`
|
|
613
613
|
* ``'datetime'`` -> :meth:`render_datetime()`
|
|
614
614
|
* ``'quantity'`` -> :meth:`render_quantity()`
|
|
615
|
+
* ``'percent'`` -> :meth:`render_percent()`
|
|
615
616
|
|
|
616
617
|
Renderer overrides are tracked via :attr:`renderers`.
|
|
617
618
|
"""
|
|
@@ -622,6 +623,7 @@ class Grid:
|
|
|
622
623
|
'date': self.render_date,
|
|
623
624
|
'datetime': self.render_datetime,
|
|
624
625
|
'quantity': self.render_quantity,
|
|
626
|
+
'percent': self.render_percent,
|
|
625
627
|
}
|
|
626
628
|
|
|
627
629
|
if renderer in builtins:
|
|
@@ -1884,6 +1886,20 @@ class Grid:
|
|
|
1884
1886
|
dt = getattr(obj, key)
|
|
1885
1887
|
return self.app.render_datetime(dt)
|
|
1886
1888
|
|
|
1889
|
+
def render_percent(self, obj, key, value, **kwargs):
|
|
1890
|
+
"""
|
|
1891
|
+
Column renderer for percentage values.
|
|
1892
|
+
|
|
1893
|
+
This calls
|
|
1894
|
+
:meth:`~wuttjamaican:wuttjamaican.app.AppHandler.render_percent()`
|
|
1895
|
+
for the return value.
|
|
1896
|
+
|
|
1897
|
+
This is not used automatically but you can use it explicitly::
|
|
1898
|
+
|
|
1899
|
+
grid.set_renderer('foo', 'percent')
|
|
1900
|
+
"""
|
|
1901
|
+
return self.app.render_percent(value, **kwargs)
|
|
1902
|
+
|
|
1887
1903
|
def render_quantity(self, obj, key, value):
|
|
1888
1904
|
"""
|
|
1889
1905
|
Column renderer for quantity values.
|
|
@@ -143,6 +143,8 @@ class MenuHandler(GenericHandler):
|
|
|
143
143
|
which will ultimately be one element of the final list of
|
|
144
144
|
dicts as described in :class:`MenuHandler`.
|
|
145
145
|
|
|
146
|
+
:param title: Override the menu title; default is "Admin".
|
|
147
|
+
|
|
146
148
|
:param include_people: You can pass this flag to indicate the
|
|
147
149
|
admin menu should contain an entry for the "People" view.
|
|
148
150
|
"""
|
|
@@ -198,7 +200,7 @@ class MenuHandler(GenericHandler):
|
|
|
198
200
|
])
|
|
199
201
|
|
|
200
202
|
return {
|
|
201
|
-
'title': "Admin",
|
|
203
|
+
'title': kwargs.get('title', "Admin"),
|
|
202
204
|
'type': 'menu',
|
|
203
205
|
'items': items,
|
|
204
206
|
}
|
|
@@ -248,12 +248,7 @@
|
|
|
248
248
|
% else:
|
|
249
249
|
<h1 class="title">${index_title}</h1>
|
|
250
250
|
% endif
|
|
251
|
-
|
|
252
|
-
<wutta-button once type="is-primary"
|
|
253
|
-
tag="a" href="${url(f'{route_prefix}.create')}"
|
|
254
|
-
icon-left="plus"
|
|
255
|
-
label="Create New" />
|
|
256
|
-
% endif
|
|
251
|
+
${self.index_title_controls()}
|
|
257
252
|
% endif
|
|
258
253
|
</div>
|
|
259
254
|
</div>
|
|
@@ -349,6 +344,15 @@
|
|
|
349
344
|
</footer>
|
|
350
345
|
</%def>
|
|
351
346
|
|
|
347
|
+
<%def name="index_title_controls()">
|
|
348
|
+
% if master and master.creatable and not master.creating and master.has_perm('create'):
|
|
349
|
+
<wutta-button once type="is-primary"
|
|
350
|
+
tag="a" href="${url(f'{route_prefix}.create')}"
|
|
351
|
+
icon-left="plus"
|
|
352
|
+
label="Create New" />
|
|
353
|
+
% endif
|
|
354
|
+
</%def>
|
|
355
|
+
|
|
352
356
|
<%def name="render_vue_template_whole_page()">
|
|
353
357
|
<script type="text/x-template" id="whole-page-template">
|
|
354
358
|
|
|
@@ -245,6 +245,8 @@ class CommonView(View):
|
|
|
245
245
|
session.add(person)
|
|
246
246
|
user.person = person
|
|
247
247
|
|
|
248
|
+
self.setup_enhance_admin_user(user)
|
|
249
|
+
|
|
248
250
|
# send user to /login
|
|
249
251
|
self.request.session.flash("Account created! Please login below.")
|
|
250
252
|
return self.redirect(self.request.route_url('login'))
|
|
@@ -254,6 +256,17 @@ class CommonView(View):
|
|
|
254
256
|
'form': form,
|
|
255
257
|
}
|
|
256
258
|
|
|
259
|
+
def setup_enhance_admin_user(self, user):
|
|
260
|
+
"""
|
|
261
|
+
Further "enhance" the initial admin user when it is first created.
|
|
262
|
+
|
|
263
|
+
This does nothing by default; subclass can override if needed.
|
|
264
|
+
|
|
265
|
+
:param user: New admin
|
|
266
|
+
:class:`~wuttjamaican:wuttjamaican.db.model.auth.User`
|
|
267
|
+
which was just created as part of initial setup.
|
|
268
|
+
"""
|
|
269
|
+
|
|
257
270
|
@classmethod
|
|
258
271
|
def defaults(cls, config):
|
|
259
272
|
cls._defaults(config)
|
|
@@ -28,7 +28,7 @@ from wuttjamaican.db.model import Role, Permission
|
|
|
28
28
|
from wuttaweb.views import MasterView
|
|
29
29
|
from wuttaweb.db import Session
|
|
30
30
|
from wuttaweb.forms import widgets
|
|
31
|
-
from wuttaweb.forms.schema import
|
|
31
|
+
from wuttaweb.forms.schema import Permissions, RoleRef
|
|
32
32
|
|
|
33
33
|
|
|
34
34
|
class RoleView(MasterView):
|
|
@@ -123,9 +123,7 @@ class RoleView(MasterView):
|
|
|
123
123
|
# users
|
|
124
124
|
if not (self.creating or self.editing):
|
|
125
125
|
f.append('users')
|
|
126
|
-
f.
|
|
127
|
-
f.set_node('users', UserRefs(self.request))
|
|
128
|
-
f.set_default('users', [u.uuid for u in role.users])
|
|
126
|
+
f.set_grid('users', self.make_users_grid(role))
|
|
129
127
|
|
|
130
128
|
# permissions
|
|
131
129
|
f.append('permissions')
|
|
@@ -134,6 +132,39 @@ class RoleView(MasterView):
|
|
|
134
132
|
if not self.creating:
|
|
135
133
|
f.set_default('permissions', list(role.permissions))
|
|
136
134
|
|
|
135
|
+
def make_users_grid(self, role):
|
|
136
|
+
"""
|
|
137
|
+
Make and return the grid for the Users field.
|
|
138
|
+
|
|
139
|
+
This grid is shown for the Users field when viewing a Role.
|
|
140
|
+
|
|
141
|
+
:returns: Fully configured :class:`~wuttaweb.grids.base.Grid`
|
|
142
|
+
instance.
|
|
143
|
+
"""
|
|
144
|
+
model = self.app.model
|
|
145
|
+
route_prefix = self.get_route_prefix()
|
|
146
|
+
|
|
147
|
+
grid = self.make_grid(key=f'{route_prefix}.view.users',
|
|
148
|
+
model_class=model.User,
|
|
149
|
+
data=role.users,
|
|
150
|
+
columns=[
|
|
151
|
+
'username',
|
|
152
|
+
'person',
|
|
153
|
+
'active',
|
|
154
|
+
])
|
|
155
|
+
|
|
156
|
+
if self.request.has_perm('users.view'):
|
|
157
|
+
url = lambda user, i: self.request.route_url('users.view', uuid=user.uuid)
|
|
158
|
+
grid.add_action('view', icon='eye', url=url)
|
|
159
|
+
grid.set_link('person')
|
|
160
|
+
grid.set_link('username')
|
|
161
|
+
|
|
162
|
+
if self.request.has_perm('users.edit'):
|
|
163
|
+
url = lambda user, i: self.request.route_url('users.edit', uuid=user.uuid)
|
|
164
|
+
grid.add_action('edit', url=url)
|
|
165
|
+
|
|
166
|
+
return grid
|
|
167
|
+
|
|
137
168
|
def unique_name(self, node, value):
|
|
138
169
|
""" """
|
|
139
170
|
model = self.app.model
|
|
@@ -88,7 +88,8 @@ app.spec = wuttaweb.app:make_wsgi_app
|
|
|
88
88
|
reload=False,
|
|
89
89
|
reload_dirs=None,
|
|
90
90
|
factory=False,
|
|
91
|
-
interface='auto'
|
|
91
|
+
interface='auto',
|
|
92
|
+
root_path='')
|
|
92
93
|
|
|
93
94
|
# with reload
|
|
94
95
|
uvicorn.run.reset_mock()
|
|
@@ -101,4 +102,5 @@ app.spec = wuttaweb.app:make_wsgi_app
|
|
|
101
102
|
reload=True,
|
|
102
103
|
reload_dirs=None,
|
|
103
104
|
factory=False,
|
|
104
|
-
interface='auto'
|
|
105
|
+
interface='auto',
|
|
106
|
+
root_path='')
|
|
@@ -1409,6 +1409,24 @@ class TestGrid(WebTestCase):
|
|
|
1409
1409
|
value = decimal.Decimal('-42.42')
|
|
1410
1410
|
self.assertEqual(grid.render_currency(obj, 'foo', value), '($42.42)')
|
|
1411
1411
|
|
|
1412
|
+
def test_render_percent(self):
|
|
1413
|
+
grid = self.make_grid(columns=['foo', 'bar'])
|
|
1414
|
+
obj = MagicMock()
|
|
1415
|
+
|
|
1416
|
+
# null
|
|
1417
|
+
self.assertEqual(grid.render_percent(obj, 'foo', None), "")
|
|
1418
|
+
|
|
1419
|
+
# typical
|
|
1420
|
+
self.assertEqual(grid.render_percent(obj, 'foo', 12.3419), '12.34 %')
|
|
1421
|
+
|
|
1422
|
+
# more decimal places
|
|
1423
|
+
self.assertEqual(grid.render_percent(obj, 'foo', 12.3419, decimals=3), '12.342 %')
|
|
1424
|
+
self.assertEqual(grid.render_percent(obj, 'foo', 12.3419, decimals=4), '12.3419 %')
|
|
1425
|
+
|
|
1426
|
+
# negative
|
|
1427
|
+
self.assertEqual(grid.render_percent(obj, 'foo', -12.3419), '(12.34 %)')
|
|
1428
|
+
self.assertEqual(grid.render_percent(obj, 'foo', -12.3419, decimals=3), '(12.342 %)')
|
|
1429
|
+
|
|
1412
1430
|
def test_render_quantity(self):
|
|
1413
1431
|
grid = self.make_grid(columns=['foo', 'bar'])
|
|
1414
1432
|
obj = MagicMock()
|
|
@@ -7,6 +7,7 @@ from sqlalchemy import orm
|
|
|
7
7
|
import colander
|
|
8
8
|
|
|
9
9
|
from wuttaweb.views import roles as mod
|
|
10
|
+
from wuttaweb.grids import Grid
|
|
10
11
|
from wuttaweb.forms.schema import RoleRef
|
|
11
12
|
from wuttaweb.testing import WebTestCase
|
|
12
13
|
|
|
@@ -93,6 +94,27 @@ class TestRoleView(WebTestCase):
|
|
|
93
94
|
view.configure_form(form)
|
|
94
95
|
self.assertIsNotNone(form.validators['name'])
|
|
95
96
|
|
|
97
|
+
def test_make_users_grid(self):
|
|
98
|
+
model = self.app.model
|
|
99
|
+
view = self.make_view()
|
|
100
|
+
role = model.Role(name="Manager")
|
|
101
|
+
|
|
102
|
+
# basic
|
|
103
|
+
grid = view.make_users_grid(role)
|
|
104
|
+
self.assertIsInstance(grid, Grid)
|
|
105
|
+
self.assertFalse(grid.linked_columns)
|
|
106
|
+
self.assertFalse(grid.actions)
|
|
107
|
+
|
|
108
|
+
# view + edit actions
|
|
109
|
+
with patch.object(self.request, 'is_root', new=True):
|
|
110
|
+
grid = view.make_users_grid(role)
|
|
111
|
+
self.assertIsInstance(grid, Grid)
|
|
112
|
+
self.assertIn('person', grid.linked_columns)
|
|
113
|
+
self.assertIn('username', grid.linked_columns)
|
|
114
|
+
self.assertEqual(len(grid.actions), 2)
|
|
115
|
+
self.assertEqual(grid.actions[0].key, 'view')
|
|
116
|
+
self.assertEqual(grid.actions[1].key, 'edit')
|
|
117
|
+
|
|
96
118
|
def test_unique_name(self):
|
|
97
119
|
model = self.app.model
|
|
98
120
|
view = self.make_view()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|