From b410b5aa02109a8d1cd5d7b4571bffc65d893dde Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Tue, 3 Feb 2026 20:27:47 -0600 Subject: [PATCH 1/5] fix: add dedicated `authenticate_user()` method for auth view in case subclass needs to tweak that behavior --- src/wuttaweb/views/auth.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/wuttaweb/views/auth.py b/src/wuttaweb/views/auth.py index f7b1d0e..6f0e9b4 100644 --- a/src/wuttaweb/views/auth.py +++ b/src/wuttaweb/views/auth.py @@ -2,7 +2,7 @@ ################################################################################ # # wuttaweb -- Web App for Wutta Framework -# Copyright © 2024-2025 Lance Edgar +# Copyright © 2024-2026 Lance Edgar # # This file is part of Wutta Framework. # @@ -49,7 +49,6 @@ class AuthView(View): """ model = self.app.model session = session or Session() - auth = self.app.get_auth_handler() # nb. redirect to /setup if no users exist user = session.query(model.User).first() @@ -79,8 +78,9 @@ class AuthView(View): if data: # truly validate user credentials - user = auth.authenticate_user(session, data["username"], data["password"]) - if user: + if user := self.authenticate_user( + session, data["username"], data["password"] + ): # okay now they're truly logged in headers = login_user(self.request, user) @@ -95,6 +95,12 @@ class AuthView(View): # 'referrer': referrer, } + def authenticate_user( + self, session, username, password + ): # pylint: disable=missing-function-docstring + auth = self.app.get_auth_handler() + return auth.authenticate_user(session, username, password) + def login_make_schema(self): # pylint: disable=empty-docstring """ """ schema = colander.Schema() From 4ac40a835b030f1fa7ab2817f9299d768438ee93 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Tue, 3 Feb 2026 20:28:41 -0600 Subject: [PATCH 2/5] test: make pylint happy --- src/wuttaweb/views/auth.py | 2 ++ src/wuttaweb/views/common.py | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/wuttaweb/views/auth.py b/src/wuttaweb/views/auth.py index 6f0e9b4..cd17a89 100644 --- a/src/wuttaweb/views/auth.py +++ b/src/wuttaweb/views/auth.py @@ -47,6 +47,7 @@ class AuthView(View): * route: ``login`` * template: ``/auth/login.mako`` """ + # pylint: disable=duplicate-code model = self.app.model session = session or Session() @@ -54,6 +55,7 @@ class AuthView(View): user = session.query(model.User).first() if not user: return self.redirect(self.request.route_url("setup")) + # pylint: enable=duplicate-code referrer = self.request.get_referrer() diff --git a/src/wuttaweb/views/common.py b/src/wuttaweb/views/common.py index 2ce78ad..d0d95e6 100644 --- a/src/wuttaweb/views/common.py +++ b/src/wuttaweb/views/common.py @@ -2,7 +2,7 @@ ################################################################################ # # wuttaweb -- Web App for Wutta Framework -# Copyright © 2024-2025 Lance Edgar +# Copyright © 2024-2026 Lance Edgar # # This file is part of Wutta Framework. # @@ -51,6 +51,7 @@ class CommonView(View): This is normally the view shown when a user navigates to the root URL for the web app. """ + # pylint: disable=duplicate-code model = self.app.model session = session or Session() @@ -58,6 +59,7 @@ class CommonView(View): user = session.query(model.User).first() if not user: return self.redirect(self.request.route_url("setup")) + # pylint: enable=duplicate-code # maybe auto-redirect anons to login if not self.request.user: From d9b880248c592f1c9787f11c01c290ed0600787f Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Wed, 4 Feb 2026 08:48:53 -0600 Subject: [PATCH 3/5] fix: fallback to dict logic for grid render date/time --- src/wuttaweb/grids/base.py | 10 ++++++++-- tests/grids/test_base.py | 13 +++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/wuttaweb/grids/base.py b/src/wuttaweb/grids/base.py index 82965ef..99f1ec6 100644 --- a/src/wuttaweb/grids/base.py +++ b/src/wuttaweb/grids/base.py @@ -2030,7 +2030,10 @@ class Grid: # pylint: disable=too-many-instance-attributes,too-many-public-meth grid.set_renderer('foo', 'date') """ - dt = getattr(obj, key) + try: + dt = getattr(obj, key) + except AttributeError: + dt = obj[key] return self.app.render_date(dt) def render_datetime(self, obj, key, value): # pylint: disable=unused-argument @@ -2046,7 +2049,10 @@ class Grid: # pylint: disable=too-many-instance-attributes,too-many-public-meth grid.set_renderer('foo', 'datetime') """ - dt = getattr(obj, key) + try: + dt = getattr(obj, key) + except AttributeError: + dt = obj[key] return self.app.render_datetime(dt, html=True) def render_enum(self, obj, key, value, enum=None): diff --git a/tests/grids/test_base.py b/tests/grids/test_base.py index b8334a6..5af544e 100644 --- a/tests/grids/test_base.py +++ b/tests/grids/test_base.py @@ -1682,6 +1682,12 @@ class TestGrid(WebTestCase): result = grid.render_date(obj, "dt", str(dt)) self.assertEqual(result, "2025-01-13") + # object as dict + dt = datetime.date(2025, 1, 13) + obj = {"dt": dt} + result = grid.render_date(obj, "dt", str(dt)) + self.assertEqual(result, "2025-01-13") + def test_render_datetime(self): tzlocal = get_timezone_by_name("America/Los_Angeles") with patch.object(self.app, "get_timezone", return_value=tzlocal): @@ -1699,6 +1705,13 @@ class TestGrid(WebTestCase): self.assertTrue(result.startswith(' Date: Wed, 4 Feb 2026 08:49:25 -0600 Subject: [PATCH 4/5] test: remove intermediate html coverage report for tox --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 56adb42..2ed5d55 100644 --- a/tox.ini +++ b/tox.ini @@ -23,7 +23,7 @@ commands = pylint wuttaweb basepython = python3.11 commands = pytest -m 'not versioned and not functional' --cov=wuttaweb - pytest -m 'versioned' --cov-append --cov=wuttaweb --cov-report=html + pytest -m 'versioned' --cov-append --cov=wuttaweb pytest -m 'functional' --cov-append --cov=wuttaweb --cov-report=html --cov-fail-under=100 [testenv:docs] From 9541bc6a27c4e6ec04ed11656410a78eb2068088 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Wed, 4 Feb 2026 08:49:58 -0600 Subject: [PATCH 5/5] =?UTF-8?q?bump:=20version=200.27.1=20=E2=86=92=200.27?= =?UTF-8?q?.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 12 ++++++++++++ pyproject.toml | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 00341dd..15bb92a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,18 @@ All notable changes to wuttaweb will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## v0.27.2 (2026-02-04) + +### Fix + +- fallback to dict logic for grid render date/time +- add dedicated `authenticate_user()` method for auth view +- increase default width for read-only form views +- add `hoverable` and `narrowed` for all `` elements +- show users grid when deleting a Person +- add `model` and `enum` to global template rendering context +- ensure grid action icon+label do not wrap + ## v0.27.1 (2026-01-03) ### Fix diff --git a/pyproject.toml b/pyproject.toml index f30e4ef..bd7ff97 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,7 +6,7 @@ build-backend = "hatchling.build" [project] name = "WuttaWeb" -version = "0.27.1" +version = "0.27.2" description = "Web App for Wutta Framework" readme = "README.md" authors = [{name = "Lance Edgar", email = "lance@wuttaproject.org"}]