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"}] 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/src/wuttaweb/views/auth.py b/src/wuttaweb/views/auth.py index f7b1d0e..cd17a89 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. # @@ -47,14 +47,15 @@ class AuthView(View): * route: ``login`` * template: ``/auth/login.mako`` """ + # pylint: disable=duplicate-code 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() if not user: return self.redirect(self.request.route_url("setup")) + # pylint: enable=duplicate-code referrer = self.request.get_referrer() @@ -79,8 +80,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 +97,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() 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: 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('