From a17d7da74ce15b0698424301b7ecf7d8b4e42746 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Fri, 2 Jan 2026 19:17:45 -0600 Subject: [PATCH 1/6] fix: accept dict instead of true enum, for `Grid.set_enum()` --- src/wuttaweb/grids/base.py | 34 +++++++++++++++++++++++++++------- tests/grids/test_base.py | 19 +++++++++++++++++-- 2 files changed, 44 insertions(+), 9 deletions(-) diff --git a/src/wuttaweb/grids/base.py b/src/wuttaweb/grids/base.py index 63829a4..313dd67 100644 --- a/src/wuttaweb/grids/base.py +++ b/src/wuttaweb/grids/base.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. # @@ -30,6 +30,12 @@ import logging import warnings from collections import namedtuple, OrderedDict +try: + from enum import EnumType +except ImportError: # pragma: no cover + # nb. python < 3.11 + from enum import EnumMeta as EnumType + import sqlalchemy as sa from sqlalchemy import orm @@ -763,7 +769,7 @@ class Grid: # pylint: disable=too-many-instance-attributes,too-many-public-meth :param key: Name of column. - :param enum: Instance of :class:`python:enum.Enum`. + :param enum: Instance of :class:`python:enum.Enum`, or a dict. """ self.enums[key] = enum self.set_renderer(key, self.render_enum, enum=enum) @@ -2050,7 +2056,7 @@ class Grid: # pylint: disable=too-many-instance-attributes,too-many-public-meth See also :meth:`set_enum()`. :param enum: Enum class for the field. This should be an - instance of :class:`~python:enum.Enum`. + instance of :class:`~python:enum.Enum` or else a dict. To use this feature for your grid:: @@ -2061,12 +2067,26 @@ class Grid: # pylint: disable=too-many-instance-attributes,too-many-public-meth TWO = 2 THREE = 3 - grid.set_enum('my_enum_field', MyEnum) + grid.set_enum("my_enum_field", MyEnum) + + Or, perhaps more common:: + + myenum = { + 1: "ONE", + 2: "TWO", + 3: "THREE", + } + + grid.set_enum("my_enum_field", myenum) """ if enum: - raw_value = obj[key] - if raw_value: - return raw_value.value + + if isinstance(enum, EnumType): + if raw_value := obj[key]: + return raw_value.value + + if isinstance(enum, dict): + return enum.get(value, value) return value diff --git a/tests/grids/test_base.py b/tests/grids/test_base.py index 5174335..4d9872d 100644 --- a/tests/grids/test_base.py +++ b/tests/grids/test_base.py @@ -1602,15 +1602,30 @@ class TestGrid(WebTestCase): grid = self.make_grid(columns=["foo", "bar"]) obj = {"status": None} - # null + # true enum, null value = grid.render_enum(obj, "status", None, enum=enum.UpgradeStatus) self.assertIsNone(value) - # normal + # true enum, normal value obj["status"] = enum.UpgradeStatus.SUCCESS value = grid.render_enum(obj, "status", "SUCCESS", enum=enum.UpgradeStatus) self.assertEqual(value, "success") + # dict enum + statuses = { + enum.UpgradeStatus.SUCCESS.name: "success", + enum.UpgradeStatus.FAILURE.name: "failure", + } + + # dict enum, null + value = grid.render_enum(obj, "status", None, enum=statuses) + self.assertIsNone(value) + + # true enum, normal value + obj["status"] = enum.UpgradeStatus.SUCCESS.value + value = grid.render_enum(obj, "status", "SUCCESS", enum=statuses) + self.assertEqual(value, "success") + def test_render_percent(self): grid = self.make_grid(columns=["foo", "bar"]) obj = MagicMock() From cbfa7f652f317c67bbb93ff965d4f28ff50f82e3 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Fri, 2 Jan 2026 19:19:58 -0600 Subject: [PATCH 2/6] fix: use wutta hint from model, for master view title --- src/wuttaweb/views/master.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/wuttaweb/views/master.py b/src/wuttaweb/views/master.py index 2875f7c..c10914d 100644 --- a/src/wuttaweb/views/master.py +++ b/src/wuttaweb/views/master.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. # @@ -3514,6 +3514,11 @@ class MasterView(View): # pylint: disable=too-many-public-methods if hasattr(cls, "model_title"): return cls.model_title + if model_class := cls.get_model_class(): + if hasattr(model_class, "__wutta_hint__"): + if model_title := model_class.__wutta_hint__.get("model_title"): + return model_title + return cls.get_model_name() @classmethod @@ -3532,6 +3537,13 @@ class MasterView(View): # pylint: disable=too-many-public-methods if hasattr(cls, "model_title_plural"): return cls.model_title_plural + if model_class := cls.get_model_class(): + if hasattr(model_class, "__wutta_hint__"): + if model_title_plural := model_class.__wutta_hint__.get( + "model_title_plural" + ): + return model_title_plural + model_title = cls.get_model_title() return f"{model_title}s" From fa2a90c9cc151413fc504be67bbc5d706f8e2725 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Fri, 2 Jan 2026 19:22:41 -0600 Subject: [PATCH 3/6] fix: show proper batch status text, from enum --- src/wuttaweb/views/batch.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/wuttaweb/views/batch.py b/src/wuttaweb/views/batch.py index ce306ea..0f028cf 100644 --- a/src/wuttaweb/views/batch.py +++ b/src/wuttaweb/views/batch.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. # @@ -32,7 +32,7 @@ import markdown from sqlalchemy import orm from wuttaweb.views import MasterView -from wuttaweb.forms.schema import UserRef +from wuttaweb.forms.schema import UserRef, WuttaDictEnum from wuttaweb.forms.widgets import BatchIdWidget @@ -147,6 +147,9 @@ class BatchMasterView(MasterView): # description g.set_link("description") + # status_code + g.set_enum("status_code", self.model_class.STATUS) + def render_batch_id( # pylint: disable=empty-docstring,unused-argument self, batch, key, value ): @@ -191,6 +194,7 @@ class BatchMasterView(MasterView): if self.creating: f.remove("status_code") else: + f.set_node("status_code", WuttaDictEnum(self.request, batch.STATUS)) f.set_readonly("status_code") # created From 90784cecb2bba64008c9d4c6ad01c81c143409a3 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Fri, 2 Jan 2026 19:23:57 -0600 Subject: [PATCH 4/6] fix: only show "create row" button if batch view supports it --- src/wuttaweb/views/batch.py | 2 +- tests/views/test_batch.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/wuttaweb/views/batch.py b/src/wuttaweb/views/batch.py index 0f028cf..89ffe6f 100644 --- a/src/wuttaweb/views/batch.py +++ b/src/wuttaweb/views/batch.py @@ -445,7 +445,7 @@ class BatchMasterView(MasterView): g.set_renderer("status_code", self.render_row_status) # tool button - create row - if not batch.executed and self.has_perm("create_row"): + if self.rows_creatable and not batch.executed and self.has_perm("create_row"): button = self.make_button( f"New {self.get_row_model_title()}", primary=True, diff --git a/tests/views/test_batch.py b/tests/views/test_batch.py index 92c0a4b..317f731 100644 --- a/tests/views/test_batch.py +++ b/tests/views/test_batch.py @@ -442,6 +442,7 @@ class TestBatchMasterView(WebTestCase): mod.BatchMasterView, model_class=MockBatch, route_prefix="mock_batches", + rows_creatable=True, create=True, ): with patch.object( From 6fd4e15ca24dc0f3e18e91c476822687c5adf447 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Fri, 2 Jan 2026 19:24:38 -0600 Subject: [PATCH 5/6] fix: remove the Users field for create/edit Person --- src/wuttaweb/views/people.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/wuttaweb/views/people.py b/src/wuttaweb/views/people.py index b726772..a4ec254 100644 --- a/src/wuttaweb/views/people.py +++ b/src/wuttaweb/views/people.py @@ -96,7 +96,9 @@ class PersonView(MasterView): # pylint: disable=abstract-method f.remove("full_name") # users - if self.viewing: + if self.creating or self.editing: + f.remove("users") + elif self.viewing: f.set_grid("users", self.make_users_grid(person)) def make_users_grid(self, person): From 9b5b7ad9a78aa10beab117c68764620c10c8d9fe Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Fri, 2 Jan 2026 19:25:33 -0600 Subject: [PATCH 6/6] fix: only show execution panel if batch view supports it e.g. POS batch view should not --- src/wuttaweb/templates/batch/view.mako | 146 +++++++++++++------------ 1 file changed, 74 insertions(+), 72 deletions(-) diff --git a/src/wuttaweb/templates/batch/view.mako b/src/wuttaweb/templates/batch/view.mako index 1305079..0f2c0b9 100644 --- a/src/wuttaweb/templates/batch/view.mako +++ b/src/wuttaweb/templates/batch/view.mako @@ -7,86 +7,88 @@ <%def name="tool_panel_execution()"> - - % if batch.executed: - -

- Batch was executed
- ${app.render_time_ago(batch.executed)}
- by ${batch.executed_by} -

-
- % elif why_not_execute: - -

- Batch cannot be executed: -

-

- ${why_not_execute} -

-
- % else: - % if master.has_perm('execute'): - + % if master.executable: + + % if batch.executed: +

- Batch can be executed + Batch was executed
+ ${app.render_time_ago(batch.executed)}
+ by ${batch.executed_by}

- - Execute Batch - - - - -
- - % else: + % elif why_not_execute:

- Batch may be executed,
- but you do not have permission. + Batch cannot be executed: +

+

+ ${why_not_execute}

+ % else: + % if master.has_perm('execute'): + +

+ Batch can be executed +

+ + Execute Batch + + + + + +
+ + % else: + +

+ Batch may be executed,
+ but you do not have permission. +

+
+ % endif % endif - % endif -
+
+ % endif <%def name="modify_vue_vars()">