From 5c23120795efc76f1108f5204538b183cacac2e6 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 1 Sep 2025 09:46:03 -0500 Subject: [PATCH 01/32] fix: fix 'unnecessary-comprehension' for pylint --- .pylintrc | 1 - src/wuttaweb/forms/schema.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.pylintrc b/.pylintrc index 66b3c38..7915322 100644 --- a/.pylintrc +++ b/.pylintrc @@ -35,4 +35,3 @@ disable=fixme, too-many-statements, ungrouped-imports, unidiomatic-typecheck, - unnecessary-comprehension, diff --git a/src/wuttaweb/forms/schema.py b/src/wuttaweb/forms/schema.py index dc839fb..6f4a608 100644 --- a/src/wuttaweb/forms/schema.py +++ b/src/wuttaweb/forms/schema.py @@ -183,7 +183,7 @@ class WuttaDictEnum(colander.String): def widget_maker(self, **kwargs): # pylint: disable=empty-docstring """ """ if "values" not in kwargs: - kwargs["values"] = [(k, v) for k, v in self.enum_dct.items()] + kwargs["values"] = list(self.enum_dct.items()) return widgets.SelectWidget(**kwargs) From d39f5afd4b4e81e64565ae785226f4a78b0c4f9e Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 1 Sep 2025 09:52:11 -0500 Subject: [PATCH 02/32] fix: fix 'unidiomatic-typecheck' for pylint --- .pylintrc | 1 - src/wuttaweb/forms/base.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.pylintrc b/.pylintrc index 7915322..70735ea 100644 --- a/.pylintrc +++ b/.pylintrc @@ -34,4 +34,3 @@ disable=fixme, too-many-public-methods, too-many-statements, ungrouped-imports, - unidiomatic-typecheck, diff --git a/src/wuttaweb/forms/base.py b/src/wuttaweb/forms/base.py index a4a469a..f4dcd9b 100644 --- a/src/wuttaweb/forms/base.py +++ b/src/wuttaweb/forms/base.py @@ -330,7 +330,7 @@ class Form: # pylint: disable=too-many-instance-attributes self.model_class = model_class self.model_instance = model_instance if self.model_instance and not self.model_class: - if type(self.model_instance) is not dict: + if not isinstance(self.model_instance, dict): self.model_class = type(self.model_instance) self.set_fields(fields or self.get_fields()) From 1fec99bc924b09c35d635dc2c9c63c9a4e8b16ad Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 1 Sep 2025 09:53:33 -0500 Subject: [PATCH 03/32] fix: fix 'too-many-statements' for pylint --- .pylintrc | 2 -- src/wuttaweb/grids/base.py | 4 +++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.pylintrc b/.pylintrc index 70735ea..268f7c9 100644 --- a/.pylintrc +++ b/.pylintrc @@ -32,5 +32,3 @@ disable=fixme, too-many-nested-blocks, too-many-positional-arguments, too-many-public-methods, - too-many-statements, - ungrouped-imports, diff --git a/src/wuttaweb/grids/base.py b/src/wuttaweb/grids/base.py index fb764c9..7886401 100644 --- a/src/wuttaweb/grids/base.py +++ b/src/wuttaweb/grids/base.py @@ -1473,7 +1473,9 @@ class Grid: # pylint: disable=too-many-instance-attributes # configuration methods ############################## - def load_settings(self, persist=True): # pylint: disable=too-many-branches + def load_settings( # pylint: disable=too-many-branches,too-many-statements + self, persist=True + ): """ Load all effective settings for the grid. From 282fc61e50ee14d476180e01878ab106449ab166 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 1 Sep 2025 09:54:48 -0500 Subject: [PATCH 04/32] fix: fix 'too-many-public-methods' for pylint --- .pylintrc | 1 - src/wuttaweb/forms/base.py | 2 +- src/wuttaweb/grids/base.py | 2 +- src/wuttaweb/views/master.py | 2 +- 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.pylintrc b/.pylintrc index 268f7c9..9bdd74c 100644 --- a/.pylintrc +++ b/.pylintrc @@ -31,4 +31,3 @@ disable=fixme, too-many-locals, too-many-nested-blocks, too-many-positional-arguments, - too-many-public-methods, diff --git a/src/wuttaweb/forms/base.py b/src/wuttaweb/forms/base.py index f4dcd9b..020da89 100644 --- a/src/wuttaweb/forms/base.py +++ b/src/wuttaweb/forms/base.py @@ -42,7 +42,7 @@ from wuttaweb.util import FieldList, get_form_data, get_model_fields, make_json_ log = logging.getLogger(__name__) -class Form: # pylint: disable=too-many-instance-attributes +class Form: # pylint: disable=too-many-instance-attributes,too-many-public-methods """ Base class for all forms. diff --git a/src/wuttaweb/grids/base.py b/src/wuttaweb/grids/base.py index 7886401..10e3b4b 100644 --- a/src/wuttaweb/grids/base.py +++ b/src/wuttaweb/grids/base.py @@ -53,7 +53,7 @@ Elements of :attr:`~Grid.sort_defaults` will be of this type. """ -class Grid: # pylint: disable=too-many-instance-attributes +class Grid: # pylint: disable=too-many-instance-attributes,too-many-public-methods """ Base class for all :term:`grids `. diff --git a/src/wuttaweb/views/master.py b/src/wuttaweb/views/master.py index a356534..6f09793 100644 --- a/src/wuttaweb/views/master.py +++ b/src/wuttaweb/views/master.py @@ -44,7 +44,7 @@ from wuttaweb.progress import SessionProgress log = logging.getLogger(__name__) -class MasterView(View): +class MasterView(View): # pylint: disable=too-many-public-methods """ Base class for "master" views. From 0dc6b615e7fbe3c03cccb22f9548ba240376ea72 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 1 Sep 2025 09:58:56 -0500 Subject: [PATCH 05/32] fix: fix 'too-many-arguments' for pylint --- .pylintrc | 2 -- src/wuttaweb/forms/base.py | 2 +- src/wuttaweb/grids/base.py | 6 +++--- src/wuttaweb/grids/filters.py | 2 +- src/wuttaweb/progress.py | 2 +- 5 files changed, 6 insertions(+), 8 deletions(-) diff --git a/.pylintrc b/.pylintrc index 9bdd74c..05598ad 100644 --- a/.pylintrc +++ b/.pylintrc @@ -26,8 +26,6 @@ disable=fixme, singleton-comparison, super-init-not-called, too-few-public-methods, - too-many-arguments, too-many-lines, too-many-locals, too-many-nested-blocks, - too-many-positional-arguments, diff --git a/src/wuttaweb/forms/base.py b/src/wuttaweb/forms/base.py index 020da89..a3c4e5b 100644 --- a/src/wuttaweb/forms/base.py +++ b/src/wuttaweb/forms/base.py @@ -267,7 +267,7 @@ class Form: # pylint: disable=too-many-instance-attributes,too-many-public-meth Note that in all other cases, this attribute may not exist. """ - def __init__( + def __init__( # pylint: disable=too-many-arguments,too-many-positional-arguments self, request, fields=None, diff --git a/src/wuttaweb/grids/base.py b/src/wuttaweb/grids/base.py index 10e3b4b..c5f4aad 100644 --- a/src/wuttaweb/grids/base.py +++ b/src/wuttaweb/grids/base.py @@ -371,7 +371,7 @@ class Grid: # pylint: disable=too-many-instance-attributes,too-many-public-meth See also :meth:`add_tool()` and :meth:`set_tools()`. """ - def __init__( + def __init__( # pylint: disable=too-many-arguments,too-many-positional-arguments self, request, vue_tagname="wutta-grid", @@ -1628,7 +1628,7 @@ class Grid: # pylint: disable=too-many-instance-attributes,too-many-public-meth return False - def get_setting( # pylint: disable=empty-docstring + def get_setting( # pylint: disable=empty-docstring,too-many-arguments,too-many-positional-arguments self, settings, key, src="session", default=None, normalize=lambda v: v ): """ """ @@ -2539,7 +2539,7 @@ class GridAction: # pylint: disable=too-many-instance-attributes Optional HTML class attribute for the action's ```` tag. """ - def __init__( + def __init__( # pylint: disable=too-many-arguments,too-many-positional-arguments self, request, key, diff --git a/src/wuttaweb/grids/filters.py b/src/wuttaweb/grids/filters.py index 331aebc..f939836 100644 --- a/src/wuttaweb/grids/filters.py +++ b/src/wuttaweb/grids/filters.py @@ -169,7 +169,7 @@ class GridFilter: # pylint: disable=too-many-instance-attributes "is_not_null", ] - def __init__( + def __init__( # pylint: disable=too-many-arguments,too-many-positional-arguments self, request, key, diff --git a/src/wuttaweb/progress.py b/src/wuttaweb/progress.py index e041be1..2c41907 100644 --- a/src/wuttaweb/progress.py +++ b/src/wuttaweb/progress.py @@ -91,7 +91,7 @@ class SessionProgress(ProgressBase): # pylint: disable=too-many-instance-attrib :attr:`success_url`. """ - def __init__( + def __init__( # pylint: disable=too-many-arguments,too-many-positional-arguments self, request, key, success_msg=None, success_url=None, error_url=None ): self.request = request From d7eacf0f52972cb061c1eeb1e5cda1959afb0006 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 1 Sep 2025 10:00:06 -0500 Subject: [PATCH 06/32] fix: fix 'too-many-lines' for pylint --- .pylintrc | 1 - src/wuttaweb/forms/base.py | 1 + src/wuttaweb/grids/base.py | 1 + src/wuttaweb/views/master.py | 1 + 4 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.pylintrc b/.pylintrc index 05598ad..7e4cbc6 100644 --- a/.pylintrc +++ b/.pylintrc @@ -26,6 +26,5 @@ disable=fixme, singleton-comparison, super-init-not-called, too-few-public-methods, - too-many-lines, too-many-locals, too-many-nested-blocks, diff --git a/src/wuttaweb/forms/base.py b/src/wuttaweb/forms/base.py index a3c4e5b..95ffc06 100644 --- a/src/wuttaweb/forms/base.py +++ b/src/wuttaweb/forms/base.py @@ -23,6 +23,7 @@ """ Base form classes """ +# pylint: disable=too-many-lines import logging from collections import OrderedDict diff --git a/src/wuttaweb/grids/base.py b/src/wuttaweb/grids/base.py index c5f4aad..5b54511 100644 --- a/src/wuttaweb/grids/base.py +++ b/src/wuttaweb/grids/base.py @@ -23,6 +23,7 @@ """ Base grid classes """ +# pylint: disable=too-many-lines import functools import logging diff --git a/src/wuttaweb/views/master.py b/src/wuttaweb/views/master.py index 6f09793..94c61df 100644 --- a/src/wuttaweb/views/master.py +++ b/src/wuttaweb/views/master.py @@ -23,6 +23,7 @@ """ Base Logic for Master Views """ +# pylint: disable=too-many-lines import logging import os From d01c343a7cc80fa79c2d9e3a69e1a895809f6fe6 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 1 Sep 2025 10:00:54 -0500 Subject: [PATCH 07/32] fix: fix 'too-few-public-methods' for pylint --- .pylintrc | 1 - src/wuttaweb/emails.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.pylintrc b/.pylintrc index 7e4cbc6..27fc1e5 100644 --- a/.pylintrc +++ b/.pylintrc @@ -25,6 +25,5 @@ disable=fixme, simplifiable-if-expression, singleton-comparison, super-init-not-called, - too-few-public-methods, too-many-locals, too-many-nested-blocks, diff --git a/src/wuttaweb/emails.py b/src/wuttaweb/emails.py index eb34bb3..3552352 100644 --- a/src/wuttaweb/emails.py +++ b/src/wuttaweb/emails.py @@ -27,7 +27,7 @@ from wuttjamaican.email import EmailSetting -class feedback(EmailSetting): # pylint: disable=invalid-name +class feedback(EmailSetting): # pylint: disable=invalid-name,too-few-public-methods """ Sent when user submits feedback via the web app. """ From 5a6ed6135ac6886bf3048573ab9d0fb8262df59c Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 1 Sep 2025 10:09:08 -0500 Subject: [PATCH 08/32] fix: fix 'abstract-method' for pylint --- .pylintrc | 1 - src/wuttaweb/forms/schema.py | 2 +- src/wuttaweb/forms/widgets.py | 6 +++--- src/wuttaweb/views/email.py | 2 +- src/wuttaweb/views/people.py | 2 +- src/wuttaweb/views/reports.py | 2 +- src/wuttaweb/views/roles.py | 4 ++-- src/wuttaweb/views/settings.py | 4 ++-- src/wuttaweb/views/upgrades.py | 2 +- src/wuttaweb/views/users.py | 2 +- 10 files changed, 13 insertions(+), 14 deletions(-) diff --git a/.pylintrc b/.pylintrc index 27fc1e5..af61f35 100644 --- a/.pylintrc +++ b/.pylintrc @@ -2,7 +2,6 @@ [MESSAGES CONTROL] disable=fixme, - abstract-method, arguments-differ, arguments-renamed, assignment-from-no-return, diff --git a/src/wuttaweb/forms/schema.py b/src/wuttaweb/forms/schema.py index 6f4a608..fba366b 100644 --- a/src/wuttaweb/forms/schema.py +++ b/src/wuttaweb/forms/schema.py @@ -69,7 +69,7 @@ class WuttaDateTime(colander.DateTime): node.raise_invalid("Invalid date and/or time") -class ObjectNode(colander.SchemaNode): +class ObjectNode(colander.SchemaNode): # pylint: disable=abstract-method """ Custom schema node class which adds methods for compatibility with ColanderAlchemy. This is a direct subclass of diff --git a/src/wuttaweb/forms/widgets.py b/src/wuttaweb/forms/widgets.py index 108572f..f33f0fd 100644 --- a/src/wuttaweb/forms/widgets.py +++ b/src/wuttaweb/forms/widgets.py @@ -299,7 +299,7 @@ class WuttaMoneyInputWidget(MoneyInputWidget): return super().serialize(field, cstruct, **kw) -class FileDownloadWidget(Widget): +class FileDownloadWidget(Widget): # pylint: disable=abstract-method """ Widget for use with :class:`~wuttaweb.forms.schema.FileDownload` fields. @@ -357,7 +357,7 @@ class FileDownloadWidget(Widget): return humanize.naturalsize(size) -class GridWidget(Widget): +class GridWidget(Widget): # pylint: disable=abstract-method """ Widget for fields whose data is represented by a :term:`grid`. @@ -512,7 +512,7 @@ class EmailRecipientsWidget(TextAreaWidget): return ", ".join(values) -class BatchIdWidget(Widget): +class BatchIdWidget(Widget): # pylint: disable=abstract-method """ Widget for use with the :attr:`~wuttjamaican:wuttjamaican.db.model.batch.BatchMixin.id` diff --git a/src/wuttaweb/views/email.py b/src/wuttaweb/views/email.py index a50977f..055084f 100644 --- a/src/wuttaweb/views/email.py +++ b/src/wuttaweb/views/email.py @@ -30,7 +30,7 @@ from wuttaweb.views import MasterView from wuttaweb.forms.schema import EmailRecipients -class EmailSettingView(MasterView): +class EmailSettingView(MasterView): # pylint: disable=abstract-method """ Master view for :term:`email settings `. """ diff --git a/src/wuttaweb/views/people.py b/src/wuttaweb/views/people.py index d8cc189..9038b50 100644 --- a/src/wuttaweb/views/people.py +++ b/src/wuttaweb/views/people.py @@ -30,7 +30,7 @@ from wuttjamaican.db.model import Person from wuttaweb.views import MasterView -class PersonView(MasterView): +class PersonView(MasterView): # pylint: disable=abstract-method """ Master view for people. diff --git a/src/wuttaweb/views/reports.py b/src/wuttaweb/views/reports.py index a79b262..906f5dd 100644 --- a/src/wuttaweb/views/reports.py +++ b/src/wuttaweb/views/reports.py @@ -37,7 +37,7 @@ from wuttaweb.views import MasterView log = logging.getLogger(__name__) -class ReportView(MasterView): +class ReportView(MasterView): # pylint: disable=abstract-method """ Master view for :term:`reports `; route prefix is ``reports``. diff --git a/src/wuttaweb/views/roles.py b/src/wuttaweb/views/roles.py index 62d2dd0..c03e1c4 100644 --- a/src/wuttaweb/views/roles.py +++ b/src/wuttaweb/views/roles.py @@ -31,7 +31,7 @@ from wuttaweb.forms import widgets from wuttaweb.forms.schema import Permissions, RoleRef -class RoleView(MasterView): +class RoleView(MasterView): # pylint: disable=abstract-method """ Master view for roles. @@ -317,7 +317,7 @@ class RoleView(MasterView): ) -class PermissionView(MasterView): +class PermissionView(MasterView): # pylint: disable=abstract-method """ Master view for permissions. diff --git a/src/wuttaweb/views/settings.py b/src/wuttaweb/views/settings.py index 7cfd576..f646865 100644 --- a/src/wuttaweb/views/settings.py +++ b/src/wuttaweb/views/settings.py @@ -35,7 +35,7 @@ from wuttaweb.views import MasterView from wuttaweb.util import get_libver, get_liburl -class AppInfoView(MasterView): +class AppInfoView(MasterView): # pylint: disable=abstract-method """ Master view for the core app info, to show/edit config etc. @@ -220,7 +220,7 @@ class AppInfoView(MasterView): return context -class SettingView(MasterView): +class SettingView(MasterView): # pylint: disable=abstract-method """ Master view for the "raw" settings table. diff --git a/src/wuttaweb/views/upgrades.py b/src/wuttaweb/views/upgrades.py index bc4e29c..99d1148 100644 --- a/src/wuttaweb/views/upgrades.py +++ b/src/wuttaweb/views/upgrades.py @@ -41,7 +41,7 @@ from wuttaweb.progress import get_progress_session log = logging.getLogger(__name__) -class UpgradeView(MasterView): +class UpgradeView(MasterView): # pylint: disable=abstract-method """ Master view for upgrades. diff --git a/src/wuttaweb/views/users.py b/src/wuttaweb/views/users.py index eefc4af..4691a1e 100644 --- a/src/wuttaweb/views/users.py +++ b/src/wuttaweb/views/users.py @@ -30,7 +30,7 @@ from wuttaweb.forms import widgets from wuttaweb.forms.schema import PersonRef, RoleRefs -class UserView(MasterView): +class UserView(MasterView): # pylint: disable=abstract-method """ Master view for users. From 11ec57387ea6a2ff188a645d82087d78baceedf0 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 1 Sep 2025 10:13:07 -0500 Subject: [PATCH 09/32] fix: fix 'assignment-from-no-return' for pylint --- .pylintrc | 1 - src/wuttaweb/views/master.py | 11 +++++++---- tests/views/test_master.py | 5 +++++ 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/.pylintrc b/.pylintrc index af61f35..fc8037d 100644 --- a/.pylintrc +++ b/.pylintrc @@ -4,7 +4,6 @@ disable=fixme, arguments-differ, arguments-renamed, - assignment-from-no-return, attribute-defined-outside-init, consider-using-dict-comprehension, consider-using-dict-items, diff --git a/src/wuttaweb/views/master.py b/src/wuttaweb/views/master.py index 94c61df..be7d7f2 100644 --- a/src/wuttaweb/views/master.py +++ b/src/wuttaweb/views/master.py @@ -918,7 +918,7 @@ class MasterView(View): # pylint: disable=too-many-public-methods if not term: return [] - data = self.autocomplete_data(term) + data = self.autocomplete_data(term) # pylint: disable=assignment-from-none if not data: return [] @@ -932,7 +932,7 @@ class MasterView(View): # pylint: disable=too-many-public-methods return results - def autocomplete_data(self, term): + def autocomplete_data(self, term): # pylint: disable=unused-argument """ Should return the data/query for the "matching" model records, based on autocomplete search term. This is called by @@ -944,6 +944,7 @@ class MasterView(View): # pylint: disable=too-many-public-methods :returns: List of data records, or SQLAlchemy query. """ + return None def autocomplete_normalize(self, obj): """ @@ -1007,13 +1008,13 @@ class MasterView(View): # pylint: disable=too-many-public-methods obj = self.get_instance() filename = self.request.GET.get("filename", None) - path = self.download_path(obj, filename) + path = self.download_path(obj, filename) # pylint: disable=assignment-from-none if not path or not os.path.exists(path): return self.notfound() return self.file_response(path) - def download_path(self, obj, filename): + def download_path(self, obj, filename): # pylint: disable=unused-argument """ Should return absolute path on disk, for the given object and filename. Result will be used to return a file response to @@ -1034,6 +1035,7 @@ class MasterView(View): # pylint: disable=too-many-public-methods the :meth:`download()` view will return a 404 not found response. """ + return None ############################## # execute methods @@ -1305,6 +1307,7 @@ class MasterView(View): # pylint: disable=too-many-public-methods Note that their order does not matter since the template must explicitly define field layout etc. """ + return [] def configure_gather_settings( self, diff --git a/tests/views/test_master.py b/tests/views/test_master.py index 6edc420..cd04f8a 100644 --- a/tests/views/test_master.py +++ b/tests/views/test_master.py @@ -1656,6 +1656,11 @@ class TestMasterView(WebTestCase): count = self.session.query(model.Setting).count() self.assertEqual(count, 0) + def test_configure_get_simple_settings(self): + view = self.make_view() + settings = view.configure_get_simple_settings() + self.assertEqual(settings, []) + def test_configure_gather_settings(self): view = self.make_view() From d6f7c19f71dbba84b15fd28426fe32b8954bd116 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 1 Sep 2025 10:15:23 -0500 Subject: [PATCH 10/32] fix: fix 'consider-using-dict-comprehension' for pylint --- .pylintrc | 1 - src/wuttaweb/grids/filters.py | 2 +- src/wuttaweb/views/batch.py | 12 +++++------- src/wuttaweb/views/master.py | 4 ++-- 4 files changed, 8 insertions(+), 11 deletions(-) diff --git a/.pylintrc b/.pylintrc index fc8037d..4431a80 100644 --- a/.pylintrc +++ b/.pylintrc @@ -5,7 +5,6 @@ disable=fixme, arguments-differ, arguments-renamed, attribute-defined-outside-init, - consider-using-dict-comprehension, consider-using-dict-items, consider-using-generator, consider-using-get, diff --git a/src/wuttaweb/grids/filters.py b/src/wuttaweb/grids/filters.py index f939836..c22b75c 100644 --- a/src/wuttaweb/grids/filters.py +++ b/src/wuttaweb/grids/filters.py @@ -248,7 +248,7 @@ class GridFilter: # pylint: disable=too-many-instance-attributes Returns a dict of all defined verb labels. """ # TODO: should traverse hierarchy - labels = dict([(verb, verb) for verb in self.get_verbs()]) + labels = {verb: verb for verb in self.get_verbs()} labels.update(self.default_verb_labels) return labels diff --git a/src/wuttaweb/views/batch.py b/src/wuttaweb/views/batch.py index 3690a20..036bf88 100644 --- a/src/wuttaweb/views/batch.py +++ b/src/wuttaweb/views/batch.py @@ -235,13 +235,11 @@ class BatchMasterView(MasterView): batch = schema.objectify(form.validated, context=form.model_instance) # then we collect attributes from the new batch - kw = dict( - [ - (key, getattr(batch, key)) - for key in form.validated - if hasattr(batch, key) - ] - ) + kw = { + key: getattr(batch, key) + for key in form.validated + if hasattr(batch, key) + } # and set attribute for user creating the batch kw["created_by"] = self.request.user diff --git a/src/wuttaweb/views/master.py b/src/wuttaweb/views/master.py index be7d7f2..509ba26 100644 --- a/src/wuttaweb/views/master.py +++ b/src/wuttaweb/views/master.py @@ -2248,9 +2248,9 @@ class MasterView(View): # pylint: disable=too-many-public-methods :returns: The dict of route kwargs for the object. """ try: - return dict([(key, obj[key]) for key in self.get_model_key()]) + return {key: obj[key] for key in self.get_model_key()} except TypeError: - return dict([(key, getattr(obj, key)) for key in self.get_model_key()]) + return {key: getattr(obj, key) for key in self.get_model_key()} def get_action_url(self, action, obj, **kwargs): """ From 65849ad82d04105a91e78c38f47eada37d1018f7 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 1 Sep 2025 10:19:54 -0500 Subject: [PATCH 11/32] fix: fix 'consider-using-dict-items' for pylint --- .pylintrc | 1 - src/wuttaweb/grids/base.py | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.pylintrc b/.pylintrc index 4431a80..5e11618 100644 --- a/.pylintrc +++ b/.pylintrc @@ -5,7 +5,6 @@ disable=fixme, arguments-differ, arguments-renamed, attribute-defined-outside-init, - consider-using-dict-items, consider-using-generator, consider-using-get, consider-using-set-comprehension, diff --git a/src/wuttaweb/grids/base.py b/src/wuttaweb/grids/base.py index 5b54511..d280f91 100644 --- a/src/wuttaweb/grids/base.py +++ b/src/wuttaweb/grids/base.py @@ -2389,9 +2389,9 @@ class Grid: # pylint: disable=too-many-instance-attributes,too-many-public-meth record = make_json_safe(record, warn=False) # customize value rendering where applicable - for key in self.renderers: + for key, renderer in self.renderers.items(): value = record.get(key, None) - record[key] = self.renderers[key](original_record, key, value) + record[key] = renderer(original_record, key, value) # add action urls to each record for action in self.actions: From 564ac318bc36127ca3b6cd7799c18ba4aea447d2 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 1 Sep 2025 10:21:32 -0500 Subject: [PATCH 12/32] fix: fix 'consider-using-get' for pylint --- .pylintrc | 1 - src/wuttaweb/grids/base.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.pylintrc b/.pylintrc index 5e11618..ca39510 100644 --- a/.pylintrc +++ b/.pylintrc @@ -6,7 +6,6 @@ disable=fixme, arguments-renamed, attribute-defined-outside-init, consider-using-generator, - consider-using-get, consider-using-set-comprehension, duplicate-code, isinstance-second-argument-not-valid-type, diff --git a/src/wuttaweb/grids/base.py b/src/wuttaweb/grids/base.py index d280f91..fc9a84b 100644 --- a/src/wuttaweb/grids/base.py +++ b/src/wuttaweb/grids/base.py @@ -689,7 +689,7 @@ class Grid: # pylint: disable=too-many-instance-attributes,too-many-public-meth "percent": self.render_percent, } - if renderer in builtins: + if renderer in builtins: # pylint: disable=consider-using-get renderer = builtins[renderer] if kwargs: From ec982fe1689bfcc7a1483a03237f5eb583cd3f9b Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 1 Sep 2025 10:22:29 -0500 Subject: [PATCH 13/32] fix: fix 'consider-using-set-comprehension' for pylint --- .pylintrc | 1 - src/wuttaweb/forms/schema.py | 2 +- src/wuttaweb/views/users.py | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.pylintrc b/.pylintrc index ca39510..4eeeae9 100644 --- a/.pylintrc +++ b/.pylintrc @@ -6,7 +6,6 @@ disable=fixme, arguments-renamed, attribute-defined-outside-init, consider-using-generator, - consider-using-set-comprehension, duplicate-code, isinstance-second-argument-not-valid-type, keyword-arg-before-vararg, diff --git a/src/wuttaweb/forms/schema.py b/src/wuttaweb/forms/schema.py index fba366b..ca62d8a 100644 --- a/src/wuttaweb/forms/schema.py +++ b/src/wuttaweb/forms/schema.py @@ -557,7 +557,7 @@ class RoleRefs(WuttaSet): auth.get_role_authenticated(session), auth.get_role_anonymous(session), } - avoid = set([role.uuid for role in avoid]) + avoid = {role.uuid for role in avoid} # also avoid admin unless current user is root if not self.request.is_root: diff --git a/src/wuttaweb/views/users.py b/src/wuttaweb/views/users.py index 4691a1e..eb5c858 100644 --- a/src/wuttaweb/views/users.py +++ b/src/wuttaweb/views/users.py @@ -233,7 +233,7 @@ class UserView(MasterView): # pylint: disable=abstract-method session = self.Session() auth = self.app.get_auth_handler() - old_roles = set([role.uuid for role in user.roles]) + old_roles = {role.uuid for role in user.roles} new_roles = data["roles"] admin = auth.get_role_administrator(session) From 4b4d81c4f3b38d6cdc7fac0d6dc722f16099aa1b Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 1 Sep 2025 10:24:29 -0500 Subject: [PATCH 14/32] fix: fix 'isinstance-second-argument-not-valid-type' for pylint --- .pylintrc | 1 - src/wuttaweb/forms/schema.py | 4 +++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.pylintrc b/.pylintrc index 4eeeae9..92b465c 100644 --- a/.pylintrc +++ b/.pylintrc @@ -7,7 +7,6 @@ disable=fixme, attribute-defined-outside-init, consider-using-generator, duplicate-code, - isinstance-second-argument-not-valid-type, keyword-arg-before-vararg, missing-function-docstring, missing-module-docstring, diff --git a/src/wuttaweb/forms/schema.py b/src/wuttaweb/forms/schema.py index ca62d8a..271bdd9 100644 --- a/src/wuttaweb/forms/schema.py +++ b/src/wuttaweb/forms/schema.py @@ -381,7 +381,9 @@ class ObjectRef(colander.SchemaType): if not value: return None - if isinstance(value, self.model_class): + if isinstance( # pylint: disable=isinstance-second-argument-not-valid-type + value, self.model_class + ): return value # fetch object from DB From ebd44c55f5d66397535de73ac2bbff6db7c2fd33 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 1 Sep 2025 10:25:21 -0500 Subject: [PATCH 15/32] fix: fix 'no-else-raise' for pylint --- .pylintrc | 1 - src/wuttaweb/grids/base.py | 8 ++++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.pylintrc b/.pylintrc index 92b465c..44744b8 100644 --- a/.pylintrc +++ b/.pylintrc @@ -10,7 +10,6 @@ disable=fixme, keyword-arg-before-vararg, missing-function-docstring, missing-module-docstring, - no-else-raise, no-member, not-callable, protected-access, diff --git a/src/wuttaweb/grids/base.py b/src/wuttaweb/grids/base.py index fc9a84b..387840b 100644 --- a/src/wuttaweb/grids/base.py +++ b/src/wuttaweb/grids/base.py @@ -1373,10 +1373,10 @@ class Grid: # pylint: disable=too-many-instance-attributes,too-many-public-meth if filterinfo and callable(filterinfo): # filtr = filterinfo raise NotImplementedError - else: - kwargs["key"] = key - kwargs.setdefault("label", self.get_label(key)) - filtr = self.make_filter(filterinfo or key, **kwargs) + + kwargs["key"] = key + kwargs.setdefault("label", self.get_label(key)) + filtr = self.make_filter(filterinfo or key, **kwargs) self.filters[key] = filtr From ab35847f23adc80903c26ff508e7e3cfa660f633 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 1 Sep 2025 10:26:33 -0500 Subject: [PATCH 16/32] fix: fix 'not-callable' for pylint --- .pylintrc | 1 - src/wuttaweb/grids/filters.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.pylintrc b/.pylintrc index 44744b8..f45d1ec 100644 --- a/.pylintrc +++ b/.pylintrc @@ -11,7 +11,6 @@ disable=fixme, missing-function-docstring, missing-module-docstring, no-member, - not-callable, protected-access, redefined-outer-name, simplifiable-if-expression, diff --git a/src/wuttaweb/grids/filters.py b/src/wuttaweb/grids/filters.py index c22b75c..e27cd5e 100644 --- a/src/wuttaweb/grids/filters.py +++ b/src/wuttaweb/grids/filters.py @@ -378,7 +378,7 @@ class GridFilter: # pylint: disable=too-many-instance-attributes raise VerbNotSupported(verb) # invoke filter method - return func(data, value) + return func(data, value) # pylint: disable=not-callable def filter_is_any(self, data, value): # pylint: disable=unused-argument """ From e38f7ba2933a3df2d79b63e9d0a916d23736f5bf Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 1 Sep 2025 10:32:22 -0500 Subject: [PATCH 17/32] fix: fix 'protected-access' for pylint --- .pylintrc | 1 - src/wuttaweb/grids/base.py | 4 ++-- src/wuttaweb/subscribers.py | 10 +++++----- .../templates/themes/butterfly/base.mako | 4 ++-- src/wuttaweb/util.py | 4 ++-- tests/test_subscribers.py | 16 ++++++++-------- 6 files changed, 19 insertions(+), 20 deletions(-) diff --git a/.pylintrc b/.pylintrc index f45d1ec..7b7bdee 100644 --- a/.pylintrc +++ b/.pylintrc @@ -11,7 +11,6 @@ disable=fixme, missing-function-docstring, missing-module-docstring, no-member, - protected-access, redefined-outer-name, simplifiable-if-expression, singleton-comparison, diff --git a/src/wuttaweb/grids/base.py b/src/wuttaweb/grids/base.py index 387840b..6565f9c 100644 --- a/src/wuttaweb/grids/base.py +++ b/src/wuttaweb/grids/base.py @@ -1087,8 +1087,8 @@ class Grid: # pylint: disable=too-many-instance-attributes,too-many-public-meth # TODO: this should be improved; is needed in tailbone for # multi-column sorting with sqlalchemy queries if model_property: - sorter._class = model_class - sorter._column = model_property + sorter._class = model_class # pylint: disable=protected-access + sorter._column = model_property # pylint: disable=protected-access return sorter diff --git a/src/wuttaweb/subscribers.py b/src/wuttaweb/subscribers.py index 25ea614..5fbdb14 100644 --- a/src/wuttaweb/subscribers.py +++ b/src/wuttaweb/subscribers.py @@ -159,20 +159,20 @@ def new_request(event): Register a Vue 3 component, so the base template knows to declare it for use within the app (page). """ - if not hasattr(request, "_wuttaweb_registered_components"): - request._wuttaweb_registered_components = OrderedDict() + if not hasattr(request, "wuttaweb_registered_components"): + request.wuttaweb_registered_components = OrderedDict() - if tagname in request._wuttaweb_registered_components: + if tagname in request.wuttaweb_registered_components: log.warning( "component with tagname '%s' already registered " "with class '%s' but we are replacing that " "with class '%s'", tagname, - request._wuttaweb_registered_components[tagname], + request.wuttaweb_registered_components[tagname], classname, ) - request._wuttaweb_registered_components[tagname] = classname + request.wuttaweb_registered_components[tagname] = classname request.register_component = register_component diff --git a/src/wuttaweb/templates/themes/butterfly/base.mako b/src/wuttaweb/templates/themes/butterfly/base.mako index 76e9b5b..944c541 100644 --- a/src/wuttaweb/templates/themes/butterfly/base.mako +++ b/src/wuttaweb/templates/themes/butterfly/base.mako @@ -58,8 +58,8 @@ const app = createApp() app.component('vue-fontawesome', FontAwesomeIcon) - % if hasattr(request, '_wuttaweb_registered_components'): - % for tagname, classname in request._wuttaweb_registered_components.items(): + % if hasattr(request, 'wuttaweb_registered_components'): + % for tagname, classname in request.wuttaweb_registered_components.items(): app.component('${tagname}', ${classname}) % endfor % endif diff --git a/src/wuttaweb/util.py b/src/wuttaweb/util.py index caa41f6..963c848 100644 --- a/src/wuttaweb/util.py +++ b/src/wuttaweb/util.py @@ -757,14 +757,14 @@ def set_app_theme(request, theme, session=None): # there's only one global template lookup; can get to it via any renderer # but should *not* use /base.mako since that one is about to get volatile - renderer = get_renderer("/menu.mako") + renderer = get_renderer("/page.mako") lookup = renderer.lookup # overwrite first entry in lookup's directory list lookup.directories[0] = theme_path # clear template cache for lookup object, so it will reload each (as needed) - lookup._collection.clear() + lookup._collection.clear() # pylint: disable=protected-access # persist current theme in db settings with app.short_session(session=session) as s: diff --git a/tests/test_subscribers.py b/tests/test_subscribers.py index 9fd7729..501e160 100644 --- a/tests/test_subscribers.py +++ b/tests/test_subscribers.py @@ -76,23 +76,23 @@ class TestNewRequest(TestCase): subscribers.new_request(event) # component tracking dict is missing at first - self.assertFalse(hasattr(self.request, "_wuttaweb_registered_components")) + self.assertFalse(hasattr(self.request, "wuttaweb_registered_components")) # registering a component self.request.register_component("foo-example", "FooExample") - self.assertTrue(hasattr(self.request, "_wuttaweb_registered_components")) - self.assertEqual(len(self.request._wuttaweb_registered_components), 1) - self.assertIn("foo-example", self.request._wuttaweb_registered_components) + self.assertTrue(hasattr(self.request, "wuttaweb_registered_components")) + self.assertEqual(len(self.request.wuttaweb_registered_components), 1) + self.assertIn("foo-example", self.request.wuttaweb_registered_components) self.assertEqual( - self.request._wuttaweb_registered_components["foo-example"], "FooExample" + self.request.wuttaweb_registered_components["foo-example"], "FooExample" ) # re-registering same name self.request.register_component("foo-example", "FooExample") - self.assertEqual(len(self.request._wuttaweb_registered_components), 1) - self.assertIn("foo-example", self.request._wuttaweb_registered_components) + self.assertEqual(len(self.request.wuttaweb_registered_components), 1) + self.assertIn("foo-example", self.request.wuttaweb_registered_components) self.assertEqual( - self.request._wuttaweb_registered_components["foo-example"], "FooExample" + self.request.wuttaweb_registered_components["foo-example"], "FooExample" ) def test_get_referrer(self): From 6c66c8d57be3281c16c718372aca0f54bda43502 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 1 Sep 2025 10:37:56 -0500 Subject: [PATCH 18/32] fix: fix 'redefined-outer-name' for pylint --- .pylintrc | 1 - src/wuttaweb/app.py | 6 +++--- src/wuttaweb/views/auth.py | 4 +++- src/wuttaweb/views/common.py | 2 +- src/wuttaweb/views/email.py | 2 +- src/wuttaweb/views/people.py | 2 +- src/wuttaweb/views/progress.py | 4 +++- src/wuttaweb/views/reports.py | 2 +- src/wuttaweb/views/roles.py | 6 ++++-- src/wuttaweb/views/settings.py | 4 ++-- src/wuttaweb/views/upgrades.py | 2 +- src/wuttaweb/views/users.py | 4 +++- 12 files changed, 23 insertions(+), 16 deletions(-) diff --git a/.pylintrc b/.pylintrc index 7b7bdee..4ae2600 100644 --- a/.pylintrc +++ b/.pylintrc @@ -11,7 +11,6 @@ disable=fixme, missing-function-docstring, missing-module-docstring, no-member, - redefined-outer-name, simplifiable-if-expression, singleton-comparison, super-init-not-called, diff --git a/src/wuttaweb/app.py b/src/wuttaweb/app.py index 1593095..38749e0 100644 --- a/src/wuttaweb/app.py +++ b/src/wuttaweb/app.py @@ -239,14 +239,14 @@ def make_wsgi_app(main_app=None, config=None): # determine the app factory if isinstance(main_app, str): - make_wsgi_app = app.load_object(main_app) + factory = app.load_object(main_app) elif callable(main_app): - make_wsgi_app = main_app + factory = main_app else: raise ValueError("main_app must be spec or callable") # construct a pyramid app "per usual" - return make_wsgi_app({}, **settings) + return factory({}, **settings) def make_asgi_app(main_app=None, config=None): diff --git a/src/wuttaweb/views/auth.py b/src/wuttaweb/views/auth.py index c2a52cb..cb82de5 100644 --- a/src/wuttaweb/views/auth.py +++ b/src/wuttaweb/views/auth.py @@ -314,7 +314,9 @@ class AuthView(View): def defaults(config, **kwargs): base = globals() - AuthView = kwargs.get("AuthView", base["AuthView"]) # pylint: disable=invalid-name + AuthView = kwargs.get( # pylint: disable=invalid-name,redefined-outer-name + "AuthView", base["AuthView"] + ) AuthView.defaults(config) diff --git a/src/wuttaweb/views/common.py b/src/wuttaweb/views/common.py index 71ef57e..5359184 100644 --- a/src/wuttaweb/views/common.py +++ b/src/wuttaweb/views/common.py @@ -345,7 +345,7 @@ class CommonView(View): def defaults(config, **kwargs): base = globals() - CommonView = kwargs.get( # pylint: disable=invalid-name + CommonView = kwargs.get( # pylint: disable=invalid-name,redefined-outer-name "CommonView", base["CommonView"] ) CommonView.defaults(config) diff --git a/src/wuttaweb/views/email.py b/src/wuttaweb/views/email.py index 055084f..4e56b0e 100644 --- a/src/wuttaweb/views/email.py +++ b/src/wuttaweb/views/email.py @@ -303,7 +303,7 @@ class EmailSettingView(MasterView): # pylint: disable=abstract-method def defaults(config, **kwargs): base = globals() - EmailSettingView = kwargs.get( # pylint: disable=invalid-name + EmailSettingView = kwargs.get( # pylint: disable=invalid-name,redefined-outer-name "EmailSettingView", base["EmailSettingView"] ) EmailSettingView.defaults(config) diff --git a/src/wuttaweb/views/people.py b/src/wuttaweb/views/people.py index 9038b50..1f329ea 100644 --- a/src/wuttaweb/views/people.py +++ b/src/wuttaweb/views/people.py @@ -216,7 +216,7 @@ class PersonView(MasterView): # pylint: disable=abstract-method def defaults(config, **kwargs): base = globals() - PersonView = kwargs.get( # pylint: disable=invalid-name + PersonView = kwargs.get( # pylint: disable=invalid-name,redefined-outer-name "PersonView", base["PersonView"] ) PersonView.defaults(config) diff --git a/src/wuttaweb/views/progress.py b/src/wuttaweb/views/progress.py index 06aa456..889a9d5 100644 --- a/src/wuttaweb/views/progress.py +++ b/src/wuttaweb/views/progress.py @@ -66,7 +66,9 @@ def progress(request): def defaults(config, **kwargs): base = globals() - progress = kwargs.get("progress", base["progress"]) + progress = kwargs.get( # pylint: disable=redefined-outer-name + "progress", base["progress"] + ) config.add_route("progress", "/progress/{key}") config.add_view(progress, route_name="progress", renderer="json") diff --git a/src/wuttaweb/views/reports.py b/src/wuttaweb/views/reports.py index 906f5dd..ffc4952 100644 --- a/src/wuttaweb/views/reports.py +++ b/src/wuttaweb/views/reports.py @@ -264,7 +264,7 @@ class ReportView(MasterView): # pylint: disable=abstract-method def defaults(config, **kwargs): base = globals() - ReportView = kwargs.get( # pylint: disable=invalid-name + ReportView = kwargs.get( # pylint: disable=invalid-name,redefined-outer-name "ReportView", base["ReportView"] ) ReportView.defaults(config) diff --git a/src/wuttaweb/views/roles.py b/src/wuttaweb/views/roles.py index c03e1c4..3c30d7f 100644 --- a/src/wuttaweb/views/roles.py +++ b/src/wuttaweb/views/roles.py @@ -380,10 +380,12 @@ class PermissionView(MasterView): # pylint: disable=abstract-method def defaults(config, **kwargs): base = globals() - RoleView = kwargs.get("RoleView", base["RoleView"]) # pylint: disable=invalid-name + RoleView = kwargs.get( # pylint: disable=invalid-name,redefined-outer-name + "RoleView", base["RoleView"] + ) RoleView.defaults(config) - PermissionView = kwargs.get( # pylint: disable=invalid-name + PermissionView = kwargs.get( # pylint: disable=invalid-name,redefined-outer-name "PermissionView", base["PermissionView"] ) PermissionView.defaults(config) diff --git a/src/wuttaweb/views/settings.py b/src/wuttaweb/views/settings.py index f646865..792935d 100644 --- a/src/wuttaweb/views/settings.py +++ b/src/wuttaweb/views/settings.py @@ -278,12 +278,12 @@ class SettingView(MasterView): # pylint: disable=abstract-method def defaults(config, **kwargs): base = globals() - AppInfoView = kwargs.get( # pylint: disable=invalid-name + AppInfoView = kwargs.get( # pylint: disable=invalid-name,redefined-outer-name "AppInfoView", base["AppInfoView"] ) AppInfoView.defaults(config) - SettingView = kwargs.get( # pylint: disable=invalid-name + SettingView = kwargs.get( # pylint: disable=invalid-name,redefined-outer-name "SettingView", base["SettingView"] ) SettingView.defaults(config) diff --git a/src/wuttaweb/views/upgrades.py b/src/wuttaweb/views/upgrades.py index 99d1148..052e6c4 100644 --- a/src/wuttaweb/views/upgrades.py +++ b/src/wuttaweb/views/upgrades.py @@ -380,7 +380,7 @@ class UpgradeView(MasterView): # pylint: disable=abstract-method def defaults(config, **kwargs): base = globals() - UpgradeView = kwargs.get( # pylint: disable=invalid-name + UpgradeView = kwargs.get( # pylint: disable=invalid-name,redefined-outer-name "UpgradeView", base["UpgradeView"] ) UpgradeView.defaults(config) diff --git a/src/wuttaweb/views/users.py b/src/wuttaweb/views/users.py index eb5c858..9982b3e 100644 --- a/src/wuttaweb/views/users.py +++ b/src/wuttaweb/views/users.py @@ -420,7 +420,9 @@ class UserView(MasterView): # pylint: disable=abstract-method def defaults(config, **kwargs): base = globals() - UserView = kwargs.get("UserView", base["UserView"]) # pylint: disable=invalid-name + UserView = kwargs.get( # pylint: disable=invalid-name,redefined-outer-name + "UserView", base["UserView"] + ) UserView.defaults(config) From 48494ee5e438527ae83ab996f126329cf1b6df5b Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 1 Sep 2025 10:39:30 -0500 Subject: [PATCH 19/32] fix: fix 'simplifiable-if-expression' for pylint --- .pylintrc | 1 - src/wuttaweb/forms/base.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.pylintrc b/.pylintrc index 4ae2600..f457ac5 100644 --- a/.pylintrc +++ b/.pylintrc @@ -11,7 +11,6 @@ disable=fixme, missing-function-docstring, missing-module-docstring, no-member, - simplifiable-if-expression, singleton-comparison, super-init-not-called, too-many-locals, diff --git a/src/wuttaweb/forms/base.py b/src/wuttaweb/forms/base.py index 95ffc06..e0d1282 100644 --- a/src/wuttaweb/forms/base.py +++ b/src/wuttaweb/forms/base.py @@ -1125,7 +1125,7 @@ class Form: # pylint: disable=too-many-instance-attributes,too-many-public-meth # for now we explicitly translate here, ugh. also # note this does not yet allow for null values.. :( if isinstance(field.typ, colander.Boolean): - value = True if value == field.typ.true_val else False + value = value == field.typ.true_val model_data[field.oid] = make_json_safe(value) From 2bcdeb42cddc41c7e713982ac20f532260e798f5 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 1 Sep 2025 10:46:35 -0500 Subject: [PATCH 20/32] fix: fix 'singleton-comparison' for pylint --- .pylintrc | 1 - src/wuttaweb/grids/filters.py | 30 +++++++++++++++++++++++------- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/.pylintrc b/.pylintrc index f457ac5..0c30195 100644 --- a/.pylintrc +++ b/.pylintrc @@ -11,7 +11,6 @@ disable=fixme, missing-function-docstring, missing-module-docstring, no-member, - singleton-comparison, super-init-not-called, too-many-locals, too-many-nested-blocks, diff --git a/src/wuttaweb/grids/filters.py b/src/wuttaweb/grids/filters.py index e27cd5e..984952a 100644 --- a/src/wuttaweb/grids/filters.py +++ b/src/wuttaweb/grids/filters.py @@ -446,7 +446,7 @@ class AlchemyFilter(GridFilter): # probably does not expect that, so explicitly include them. return query.filter( sa.or_( - self.model_property == None, + self.model_property == None, # pylint: disable=singleton-comparison self.model_property != value, ) ) @@ -491,14 +491,18 @@ class AlchemyFilter(GridFilter): """ Filter data with an ``IS NULL`` query. The value is ignored. """ - return query.filter(self.model_property == None) + return query.filter( + self.model_property == None # pylint: disable=singleton-comparison + ) def filter_is_not_null(self, query, value): # pylint: disable=unused-argument """ Filter data with an ``IS NOT NULL`` query. The value is ignored. """ - return query.filter(self.model_property != None) + return query.filter( + self.model_property != None # pylint: disable=singleton-comparison + ) class StringAlchemyFilter(AlchemyFilter): @@ -550,7 +554,12 @@ class StringAlchemyFilter(AlchemyFilter): # sql probably excludes null values from results, but user # probably does not expect that, so explicitly include them. - return query.filter(sa.or_(self.model_property == None, sa.and_(*criteria))) + return query.filter( + sa.or_( + self.model_property == None, # pylint: disable=singleton-comparison + sa.and_(*criteria), + ) + ) class NumericAlchemyFilter(AlchemyFilter): @@ -628,14 +637,18 @@ class BooleanAlchemyFilter(AlchemyFilter): Filter data with an "is true" condition. The value is ignored. """ - return query.filter(self.model_property == True) + return query.filter( + self.model_property == True # pylint: disable=singleton-comparison + ) def filter_is_false(self, query, value): # pylint: disable=unused-argument """ Filter data with an "is false" condition. The value is ignored. """ - return query.filter(self.model_property == False) + return query.filter( + self.model_property == False # pylint: disable=singleton-comparison + ) def filter_is_false_null(self, query, value): # pylint: disable=unused-argument """ @@ -643,7 +656,10 @@ class BooleanAlchemyFilter(AlchemyFilter): ignored. """ return query.filter( - sa.or_(self.model_property == False, self.model_property == None) + sa.or_( + self.model_property == False, # pylint: disable=singleton-comparison + self.model_property == None, # pylint: disable=singleton-comparison + ) ) From 2624f9dce8a842069e2ab339c055dd208956007b Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 1 Sep 2025 10:48:29 -0500 Subject: [PATCH 21/32] fix: fix 'super-init-not-called' for pylint --- .pylintrc | 1 - src/wuttaweb/progress.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.pylintrc b/.pylintrc index 0c30195..0e698d1 100644 --- a/.pylintrc +++ b/.pylintrc @@ -11,6 +11,5 @@ disable=fixme, missing-function-docstring, missing-module-docstring, no-member, - super-init-not-called, too-many-locals, too-many-nested-blocks, diff --git a/src/wuttaweb/progress.py b/src/wuttaweb/progress.py index 2c41907..d09a057 100644 --- a/src/wuttaweb/progress.py +++ b/src/wuttaweb/progress.py @@ -91,7 +91,7 @@ class SessionProgress(ProgressBase): # pylint: disable=too-many-instance-attrib :attr:`success_url`. """ - def __init__( # pylint: disable=too-many-arguments,too-many-positional-arguments + def __init__( # pylint: disable=too-many-arguments,too-many-positional-arguments,super-init-not-called self, request, key, success_msg=None, success_url=None, error_url=None ): self.request = request From 07e90229ce554b6b0729a64f8b82653beb2dcfd8 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 1 Sep 2025 10:59:58 -0500 Subject: [PATCH 22/32] fix: fix 'missing-function-docstring' and 'missing-module-docstring' for pylint --- .pylintrc | 2 -- src/wuttaweb/_version.py | 3 +++ src/wuttaweb/auth.py | 20 ++++++++++++++------ src/wuttaweb/static/__init__.py | 4 ++-- src/wuttaweb/subscribers.py | 2 +- src/wuttaweb/testing.py | 14 ++++++++++++-- src/wuttaweb/views/__init__.py | 4 ++-- src/wuttaweb/views/auth.py | 20 ++++++++++++++------ src/wuttaweb/views/common.py | 7 ++++--- src/wuttaweb/views/email.py | 4 ++-- src/wuttaweb/views/essential.py | 6 +++--- src/wuttaweb/views/people.py | 4 ++-- src/wuttaweb/views/progress.py | 6 +++--- src/wuttaweb/views/reports.py | 4 ++-- src/wuttaweb/views/roles.py | 4 ++-- src/wuttaweb/views/settings.py | 4 ++-- src/wuttaweb/views/upgrades.py | 4 ++-- src/wuttaweb/views/users.py | 4 ++-- 18 files changed, 72 insertions(+), 44 deletions(-) diff --git a/.pylintrc b/.pylintrc index 0e698d1..222c312 100644 --- a/.pylintrc +++ b/.pylintrc @@ -8,8 +8,6 @@ disable=fixme, consider-using-generator, duplicate-code, keyword-arg-before-vararg, - missing-function-docstring, - missing-module-docstring, no-member, too-many-locals, too-many-nested-blocks, diff --git a/src/wuttaweb/_version.py b/src/wuttaweb/_version.py index 8423504..0b9e2e5 100644 --- a/src/wuttaweb/_version.py +++ b/src/wuttaweb/_version.py @@ -1,4 +1,7 @@ # -*- coding: utf-8; -*- +""" +Package Version +""" from importlib.metadata import version diff --git a/src/wuttaweb/auth.py b/src/wuttaweb/auth.py index e6222c0..26370ba 100644 --- a/src/wuttaweb/auth.py +++ b/src/wuttaweb/auth.py @@ -105,7 +105,8 @@ class WuttaSecurityPolicy: self.identity_cache = RequestLocalCache(self.load_identity) self.db_session = db_session or Session() - def load_identity(self, request): + def load_identity(self, request): # pylint: disable=empty-docstring + """ """ config = request.registry.settings["wutta_config"] app = config.get_app() model = app.model @@ -122,22 +123,29 @@ class WuttaSecurityPolicy: return user - def identity(self, request): + def identity(self, request): # pylint: disable=empty-docstring + """ """ return self.identity_cache.get_or_create(request) - def authenticated_userid(self, request): + def authenticated_userid(self, request): # pylint: disable=empty-docstring + """ """ user = self.identity(request) if user is not None: return user.uuid return None - def remember(self, request, userid, **kw): + def remember(self, request, userid, **kw): # pylint: disable=empty-docstring + """ """ return self.session_helper.remember(request, userid, **kw) - def forget(self, request, **kw): + def forget(self, request, **kw): # pylint: disable=empty-docstring + """ """ return self.session_helper.forget(request, **kw) - def permits(self, request, context, permission): # pylint: disable=unused-argument + def permits( # pylint: disable=unused-argument,empty-docstring + self, request, context, permission + ): + """ """ # nb. root user can do anything if getattr(request, "is_root", False): diff --git a/src/wuttaweb/static/__init__.py b/src/wuttaweb/static/__init__.py index 8dcfdf5..95166ca 100644 --- a/src/wuttaweb/static/__init__.py +++ b/src/wuttaweb/static/__init__.py @@ -2,7 +2,7 @@ ################################################################################ # # wuttaweb -- Web App for Wutta Framework -# Copyright © 2024 Lance Edgar +# Copyright © 2024-2025 Lance Edgar # # This file is part of Wutta Framework. # @@ -70,5 +70,5 @@ testing = Resource(img, "testing.png", renderer=True) # TODO: should consider deprecating this? -def includeme(config): +def includeme(config): # pylint: disable=missing-function-docstring config.add_static_view("wuttaweb", "wuttaweb:static") diff --git a/src/wuttaweb/subscribers.py b/src/wuttaweb/subscribers.py index 5fbdb14..5dba500 100644 --- a/src/wuttaweb/subscribers.py +++ b/src/wuttaweb/subscribers.py @@ -411,7 +411,7 @@ def before_render(event): context["available_themes"] = get_available_themes(config) -def includeme(config): +def includeme(config): # pylint: disable=missing-function-docstring config.add_subscriber(new_request, "pyramid.events.NewRequest") config.add_subscriber(new_request_set_user, "pyramid.events.NewRequest") config.add_subscriber(before_render, "pyramid.events.BeforeRender") diff --git a/src/wuttaweb/testing.py b/src/wuttaweb/testing.py index d6f6767..ab13273 100644 --- a/src/wuttaweb/testing.py +++ b/src/wuttaweb/testing.py @@ -2,7 +2,7 @@ ################################################################################ # # wuttaweb -- Web App for Wutta Framework -# Copyright © 2024 Lance Edgar +# Copyright © 2024-2025 Lance Edgar # # This file is part of Wutta Framework. # @@ -39,10 +39,14 @@ class WebTestCase(DataTestCase): Base class for test suites requiring a full (typical) web app. """ - def setUp(self): + def setUp(self): # pylint: disable=empty-docstring + """ """ self.setup_web() def setup_web(self): + """ + Perform setup for the testing web app. + """ self.setup_db() self.request = self.make_request() self.pyramid_config = testing.setUp( @@ -87,8 +91,14 @@ class WebTestCase(DataTestCase): self.teardown_web() def teardown_web(self): + """ + Perform teardown for the testing web app. + """ testing.tearDown() self.teardown_db() def make_request(self): + """ + Make and return a new dummy request object. + """ return testing.DummyRequest() diff --git a/src/wuttaweb/views/__init__.py b/src/wuttaweb/views/__init__.py index 6b59940..16b6be9 100644 --- a/src/wuttaweb/views/__init__.py +++ b/src/wuttaweb/views/__init__.py @@ -2,7 +2,7 @@ ################################################################################ # # wuttaweb -- Web App for Wutta Framework -# Copyright © 2024 Lance Edgar +# Copyright © 2024-2025 Lance Edgar # # This file is part of Wutta Framework. # @@ -34,5 +34,5 @@ from .base import View from .master import MasterView -def includeme(config): +def includeme(config): # pylint: disable=missing-function-docstring config.include("wuttaweb.views.essential") diff --git a/src/wuttaweb/views/auth.py b/src/wuttaweb/views/auth.py index cb82de5..f7b1d0e 100644 --- a/src/wuttaweb/views/auth.py +++ b/src/wuttaweb/views/auth.py @@ -95,7 +95,8 @@ class AuthView(View): # 'referrer': referrer, } - def login_make_schema(self): + def login_make_schema(self): # pylint: disable=empty-docstring + """ """ schema = colander.Schema() # nb. we must explicitly declare the widgets in order to also @@ -220,13 +221,19 @@ class AuthView(View): return schema - def change_password_validate_current_password(self, node, value): + def change_password_validate_current_password( # pylint: disable=empty-docstring + self, node, value + ): + """ """ auth = self.app.get_auth_handler() user = self.request.user if not auth.check_user_password(user, value): node.raise_invalid("Current password is incorrect.") - def change_password_validate_new_password(self, node, value): + def change_password_validate_new_password( # pylint: disable=empty-docstring + self, node, value + ): + """ """ auth = self.app.get_auth_handler() user = self.request.user if auth.check_user_password(user, value): @@ -277,7 +284,8 @@ class AuthView(View): return self.redirect(url) @classmethod - def defaults(cls, config): + def defaults(cls, config): # pylint: disable=empty-docstring + """ """ cls._auth_defaults(config) @classmethod @@ -311,7 +319,7 @@ class AuthView(View): config.add_view(cls, attr="stop_root", route_name="stop_root") -def defaults(config, **kwargs): +def defaults(config, **kwargs): # pylint: disable=missing-function-docstring base = globals() AuthView = kwargs.get( # pylint: disable=invalid-name,redefined-outer-name @@ -320,5 +328,5 @@ def defaults(config, **kwargs): AuthView.defaults(config) -def includeme(config): +def includeme(config): # pylint: disable=missing-function-docstring defaults(config) diff --git a/src/wuttaweb/views/common.py b/src/wuttaweb/views/common.py index 5359184..5992c55 100644 --- a/src/wuttaweb/views/common.py +++ b/src/wuttaweb/views/common.py @@ -294,7 +294,8 @@ class CommonView(View): return self.redirect(referrer) @classmethod - def defaults(cls, config): + def defaults(cls, config): # pylint: disable=empty-docstring + """ """ cls._defaults(config) @classmethod @@ -342,7 +343,7 @@ class CommonView(View): ) -def defaults(config, **kwargs): +def defaults(config, **kwargs): # pylint: disable=missing-function-docstring base = globals() CommonView = kwargs.get( # pylint: disable=invalid-name,redefined-outer-name @@ -351,5 +352,5 @@ def defaults(config, **kwargs): CommonView.defaults(config) -def includeme(config): +def includeme(config): # pylint: disable=missing-function-docstring defaults(config) diff --git a/src/wuttaweb/views/email.py b/src/wuttaweb/views/email.py index 4e56b0e..18526f5 100644 --- a/src/wuttaweb/views/email.py +++ b/src/wuttaweb/views/email.py @@ -300,7 +300,7 @@ class EmailSettingView(MasterView): # pylint: disable=abstract-method ) -def defaults(config, **kwargs): +def defaults(config, **kwargs): # pylint: disable=missing-function-docstring base = globals() EmailSettingView = kwargs.get( # pylint: disable=invalid-name,redefined-outer-name @@ -309,5 +309,5 @@ def defaults(config, **kwargs): EmailSettingView.defaults(config) -def includeme(config): +def includeme(config): # pylint: disable=missing-function-docstring defaults(config) diff --git a/src/wuttaweb/views/essential.py b/src/wuttaweb/views/essential.py index b46a658..e8eac32 100644 --- a/src/wuttaweb/views/essential.py +++ b/src/wuttaweb/views/essential.py @@ -2,7 +2,7 @@ ################################################################################ # # wuttaweb -- Web App for Wutta Framework -# Copyright © 2024 Lance Edgar +# Copyright © 2024-2025 Lance Edgar # # This file is part of Wutta Framework. # @@ -41,7 +41,7 @@ That will in turn include the following modules: """ -def defaults(config, **kwargs): +def defaults(config, **kwargs): # pylint: disable=missing-function-docstring def mod(spec): return kwargs.get(spec, spec) @@ -57,5 +57,5 @@ def defaults(config, **kwargs): config.include(mod("wuttaweb.views.upgrades")) -def includeme(config): +def includeme(config): # pylint: disable=missing-function-docstring defaults(config) diff --git a/src/wuttaweb/views/people.py b/src/wuttaweb/views/people.py index 1f329ea..bd75f90 100644 --- a/src/wuttaweb/views/people.py +++ b/src/wuttaweb/views/people.py @@ -213,7 +213,7 @@ class PersonView(MasterView): # pylint: disable=abstract-method ) -def defaults(config, **kwargs): +def defaults(config, **kwargs): # pylint: disable=missing-function-docstring base = globals() PersonView = kwargs.get( # pylint: disable=invalid-name,redefined-outer-name @@ -222,5 +222,5 @@ def defaults(config, **kwargs): PersonView.defaults(config) -def includeme(config): +def includeme(config): # pylint: disable=missing-function-docstring defaults(config) diff --git a/src/wuttaweb/views/progress.py b/src/wuttaweb/views/progress.py index 889a9d5..fb419ec 100644 --- a/src/wuttaweb/views/progress.py +++ b/src/wuttaweb/views/progress.py @@ -2,7 +2,7 @@ ################################################################################ # # wuttaweb -- Web App for Wutta Framework -# Copyright © 2024 Lance Edgar +# Copyright © 2024-2025 Lance Edgar # # This file is part of Wutta Framework. # @@ -63,7 +63,7 @@ def progress(request): return session -def defaults(config, **kwargs): +def defaults(config, **kwargs): # pylint: disable=missing-function-docstring base = globals() progress = kwargs.get( # pylint: disable=redefined-outer-name @@ -73,5 +73,5 @@ def defaults(config, **kwargs): config.add_view(progress, route_name="progress", renderer="json") -def includeme(config): +def includeme(config): # pylint: disable=missing-function-docstring defaults(config) diff --git a/src/wuttaweb/views/reports.py b/src/wuttaweb/views/reports.py index ffc4952..f81e47d 100644 --- a/src/wuttaweb/views/reports.py +++ b/src/wuttaweb/views/reports.py @@ -261,7 +261,7 @@ class ReportView(MasterView): # pylint: disable=abstract-method ) -def defaults(config, **kwargs): +def defaults(config, **kwargs): # pylint: disable=missing-function-docstring base = globals() ReportView = kwargs.get( # pylint: disable=invalid-name,redefined-outer-name @@ -270,5 +270,5 @@ def defaults(config, **kwargs): ReportView.defaults(config) -def includeme(config): +def includeme(config): # pylint: disable=missing-function-docstring defaults(config) diff --git a/src/wuttaweb/views/roles.py b/src/wuttaweb/views/roles.py index 3c30d7f..abce1d6 100644 --- a/src/wuttaweb/views/roles.py +++ b/src/wuttaweb/views/roles.py @@ -377,7 +377,7 @@ class PermissionView(MasterView): # pylint: disable=abstract-method f.set_node("role", RoleRef(self.request)) -def defaults(config, **kwargs): +def defaults(config, **kwargs): # pylint: disable=missing-function-docstring base = globals() RoleView = kwargs.get( # pylint: disable=invalid-name,redefined-outer-name @@ -391,5 +391,5 @@ def defaults(config, **kwargs): PermissionView.defaults(config) -def includeme(config): +def includeme(config): # pylint: disable=missing-function-docstring defaults(config) diff --git a/src/wuttaweb/views/settings.py b/src/wuttaweb/views/settings.py index 792935d..a35e4a9 100644 --- a/src/wuttaweb/views/settings.py +++ b/src/wuttaweb/views/settings.py @@ -275,7 +275,7 @@ class SettingView(MasterView): # pylint: disable=abstract-method node.raise_invalid("Setting name must be unique") -def defaults(config, **kwargs): +def defaults(config, **kwargs): # pylint: disable=missing-function-docstring base = globals() AppInfoView = kwargs.get( # pylint: disable=invalid-name,redefined-outer-name @@ -289,5 +289,5 @@ def defaults(config, **kwargs): SettingView.defaults(config) -def includeme(config): +def includeme(config): # pylint: disable=missing-function-docstring defaults(config) diff --git a/src/wuttaweb/views/upgrades.py b/src/wuttaweb/views/upgrades.py index 052e6c4..181e7a7 100644 --- a/src/wuttaweb/views/upgrades.py +++ b/src/wuttaweb/views/upgrades.py @@ -377,7 +377,7 @@ class UpgradeView(MasterView): # pylint: disable=abstract-method ) -def defaults(config, **kwargs): +def defaults(config, **kwargs): # pylint: disable=missing-function-docstring base = globals() UpgradeView = kwargs.get( # pylint: disable=invalid-name,redefined-outer-name @@ -386,5 +386,5 @@ def defaults(config, **kwargs): UpgradeView.defaults(config) -def includeme(config): +def includeme(config): # pylint: disable=missing-function-docstring defaults(config) diff --git a/src/wuttaweb/views/users.py b/src/wuttaweb/views/users.py index 9982b3e..2644b21 100644 --- a/src/wuttaweb/views/users.py +++ b/src/wuttaweb/views/users.py @@ -417,7 +417,7 @@ class UserView(MasterView): # pylint: disable=abstract-method ) -def defaults(config, **kwargs): +def defaults(config, **kwargs): # pylint: disable=missing-function-docstring base = globals() UserView = kwargs.get( # pylint: disable=invalid-name,redefined-outer-name @@ -426,5 +426,5 @@ def defaults(config, **kwargs): UserView.defaults(config) -def includeme(config): +def includeme(config): # pylint: disable=missing-function-docstring defaults(config) From 95aeb878991fb2a107ec0c94b8ed3538965a8c37 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 1 Sep 2025 11:01:26 -0500 Subject: [PATCH 23/32] fix: fix 'consider-using-generator' for pylint --- .pylintrc | 1 - src/wuttaweb/views/master.py | 8 +++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/.pylintrc b/.pylintrc index 222c312..bd36f4a 100644 --- a/.pylintrc +++ b/.pylintrc @@ -5,7 +5,6 @@ disable=fixme, arguments-differ, arguments-renamed, attribute-defined-outside-init, - consider-using-generator, duplicate-code, keyword-arg-before-vararg, no-member, diff --git a/src/wuttaweb/views/master.py b/src/wuttaweb/views/master.py index 509ba26..b6347bb 100644 --- a/src/wuttaweb/views/master.py +++ b/src/wuttaweb/views/master.py @@ -2812,11 +2812,9 @@ class MasterView(View): # pylint: disable=too-many-public-methods inspector = sa.inspect(model_class) keys = [col.name for col in inspector.primary_key] return tuple( - [ - prop.key - for prop in inspector.column_attrs - if all(col.name in keys for col in prop.columns) - ] + prop.key + for prop in inspector.column_attrs + if all(col.name in keys for col in prop.columns) ) raise AttributeError(f"you must define model_key for view class: {cls}") From 1dd184622fc87f4849cd67e7a6776832a6658d15 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 1 Sep 2025 11:03:10 -0500 Subject: [PATCH 24/32] fix: fix 'too-many-locals' for pylint --- .pylintrc | 1 - src/wuttaweb/forms/base.py | 4 ++-- src/wuttaweb/grids/base.py | 2 +- src/wuttaweb/views/common.py | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.pylintrc b/.pylintrc index bd36f4a..c42bc1d 100644 --- a/.pylintrc +++ b/.pylintrc @@ -8,5 +8,4 @@ disable=fixme, duplicate-code, keyword-arg-before-vararg, no-member, - too-many-locals, too-many-nested-blocks, diff --git a/src/wuttaweb/forms/base.py b/src/wuttaweb/forms/base.py index e0d1282..d57fe73 100644 --- a/src/wuttaweb/forms/base.py +++ b/src/wuttaweb/forms/base.py @@ -268,7 +268,7 @@ class Form: # pylint: disable=too-many-instance-attributes,too-many-public-meth Note that in all other cases, this attribute may not exist. """ - def __init__( # pylint: disable=too-many-arguments,too-many-positional-arguments + def __init__( # pylint: disable=too-many-arguments,too-many-positional-arguments,too-many-locals self, request, fields=None, @@ -983,7 +983,7 @@ class Form: # pylint: disable=too-many-instance-attributes,too-many-public-meth output = render(template, context) return HTML.literal(output) - def render_vue_field( # pylint: disable=unused-argument + def render_vue_field( # pylint: disable=unused-argument,too-many-locals self, fieldname, readonly=None, diff --git a/src/wuttaweb/grids/base.py b/src/wuttaweb/grids/base.py index 6565f9c..074aa79 100644 --- a/src/wuttaweb/grids/base.py +++ b/src/wuttaweb/grids/base.py @@ -372,7 +372,7 @@ class Grid: # pylint: disable=too-many-instance-attributes,too-many-public-meth See also :meth:`add_tool()` and :meth:`set_tools()`. """ - def __init__( # pylint: disable=too-many-arguments,too-many-positional-arguments + def __init__( # pylint: disable=too-many-arguments,too-many-positional-arguments,too-many-locals self, request, vue_tagname="wutta-grid", diff --git a/src/wuttaweb/views/common.py b/src/wuttaweb/views/common.py index 5992c55..74c6858 100644 --- a/src/wuttaweb/views/common.py +++ b/src/wuttaweb/views/common.py @@ -135,7 +135,7 @@ class CommonView(View): """ """ self.app.send_email("feedback", context) - def setup(self, session=None): + def setup(self, session=None): # pylint: disable=too-many-locals """ View for first-time app setup, to create admin user. From deaf1976f3e5946483e6bbd81daf79b1d54e102c Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 1 Sep 2025 11:04:31 -0500 Subject: [PATCH 25/32] fix: fix 'too-many-nested-blocks' for pylint --- .pylintrc | 1 - src/wuttaweb/menus.py | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.pylintrc b/.pylintrc index c42bc1d..e0e154b 100644 --- a/.pylintrc +++ b/.pylintrc @@ -8,4 +8,3 @@ disable=fixme, duplicate-code, keyword-arg-before-vararg, no-member, - too-many-nested-blocks, diff --git a/src/wuttaweb/menus.py b/src/wuttaweb/menus.py index 10e9a97..8e04296 100644 --- a/src/wuttaweb/menus.py +++ b/src/wuttaweb/menus.py @@ -229,7 +229,7 @@ class MenuHandler(GenericHandler): # that somewhat to produce our final menus self._mark_allowed(request, raw_menus) final_menus = [] - for topitem in raw_menus: + for topitem in raw_menus: # pylint: disable=too-many-nested-blocks if topitem["allowed"]: @@ -323,7 +323,7 @@ class MenuHandler(GenericHandler): Traverse the menu set, and mark each item as "allowed" (or not) based on current user permissions. """ - for topitem in menus: + for topitem in menus: # pylint: disable=too-many-nested-blocks if topitem.get("type", "menu") == "link": topitem["allowed"] = True From e123b12cd9a46d2970f58a0277034916ae01752c Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 1 Sep 2025 11:06:47 -0500 Subject: [PATCH 26/32] fix: fix 'keyword-arg-before-vararg' for pylint --- .pylintrc | 1 - src/wuttaweb/forms/schema.py | 9 ++------- src/wuttaweb/forms/widgets.py | 3 ++- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/.pylintrc b/.pylintrc index e0e154b..7af1cf2 100644 --- a/.pylintrc +++ b/.pylintrc @@ -6,5 +6,4 @@ disable=fixme, arguments-renamed, attribute-defined-outside-init, duplicate-code, - keyword-arg-before-vararg, no-member, diff --git a/src/wuttaweb/forms/schema.py b/src/wuttaweb/forms/schema.py index 271bdd9..f790f3a 100644 --- a/src/wuttaweb/forms/schema.py +++ b/src/wuttaweb/forms/schema.py @@ -288,13 +288,8 @@ class ObjectRef(colander.SchemaType): default_empty_option = ("", "(none)") - def __init__( - self, - request, - empty_option=None, - *args, - **kwargs, - ): + def __init__(self, request, *args, **kwargs): + empty_option = kwargs.pop("empty_option", None) # nb. allow session injection for tests self.session = kwargs.pop("session", Session()) super().__init__(*args, **kwargs) diff --git a/src/wuttaweb/forms/widgets.py b/src/wuttaweb/forms/widgets.py index f33f0fd..ae233bb 100644 --- a/src/wuttaweb/forms/widgets.py +++ b/src/wuttaweb/forms/widgets.py @@ -103,7 +103,8 @@ class ObjectRefWidget(SelectWidget): readonly_template = "readonly/objectref" - def __init__(self, request, url=None, *args, **kwargs): + def __init__(self, request, *args, **kwargs): + url = kwargs.pop("url", None) super().__init__(*args, **kwargs) self.request = request self.url = url From 459c16ba4fcc02dd92084967f375ffca247f4f32 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 1 Sep 2025 11:21:44 -0500 Subject: [PATCH 27/32] fix: fix 'arguments-differ' for pylint --- .pylintrc | 1 - src/wuttaweb/views/email.py | 8 ++++++-- src/wuttaweb/views/reports.py | 4 +++- src/wuttaweb/views/roles.py | 2 +- src/wuttaweb/views/settings.py | 4 +++- 5 files changed, 13 insertions(+), 6 deletions(-) diff --git a/.pylintrc b/.pylintrc index 7af1cf2..c29befd 100644 --- a/.pylintrc +++ b/.pylintrc @@ -2,7 +2,6 @@ [MESSAGES CONTROL] disable=fixme, - arguments-differ, arguments-renamed, attribute-defined-outside-init, duplicate-code, diff --git a/src/wuttaweb/views/email.py b/src/wuttaweb/views/email.py index 18526f5..5f51832 100644 --- a/src/wuttaweb/views/email.py +++ b/src/wuttaweb/views/email.py @@ -136,7 +136,9 @@ class EmailSettingView(MasterView): # pylint: disable=abstract-method recips = ", ".join(recips[:2]) return f"{recips}, ..." - def get_instance(self): # pylint: disable=empty-docstring + def get_instance( # pylint: disable=empty-docstring,arguments-differ,unused-argument + self, **kwargs + ): """ """ key = self.request.matchdict["key"] setting = self.email_handler.get_email_setting(key, instance=False) @@ -175,7 +177,9 @@ class EmailSettingView(MasterView): # pylint: disable=abstract-method # enabled f.set_node("enabled", colander.Boolean()) - def persist(self, setting): # pylint: disable=too-many-branches,empty-docstring + def persist( # pylint: disable=too-many-branches,empty-docstring,arguments-differ,unused-argument + self, setting, **kwargs + ): """ """ session = self.Session() key = self.request.matchdict["key"] diff --git a/src/wuttaweb/views/reports.py b/src/wuttaweb/views/reports.py index f81e47d..516965f 100644 --- a/src/wuttaweb/views/reports.py +++ b/src/wuttaweb/views/reports.py @@ -103,7 +103,9 @@ class ReportView(MasterView): # pylint: disable=abstract-method # help_text g.set_searchable("help_text") - def get_instance(self): # pylint: disable=empty-docstring + def get_instance( # pylint: disable=empty-docstring,arguments-differ,unused-argument + self, **kwargs + ): """ """ key = self.request.matchdict["report_key"] report = self.report_handler.get_report(key) diff --git a/src/wuttaweb/views/roles.py b/src/wuttaweb/views/roles.py index abce1d6..bae95d3 100644 --- a/src/wuttaweb/views/roles.py +++ b/src/wuttaweb/views/roles.py @@ -346,7 +346,7 @@ class PermissionView(MasterView): # pylint: disable=abstract-method "permission", ] - def get_query(self, **kwargs): # pylint: disable=empty-docstring + def get_query(self, **kwargs): # pylint: disable=empty-docstring,arguments-differ """ """ query = super().get_query(**kwargs) model = self.app.model diff --git a/src/wuttaweb/views/settings.py b/src/wuttaweb/views/settings.py index a35e4a9..efbefa2 100644 --- a/src/wuttaweb/views/settings.py +++ b/src/wuttaweb/views/settings.py @@ -173,7 +173,9 @@ class AppInfoView(MasterView): # pylint: disable=abstract-method return simple_settings - def configure_get_context(self, **kwargs): # pylint: disable=empty-docstring + def configure_get_context( # pylint: disable=empty-docstring,arguments-differ + self, **kwargs + ): """ """ context = super().configure_get_context(**kwargs) From 92754a64c497f47ac3720bb056554d5fee521dd5 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 1 Sep 2025 11:33:43 -0500 Subject: [PATCH 28/32] fix: fix 'arguments-renamed' for pylint --- .pylintrc | 1 - src/wuttaweb/forms/schema.py | 9 ++++++--- src/wuttaweb/views/batch.py | 24 ++++++++++++++++-------- src/wuttaweb/views/email.py | 9 ++++++--- src/wuttaweb/views/people.py | 6 ++++-- src/wuttaweb/views/reports.py | 9 ++++++--- src/wuttaweb/views/roles.py | 18 ++++++++++++------ src/wuttaweb/views/settings.py | 9 ++++++--- src/wuttaweb/views/upgrades.py | 15 ++++++++++----- src/wuttaweb/views/users.py | 9 ++++++--- 10 files changed, 72 insertions(+), 37 deletions(-) diff --git a/.pylintrc b/.pylintrc index c29befd..6f4f59c 100644 --- a/.pylintrc +++ b/.pylintrc @@ -2,7 +2,6 @@ [MESSAGES CONTROL] disable=fixme, - arguments-renamed, attribute-defined-outside-init, duplicate-code, no-member, diff --git a/src/wuttaweb/forms/schema.py b/src/wuttaweb/forms/schema.py index f790f3a..e42ac33 100644 --- a/src/wuttaweb/forms/schema.py +++ b/src/wuttaweb/forms/schema.py @@ -472,8 +472,9 @@ class PersonRef(ObjectRef): """ """ return query.order_by(self.model_class.full_name) - def get_object_url(self, person): # pylint: disable=empty-docstring + def get_object_url(self, obj): # pylint: disable=empty-docstring """ """ + person = obj return self.request.route_url("people.view", uuid=person.uuid) @@ -496,8 +497,9 @@ class RoleRef(ObjectRef): """ """ return query.order_by(self.model_class.name) - def get_object_url(self, role): # pylint: disable=empty-docstring + def get_object_url(self, obj): # pylint: disable=empty-docstring """ """ + role = obj return self.request.route_url("roles.view", uuid=role.uuid) @@ -520,8 +522,9 @@ class UserRef(ObjectRef): """ """ return query.order_by(self.model_class.username) - def get_object_url(self, user): # pylint: disable=empty-docstring + def get_object_url(self, obj): # pylint: disable=empty-docstring """ """ + user = obj return self.request.route_url("users.view", uuid=user.uuid) diff --git a/src/wuttaweb/views/batch.py b/src/wuttaweb/views/batch.py index 036bf88..5d85dc2 100644 --- a/src/wuttaweb/views/batch.py +++ b/src/wuttaweb/views/batch.py @@ -121,8 +121,9 @@ class BatchMasterView(MasterView): return super().render_to_response(template, context) - def configure_grid(self, g): # pylint: disable=empty-docstring + def configure_grid(self, grid): # pylint: disable=empty-docstring """ """ + g = grid super().configure_grid(g) model = self.app.model @@ -153,15 +154,17 @@ class BatchMasterView(MasterView): return f"{batch_id:08d}" return None - def get_instance_title(self, batch): # pylint: disable=empty-docstring + def get_instance_title(self, instance): # pylint: disable=empty-docstring """ """ + batch = instance if batch.description: return f"{batch.id_str} {batch.description}" return batch.id_str - def configure_form(self, f): # pylint: disable=too-many-branches,empty-docstring + def configure_form(self, form): # pylint: disable=too-many-branches,empty-docstring """ """ - super().configure_form(f) + super().configure_form(form) + f = form batch = f.model_instance # id @@ -253,7 +256,7 @@ class BatchMasterView(MasterView): # when not creating, normal logic is fine return super().objectify(form) - def redirect_after_create(self, batch): + def redirect_after_create(self, obj): """ If the new batch requires initial population, we launch a thread for that and show the "progress" page. @@ -261,6 +264,8 @@ class BatchMasterView(MasterView): Otherwise this will do the normal thing of redirecting to the "view" page for the new batch. """ + batch = obj + # just view batch if should not populate if not self.batch_handler.should_populate(batch): return self.redirect(self.get_action_url("view", batch)) @@ -281,7 +286,7 @@ class BatchMasterView(MasterView): thread.start() return self.render_progress(progress) - def delete_instance(self, batch): + def delete_instance(self, obj): """ Delete the given batch instance. @@ -289,6 +294,7 @@ class BatchMasterView(MasterView): :meth:`~wuttjamaican:wuttjamaican.batch.BatchHandler.do_delete()` on the :attr:`batch_handler`. """ + batch = obj self.batch_handler.do_delete(batch, self.request.user) ############################## @@ -386,20 +392,22 @@ class BatchMasterView(MasterView): model_class = cls.get_model_class() return model_class.__row_class__ - def get_row_grid_data(self, batch): + def get_row_grid_data(self, obj): """ Returns the base query for the batch :attr:`~wuttjamaican:wuttjamaican.db.model.batch.BatchMixin.rows` data. """ + batch = obj row_model_class = self.get_row_model_class() query = self.Session.query(row_model_class).filter( row_model_class.batch == batch ) return query - def configure_row_grid(self, g): # pylint: disable=empty-docstring + def configure_row_grid(self, grid): # pylint: disable=empty-docstring """ """ + g = grid super().configure_row_grid(g) g.set_label("sequence", "Seq.", column_only=True) diff --git a/src/wuttaweb/views/email.py b/src/wuttaweb/views/email.py index 5f51832..981faff 100644 --- a/src/wuttaweb/views/email.py +++ b/src/wuttaweb/views/email.py @@ -107,8 +107,9 @@ class EmailSettingView(MasterView): # pylint: disable=abstract-method "enabled": self.email_handler.is_enabled(key), } - def configure_grid(self, g): # pylint: disable=empty-docstring + def configure_grid(self, grid): # pylint: disable=empty-docstring """ """ + g = grid super().configure_grid(g) # key @@ -147,12 +148,14 @@ class EmailSettingView(MasterView): # pylint: disable=abstract-method raise self.notfound() - def get_instance_title(self, setting): # pylint: disable=empty-docstring + def get_instance_title(self, instance): # pylint: disable=empty-docstring """ """ + setting = instance return setting["subject"] - def configure_form(self, f): # pylint: disable=empty-docstring + def configure_form(self, form): # pylint: disable=empty-docstring """ """ + f = form super().configure_form(f) # description diff --git a/src/wuttaweb/views/people.py b/src/wuttaweb/views/people.py index bd75f90..d832ed4 100644 --- a/src/wuttaweb/views/people.py +++ b/src/wuttaweb/views/people.py @@ -70,8 +70,9 @@ class PersonView(MasterView): # pylint: disable=abstract-method "users", ] - def configure_grid(self, g): # pylint: disable=empty-docstring + def configure_grid(self, grid): # pylint: disable=empty-docstring """ """ + g = grid super().configure_grid(g) # full_name @@ -83,8 +84,9 @@ class PersonView(MasterView): # pylint: disable=abstract-method # last_name g.set_link("last_name") - def configure_form(self, f): # pylint: disable=empty-docstring + def configure_form(self, form): # pylint: disable=empty-docstring """ """ + f = form super().configure_form(f) person = f.model_instance diff --git a/src/wuttaweb/views/reports.py b/src/wuttaweb/views/reports.py index 516965f..90ff204 100644 --- a/src/wuttaweb/views/reports.py +++ b/src/wuttaweb/views/reports.py @@ -89,8 +89,9 @@ class ReportView(MasterView): # pylint: disable=abstract-method "help_text": report.__doc__, } - def configure_grid(self, g): # pylint: disable=empty-docstring + def configure_grid(self, grid): # pylint: disable=empty-docstring """ """ + g = grid super().configure_grid(g) # report_key @@ -114,8 +115,9 @@ class ReportView(MasterView): # pylint: disable=abstract-method raise self.notfound() - def get_instance_title(self, report): # pylint: disable=empty-docstring + def get_instance_title(self, instance): # pylint: disable=empty-docstring """ """ + report = instance return report["report_title"] def view(self): @@ -153,8 +155,9 @@ class ReportView(MasterView): # pylint: disable=abstract-method return self.render_to_response("view", context) - def configure_form(self, f): # pylint: disable=empty-docstring + def configure_form(self, form): # pylint: disable=empty-docstring """ """ + f = form super().configure_form(f) key = self.request.matchdict["report_key"] report = self.report_handler.get_report(key) diff --git a/src/wuttaweb/views/roles.py b/src/wuttaweb/views/roles.py index bae95d3..a697320 100644 --- a/src/wuttaweb/views/roles.py +++ b/src/wuttaweb/views/roles.py @@ -65,8 +65,9 @@ class RoleView(MasterView): # pylint: disable=abstract-method query = super().get_query(session=session) return query.order_by(model.Role.name) - def configure_grid(self, g): # pylint: disable=empty-docstring + def configure_grid(self, grid): # pylint: disable=empty-docstring """ """ + g = grid super().configure_grid(g) # name @@ -75,8 +76,9 @@ class RoleView(MasterView): # pylint: disable=abstract-method # notes g.set_renderer("notes", self.grid_render_notes) - def is_editable(self, role): # pylint: disable=empty-docstring + def is_editable(self, obj): # pylint: disable=empty-docstring """ """ + role = obj session = self.app.get_session(role) auth = self.app.get_auth_handler() @@ -93,8 +95,9 @@ class RoleView(MasterView): # pylint: disable=abstract-method return True - def is_deletable(self, role): # pylint: disable=empty-docstring + def is_deletable(self, obj): # pylint: disable=empty-docstring """ """ + role = obj session = self.app.get_session(role) auth = self.app.get_auth_handler() @@ -108,8 +111,9 @@ class RoleView(MasterView): # pylint: disable=abstract-method return True - def configure_form(self, f): # pylint: disable=empty-docstring + def configure_form(self, form): # pylint: disable=empty-docstring """ """ + f = form super().configure_form(f) role = f.model_instance @@ -356,8 +360,9 @@ class PermissionView(MasterView): # pylint: disable=abstract-method return query - def configure_grid(self, g): # pylint: disable=empty-docstring + def configure_grid(self, grid): # pylint: disable=empty-docstring """ """ + g = grid super().configure_grid(g) model = self.app.model @@ -369,8 +374,9 @@ class PermissionView(MasterView): # pylint: disable=abstract-method # permission g.set_link("permission") - def configure_form(self, f): # pylint: disable=empty-docstring + def configure_form(self, form): # pylint: disable=empty-docstring """ """ + f = form super().configure_form(f) # role diff --git a/src/wuttaweb/views/settings.py b/src/wuttaweb/views/settings.py index efbefa2..11cb0d0 100644 --- a/src/wuttaweb/views/settings.py +++ b/src/wuttaweb/views/settings.py @@ -93,8 +93,9 @@ class AppInfoView(MasterView): # pylint: disable=abstract-method return data - def configure_grid(self, g): # pylint: disable=empty-docstring + def configure_grid(self, grid): # pylint: disable=empty-docstring """ """ + g = grid super().configure_grid(g) g.sort_multiple = False @@ -244,15 +245,17 @@ class SettingView(MasterView): # pylint: disable=abstract-method sort_defaults = "name" # TODO: master should handle this (per model key) - def configure_grid(self, g): # pylint: disable=empty-docstring + def configure_grid(self, grid): # pylint: disable=empty-docstring """ """ + g = grid super().configure_grid(g) # name g.set_link("name") - def configure_form(self, f): # pylint: disable=empty-docstring + def configure_form(self, form): # pylint: disable=empty-docstring """ """ + f = form super().configure_form(f) # name diff --git a/src/wuttaweb/views/upgrades.py b/src/wuttaweb/views/upgrades.py index 181e7a7..c591b45 100644 --- a/src/wuttaweb/views/upgrades.py +++ b/src/wuttaweb/views/upgrades.py @@ -72,8 +72,9 @@ class UpgradeView(MasterView): # pylint: disable=abstract-method sort_defaults = ("created", "desc") - def configure_grid(self, g): # pylint: disable=empty-docstring + def configure_grid(self, grid): # pylint: disable=empty-docstring """ """ + g = grid super().configure_grid(g) model = self.app.model enum = self.app.enum @@ -121,8 +122,9 @@ class UpgradeView(MasterView): # pylint: disable=abstract-method return "has-background-warning" return None - def configure_form(self, f): # pylint: disable=empty-docstring + def configure_form(self, form): # pylint: disable=empty-docstring """ """ + f = form super().configure_form(f) enum = self.app.enum upgrade = f.model_instance @@ -204,11 +206,12 @@ class UpgradeView(MasterView): # pylint: disable=abstract-method "stderr_file", self.get_upgrade_filepath(upgrade, "stderr.log") ) - def delete_instance(self, upgrade): + def delete_instance(self, obj): """ We override this method to delete any files associated with the upgrade, in addition to deleting the upgrade proper. """ + upgrade = obj path = self.get_upgrade_filepath(upgrade, create=False) if os.path.exists(path): shutil.rmtree(path) @@ -227,8 +230,9 @@ class UpgradeView(MasterView): # pylint: disable=abstract-method return upgrade - def download_path(self, upgrade, filename): # pylint: disable=empty-docstring + def download_path(self, obj, filename): # pylint: disable=empty-docstring """ """ + upgrade = obj if filename: return self.get_upgrade_filepath(upgrade, filename) return None @@ -245,7 +249,7 @@ class UpgradeView(MasterView): # pylint: disable=abstract-method path = os.path.join(path, filename) return path - def execute_instance(self, upgrade, user, progress=None): + def execute_instance(self, obj, user, progress=None): """ This method runs the actual upgrade. @@ -258,6 +262,7 @@ class UpgradeView(MasterView): # pylint: disable=abstract-method The upgrade itself is marked as "executed" with status of either ``SUCCESS`` or ``FAILURE``. """ + upgrade = obj enum = self.app.enum # locate file paths diff --git a/src/wuttaweb/views/users.py b/src/wuttaweb/views/users.py index 2644b21..fca830f 100644 --- a/src/wuttaweb/views/users.py +++ b/src/wuttaweb/views/users.py @@ -82,8 +82,9 @@ class UserView(MasterView): # pylint: disable=abstract-method return query - def configure_grid(self, g): # pylint: disable=empty-docstring + def configure_grid(self, grid): # pylint: disable=empty-docstring """ """ + g = grid super().configure_grid(g) model = self.app.model @@ -106,8 +107,9 @@ class UserView(MasterView): # pylint: disable=abstract-method return "has-background-warning" return None - def is_editable(self, user): # pylint: disable=empty-docstring + def is_editable(self, obj): # pylint: disable=empty-docstring """ """ + user = obj # only root can edit certain users if user.prevent_edit and not self.request.is_root: @@ -115,8 +117,9 @@ class UserView(MasterView): # pylint: disable=abstract-method return True - def configure_form(self, f): # pylint: disable=empty-docstring + def configure_form(self, form): # pylint: disable=empty-docstring """ """ + f = form super().configure_form(f) user = f.model_instance From dd25d98e7dcfb4b86e03ff609e5c5a73c2fc1f04 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 1 Sep 2025 11:53:50 -0500 Subject: [PATCH 29/32] fix: fix 'attribute-defined-outside-init' for pylint --- .pylintrc | 1 - src/wuttaweb/app.py | 6 +++--- src/wuttaweb/forms/base.py | 16 ++++++++-------- src/wuttaweb/grids/base.py | 15 +++++++++------ src/wuttaweb/views/master.py | 1 + src/wuttaweb/views/roles.py | 2 ++ tests/forms/test_base.py | 4 ++-- tests/grids/test_base.py | 8 ++++---- 8 files changed, 29 insertions(+), 24 deletions(-) diff --git a/.pylintrc b/.pylintrc index 6f4f59c..831eddb 100644 --- a/.pylintrc +++ b/.pylintrc @@ -2,6 +2,5 @@ [MESSAGES CONTROL] disable=fixme, - attribute-defined-outside-init, duplicate-code, no-member, diff --git a/src/wuttaweb/app.py b/src/wuttaweb/app.py index 38749e0..75d00f2 100644 --- a/src/wuttaweb/app.py +++ b/src/wuttaweb/app.py @@ -65,13 +65,13 @@ class WebAppProvider(AppProvider): :returns: Instance of :class:`~wuttaweb.handler.WebHandler`. """ - if "web_handler" not in self.__dict__: + if "web" not in self.app.handlers: spec = self.config.get( f"{self.appname}.web.handler_spec", default="wuttaweb.handler:WebHandler", ) - self.web_handler = self.app.load_object(spec)(self.config) - return self.web_handler + self.app.handlers["web"] = self.app.load_object(spec)(self.config) + return self.app.handlers["web"] def make_wutta_config(settings, config_maker=None, **kwargs): diff --git a/src/wuttaweb/forms/base.py b/src/wuttaweb/forms/base.py index d57fe73..0250bfb 100644 --- a/src/wuttaweb/forms/base.py +++ b/src/wuttaweb/forms/base.py @@ -264,10 +264,11 @@ class Form: # pylint: disable=too-many-instance-attributes,too-many-public-meth If the :meth:`validate()` method was called, and it succeeded, this will be set to the validated data dict. - - Note that in all other cases, this attribute may not exist. """ + deform_form = None + validated = None + def __init__( # pylint: disable=too-many-arguments,too-many-positional-arguments,too-many-locals self, request, @@ -874,7 +875,7 @@ class Form: # pylint: disable=too-many-instance-attributes,too-many-public-meth Return the :class:`deform:deform.Form` instance for the form, generating it automatically if necessary. """ - if not hasattr(self, "deform_form"): + if not self.deform_form: schema = self.get_schema() kwargs = {} @@ -1174,9 +1175,9 @@ class Form: # pylint: disable=too-many-instance-attributes,too-many-public-meth :attr:`validated` attribute. However if the data is not valid, ``False`` is returned, and - there will be no :attr:`validated` attribute. In that case - you should inspect the form errors to learn/display what went - wrong for the user's sake. See also + the :attr:`validated` attribute will be ``None``. In that + case you should inspect the form errors to learn/display what + went wrong for the user's sake. See also :meth:`get_field_errors()`. This uses :meth:`deform:deform.Field.validate()` under the @@ -1192,8 +1193,7 @@ class Form: # pylint: disable=too-many-instance-attributes,too-many-public-meth :returns: Data dict, or ``False``. """ - if hasattr(self, "validated"): - del self.validated + self.validated = None if self.request.method != "POST": return False diff --git a/src/wuttaweb/grids/base.py b/src/wuttaweb/grids/base.py index 074aa79..2779bef 100644 --- a/src/wuttaweb/grids/base.py +++ b/src/wuttaweb/grids/base.py @@ -264,7 +264,7 @@ class Grid: # pylint: disable=too-many-instance-attributes,too-many-public-meth ``active_sorters`` defines the "current/effective" sorters. This attribute is set by :meth:`load_settings()`; until that is - called it will not exist. + called its value will be ``None``. This is conceptually a "subset" of :attr:`sorters` although a different format is used here:: @@ -372,6 +372,10 @@ class Grid: # pylint: disable=too-many-instance-attributes,too-many-public-meth See also :meth:`add_tool()` and :meth:`set_tools()`. """ + active_sorters = None + joined = None + pager = None + def __init__( # pylint: disable=too-many-arguments,too-many-positional-arguments,too-many-locals self, request, @@ -2293,12 +2297,11 @@ class Grid: # pylint: disable=too-many-instance-attributes,too-many-public-meth :returns: The first sorter in format ``[sortkey, sortdir]``, or ``None``. """ - if hasattr(self, "active_sorters"): - if self.active_sorters: - sorter = self.active_sorters[0] - return [sorter["key"], sorter["dir"]] + if self.active_sorters: + sorter = self.active_sorters[0] + return [sorter["key"], sorter["dir"]] - elif self.sort_defaults: + if self.sort_defaults: sorter = self.sort_defaults[0] return [sorter.sortkey, sorter.sortdir] diff --git a/src/wuttaweb/views/master.py b/src/wuttaweb/views/master.py index b6347bb..2b070a0 100644 --- a/src/wuttaweb/views/master.py +++ b/src/wuttaweb/views/master.py @@ -439,6 +439,7 @@ class MasterView(View): # pylint: disable=too-many-public-methods viewing = False editing = False deleting = False + executing = False configuring = False # default DB session diff --git a/src/wuttaweb/views/roles.py b/src/wuttaweb/views/roles.py index a697320..20299c3 100644 --- a/src/wuttaweb/views/roles.py +++ b/src/wuttaweb/views/roles.py @@ -58,6 +58,8 @@ class RoleView(MasterView): # pylint: disable=abstract-method } sort_defaults = "name" + wutta_permissions = None + # TODO: master should handle this, possibly via configure_form() def get_query(self, session=None): # pylint: disable=empty-docstring """ """ diff --git a/tests/forms/test_base.py b/tests/forms/test_base.py index eaa2286..73bc47a 100644 --- a/tests/forms/test_base.py +++ b/tests/forms/test_base.py @@ -363,7 +363,7 @@ class TestForm(TestCase): # basic form = self.make_form(schema=schema) - self.assertFalse(hasattr(form, "deform_form")) + self.assertIsNone(form.deform_form) dform = form.get_deform() self.assertIsInstance(dform, deform.Form) self.assertIs(form.deform_form, dform) @@ -684,7 +684,7 @@ class TestForm(TestCase): def test_validate(self): schema = self.make_schema() form = self.make_form(schema=schema) - self.assertFalse(hasattr(form, "validated")) + self.assertIsNone(form.validated) # will not validate unless request is POST self.request.POST = {"foo": "blarg", "bar": "baz"} diff --git a/tests/grids/test_base.py b/tests/grids/test_base.py index ffc2645..0498d49 100644 --- a/tests/grids/test_base.py +++ b/tests/grids/test_base.py @@ -497,7 +497,7 @@ class TestGrid(WebTestCase): # settings are loaded, applied, saved self.assertEqual(grid.sort_defaults, []) - self.assertFalse(hasattr(grid, "active_sorters")) + self.assertIsNone(grid.active_sorters) self.request.GET = {"sort1key": "name", "sort1dir": "desc"} grid.load_settings() self.assertEqual(grid.active_sorters, [{"key": "name", "dir": "desc"}]) @@ -525,7 +525,7 @@ class TestGrid(WebTestCase): sort_on_backend=True, sort_defaults="name", ) - self.assertFalse(hasattr(grid, "active_sorters")) + self.assertIsNone(grid.active_sorters) grid.load_settings() self.assertEqual(grid.active_sorters, [{"key": "name", "dir": "asc"}]) @@ -537,7 +537,7 @@ class TestGrid(WebTestCase): mod.SortInfo("name", "asc"), mod.SortInfo("value", "desc"), ] - self.assertFalse(hasattr(grid, "active_sorters")) + self.assertIsNone(grid.active_sorters) grid.load_settings() self.assertEqual(grid.active_sorters, [{"key": "name", "dir": "asc"}]) @@ -556,7 +556,7 @@ class TestGrid(WebTestCase): paginated=True, paginate_on_backend=True, ) - self.assertFalse(hasattr(grid, "active_sorters")) + self.assertIsNone(grid.active_sorters) grid.load_settings() self.assertEqual(grid.active_sorters, [{"key": "name", "dir": "desc"}]) From ad74bede045fcfc846bb0ad010415cf8c7c76a74 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 1 Sep 2025 12:10:12 -0500 Subject: [PATCH 30/32] fix: fix 'no-member' for pylint --- .pylintrc | 1 - src/wuttaweb/forms/widgets.py | 2 ++ src/wuttaweb/grids/filters.py | 20 ++++++++++---------- src/wuttaweb/views/batch.py | 5 ++--- src/wuttaweb/views/master.py | 9 +++++---- tests/grids/test_filters.py | 2 +- tests/views/test_master.py | 2 +- 7 files changed, 21 insertions(+), 20 deletions(-) diff --git a/.pylintrc b/.pylintrc index 831eddb..527cc44 100644 --- a/.pylintrc +++ b/.pylintrc @@ -3,4 +3,3 @@ [MESSAGES CONTROL] disable=fixme, duplicate-code, - no-member, diff --git a/src/wuttaweb/forms/widgets.py b/src/wuttaweb/forms/widgets.py index ae233bb..55eea47 100644 --- a/src/wuttaweb/forms/widgets.py +++ b/src/wuttaweb/forms/widgets.py @@ -407,6 +407,7 @@ class RoleRefsWidget(WuttaCheckboxChoiceWidget): """ readonly_template = "readonly/rolerefs" + session = None def serialize(self, field, cstruct, **kw): # pylint: disable=empty-docstring """ """ @@ -463,6 +464,7 @@ class PermissionsWidget(WuttaCheckboxChoiceWidget): template = "permissions" readonly_template = "readonly/permissions" + permissions = None def serialize(self, field, cstruct, **kw): # pylint: disable=empty-docstring """ """ diff --git a/src/wuttaweb/grids/filters.py b/src/wuttaweb/grids/filters.py index 984952a..170fbd9 100644 --- a/src/wuttaweb/grids/filters.py +++ b/src/wuttaweb/grids/filters.py @@ -59,9 +59,10 @@ class GridFilter: # pylint: disable=too-many-instance-attributes :param request: Current :term:`request` object. - :param model_property: Property of a model class, representing the - column by which to filter. For instance, - ``model.Person.full_name``. + :param nullable: Boolean indicating whether the filter should + include ``is_null`` and ``is_not_null`` verbs. If not + specified, the column will be inspected (if possible) and use + its nullable flag. :param \\**kwargs: Any additional kwargs will be set as attributes on the filter instance. @@ -176,6 +177,7 @@ class GridFilter: # pylint: disable=too-many-instance-attributes label=None, verbs=None, choices=None, + nullable=None, default_active=False, default_verb=None, default_value=None, @@ -196,10 +198,14 @@ class GridFilter: # pylint: disable=too-many-instance-attributes self.verbs = verbs if default_verb: self.default_verb = default_verb + self.verb = None # active verb is set later # choices self.set_choices(choices or {}) + # nullable + self.nullable = nullable + # value self.default_value = default_value self.value = self.default_value @@ -398,18 +404,12 @@ class AlchemyFilter(GridFilter): :param model_property: Property of a model class, representing the column by which to filter. For instance, ``model.Person.full_name``. - - :param nullable: Boolean indicating whether the filter should - include ``is_null`` and ``is_not_null`` verbs. If not - specified, the column will be inspected and use its nullable - flag. """ def __init__(self, *args, **kwargs): - nullable = kwargs.pop("nullable", None) + self.model_property = kwargs.pop("model_property") super().__init__(*args, **kwargs) - self.nullable = nullable if self.nullable is None: columns = self.model_property.prop.columns if len(columns) == 1: diff --git a/src/wuttaweb/views/batch.py b/src/wuttaweb/views/batch.py index 5d85dc2..fd68e7e 100644 --- a/src/wuttaweb/views/batch.py +++ b/src/wuttaweb/views/batch.py @@ -398,11 +398,10 @@ class BatchMasterView(MasterView): :attr:`~wuttjamaican:wuttjamaican.db.model.batch.BatchMixin.rows` data. """ + session = self.Session() batch = obj row_model_class = self.get_row_model_class() - query = self.Session.query(row_model_class).filter( - row_model_class.batch == batch - ) + query = session.query(row_model_class).filter(row_model_class.batch == batch) return query def configure_row_grid(self, grid): # pylint: disable=empty-docstring diff --git a/src/wuttaweb/views/master.py b/src/wuttaweb/views/master.py index 2b070a0..d22707d 100644 --- a/src/wuttaweb/views/master.py +++ b/src/wuttaweb/views/master.py @@ -399,6 +399,8 @@ class MasterView(View): # pylint: disable=too-many-public-methods # attributes ############################## + model_class = None + # features listable = True has_grid = True @@ -526,11 +528,12 @@ class MasterView(View): # pylint: disable=too-many-public-methods * :meth:`redirect_after_create()` """ self.creating = True + session = self.Session() form = self.make_model_form(cancel_url_fallback=self.get_index_url()) if form.validate(): obj = self.create_save_form(form) - self.Session.flush() + session.flush() return self.redirect_after_create(obj) context = { @@ -2702,9 +2705,7 @@ class MasterView(View): # pylint: disable=too-many-public-methods do not set the :attr:`model_class`, then you *must* set the :attr:`model_name`. """ - if hasattr(cls, "model_class"): - return cls.model_class - return None + return cls.model_class @classmethod def get_model_name(cls): diff --git a/tests/grids/test_filters.py b/tests/grids/test_filters.py index 1247715..efb58eb 100644 --- a/tests/grids/test_filters.py +++ b/tests/grids/test_filters.py @@ -52,7 +52,7 @@ class TestGridFilter(WebTestCase): # verb is not set by default, but can be set filtr = self.make_filter(model.Setting.name) - self.assertFalse(hasattr(filtr, "verb")) + self.assertIsNone(filtr.verb) filtr = self.make_filter(model.Setting.name, verb="foo") self.assertEqual(filtr.verb, "foo") diff --git a/tests/views/test_master.py b/tests/views/test_master.py index cd04f8a..9ced228 100644 --- a/tests/views/test_master.py +++ b/tests/views/test_master.py @@ -624,7 +624,7 @@ class TestMasterView(WebTestCase): view = self.make_view() # empty by default - self.assertFalse(hasattr(mod.MasterView, "model_class")) + self.assertIsNone(mod.MasterView.model_class) data = view.get_grid_data(session=self.session) self.assertEqual(data, []) From a1868e1f4447e329710d49a99c8688088e05ba00 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 1 Sep 2025 13:31:33 -0500 Subject: [PATCH 31/32] fix: fix 'duplicate-code' for pylint --- .pylintrc | 5 ++- src/wuttaweb/forms/base.py | 15 ++++--- src/wuttaweb/grids/base.py | 14 +++--- src/wuttaweb/util.py | 65 ++++++++++++++++++++++++++++ src/wuttaweb/views/batch.py | 60 +++++--------------------- src/wuttaweb/views/master.py | 82 ++++++++++++++++++++++++++++-------- src/wuttaweb/views/people.py | 27 ++---------- src/wuttaweb/views/roles.py | 28 ++---------- tests/test_util.py | 47 +++++++++++++++++++++ tests/views/test_master.py | 19 +++++++++ 10 files changed, 233 insertions(+), 129 deletions(-) diff --git a/.pylintrc b/.pylintrc index 527cc44..5a30127 100644 --- a/.pylintrc +++ b/.pylintrc @@ -2,4 +2,7 @@ [MESSAGES CONTROL] disable=fixme, - duplicate-code, + +[SIMILARITIES] +# nb. cuts out some noise for duplicate-code +min-similarity-lines=5 diff --git a/src/wuttaweb/forms/base.py b/src/wuttaweb/forms/base.py index 0250bfb..6365aa8 100644 --- a/src/wuttaweb/forms/base.py +++ b/src/wuttaweb/forms/base.py @@ -37,7 +37,13 @@ from colanderalchemy import SQLAlchemySchemaNode from pyramid.renderers import render from webhelpers2.html import HTML -from wuttaweb.util import FieldList, get_form_data, get_model_fields, make_json_safe +from wuttaweb.util import ( + FieldList, + get_form_data, + get_model_fields, + make_json_safe, + render_vue_finalize, +) log = logging.getLogger(__name__) @@ -1095,12 +1101,7 @@ class Form: # pylint: disable=too-many-instance-attributes,too-many-public-meth The actual output may depend on various form attributes, in particular :attr:`vue_tagname`. """ - set_data = f"{self.vue_component}.data = function() {{ return {self.vue_component}Data }}" - make_component = f"Vue.component('{self.vue_tagname}', {self.vue_component})" - return HTML.tag( - "script", - c=["\n", HTML.literal(set_data), "\n", HTML.literal(make_component), "\n"], - ) + return render_vue_finalize(self.vue_tagname, self.vue_component) def get_vue_model_data(self): """ diff --git a/src/wuttaweb/grids/base.py b/src/wuttaweb/grids/base.py index 2779bef..9461b23 100644 --- a/src/wuttaweb/grids/base.py +++ b/src/wuttaweb/grids/base.py @@ -39,7 +39,12 @@ from pyramid.renderers import render from webhelpers2.html import HTML from wuttjamaican.db.util import UUID -from wuttaweb.util import FieldList, get_model_fields, make_json_safe +from wuttaweb.util import ( + FieldList, + get_model_fields, + make_json_safe, + render_vue_finalize, +) from wuttaweb.grids.filters import default_sqlalchemy_filters, VerbNotSupported @@ -2212,12 +2217,7 @@ class Grid: # pylint: disable=too-many-instance-attributes,too-many-public-meth The actual output may depend on various grid attributes, in particular :attr:`vue_tagname`. """ - set_data = f"{self.vue_component}.data = function() {{ return {self.vue_component}Data }}" - make_component = f"Vue.component('{self.vue_tagname}', {self.vue_component})" - return HTML.tag( - "script", - c=["\n", HTML.literal(set_data), "\n", HTML.literal(make_component), "\n"], - ) + return render_vue_finalize(self.vue_tagname, self.vue_component) def get_vue_columns(self): """ diff --git a/src/wuttaweb/util.py b/src/wuttaweb/util.py index 963c848..5492485 100644 --- a/src/wuttaweb/util.py +++ b/src/wuttaweb/util.py @@ -618,6 +618,71 @@ def make_json_safe(value, key=None, warn=True): return value +def render_vue_finalize(vue_tagname, vue_component): + """ + Render the Vue "finalize" script for a form or grid component. + + This is a convenience for shared logic; it returns e.g.: + + .. code-block:: html + + + """ + set_data = f"{vue_component}.data = function() {{ return {vue_component}Data }}" + make_component = f"Vue.component('{vue_tagname}', {vue_component})" + return HTML.tag( + "script", + c=["\n", HTML.literal(set_data), "\n", HTML.literal(make_component), "\n"], + ) + + +def make_users_grid(request, **kwargs): + """ + Make and return a users (sub)grid. + + This grid is shown for the Users field when viewing a Person or + Role, for instance. It is called by the following methods: + + * :meth:`wuttaweb.views.people.PersonView.make_users_grid()` + * :meth:`wuttaweb.views.roles.RoleView.make_users_grid()` + + :returns: Fully configured :class:`~wuttaweb.grids.base.Grid` + instance. + """ + config = request.wutta_config + app = config.get_app() + model = app.model + web = app.get_web_handler() + + if "key" not in kwargs: + route_prefix = kwargs.pop("route_prefix") + kwargs["key"] = f"{route_prefix}.view.users" + + kwargs.setdefault("model_class", model.User) + grid = web.make_grid(request, **kwargs) + + if request.has_perm("users.view"): + + def view_url(user, i): # pylint: disable=unused-argument + return request.route_url("users.view", uuid=user.uuid) + + grid.add_action("view", icon="eye", url=view_url) + grid.set_link("person") + grid.set_link("username") + + if request.has_perm("users.edit"): + + def edit_url(user, i): # pylint: disable=unused-argument + return request.route_url("users.edit", uuid=user.uuid) + + grid.add_action("edit", url=edit_url) + + return grid + + ############################## # theme functions ############################## diff --git a/src/wuttaweb/views/batch.py b/src/wuttaweb/views/batch.py index fd68e7e..79bea75 100644 --- a/src/wuttaweb/views/batch.py +++ b/src/wuttaweb/views/batch.py @@ -51,6 +51,8 @@ class BatchMasterView(MasterView): from :meth:`get_batch_handler()`. """ + executable = True + labels = { "id": "Batch ID", "status_code": "Status", @@ -330,29 +332,22 @@ class BatchMasterView(MasterView): raise RuntimeError("can't find the batch") time.sleep(0.1) - try: - # populate the batch - self.batch_handler.do_populate(batch, progress=progress) - session.flush() - - except Exception as error: # pylint: disable=broad-exception-caught - session.rollback() + def onerror(): log.warning( "failed to populate %s: %s", self.get_model_title(), batch, exc_info=True, ) - if progress: - progress.handle_error(error) - else: - session.commit() - if progress: - progress.handle_success() - - finally: - session.close() + self.do_thread_body( + self.batch_handler.do_populate, + (batch,), + {"progress": progress}, + onerror, + session=session, + progress=progress, + ) ############################## # execute methods @@ -418,36 +413,3 @@ class BatchMasterView(MasterView): ): """ """ return row.STATUS.get(value, value) - - ############################## - # configuration - ############################## - - @classmethod - def defaults(cls, config): # pylint: disable=empty-docstring - """ """ - cls._defaults(config) - cls._batch_defaults(config) - - @classmethod - def _batch_defaults(cls, config): - route_prefix = cls.get_route_prefix() - permission_prefix = cls.get_permission_prefix() - model_title = cls.get_model_title() - instance_url_prefix = cls.get_instance_url_prefix() - - # execute - config.add_route( - f"{route_prefix}.execute", - f"{instance_url_prefix}/execute", - request_method="POST", - ) - config.add_view( - cls, - attr="execute", - route_name=f"{route_prefix}.execute", - permission=f"{permission_prefix}.execute", - ) - config.add_wutta_permission( - permission_prefix, f"{permission_prefix}.execute", f"Execute {model_title}" - ) diff --git a/src/wuttaweb/views/master.py b/src/wuttaweb/views/master.py index d22707d..500a276 100644 --- a/src/wuttaweb/views/master.py +++ b/src/wuttaweb/views/master.py @@ -822,33 +822,25 @@ class MasterView(View): # pylint: disable=too-many-public-methods self, query, progress=None ): """ """ - model_title_plural = self.get_model_title_plural() - - # nb. use new session, separate from web transaction session = self.app.make_session() records = query.with_session(session).all() - try: - self.delete_bulk_action(records, progress=progress) - - except Exception as error: # pylint: disable=broad-exception-caught - session.rollback() + def onerror(): log.warning( "failed to delete %s results for %s", len(records), - model_title_plural, + self.get_model_title_plural(), exc_info=True, ) - if progress: - progress.handle_error(error) - else: - session.commit() - if progress: - progress.handle_success() - - finally: - session.close() + self.do_thread_body( + self.delete_bulk_action, + (records,), + {"progress": progress}, + onerror, + session=session, + progress=progress, + ) def delete_bulk_action(self, data, progress=None): """ @@ -2485,6 +2477,60 @@ class MasterView(View): # pylint: disable=too-many-public-methods session = session or self.Session() session.add(obj) + def do_thread_body( # pylint: disable=too-many-arguments,too-many-positional-arguments + self, func, args, kwargs, onerror=None, session=None, progress=None + ): + """ + Generic method to invoke for thread operations. + + :param func: Callable which performs the actual logic. This + will be wrapped with a try/except statement for error + handling. + + :param args: Tuple of positional arguments to pass to the + ``func`` callable. + + :param kwargs: Dict of keyword arguments to pass to the + ``func`` callable. + + :param onerror: Optional callback to invoke if ``func`` raises + an error. It should not expect any arguments. + + :param session: Optional :term:`db session` in effect. Note + that if supplied, it will be *committed* (or rolled back on + error) and *closed* by this method. If you need more + specialized handling, do not use this method (or don't + specify the ``session``). + + :param progress: Optional progress factory. If supplied, this + is assumed to be a + :class:`~wuttaweb.progress.SessionProgress` instance, and + it will be updated per success or failure of ``func`` + invocation. + """ + try: + func(*args, **kwargs) + + except Exception as error: # pylint: disable=broad-exception-caught + if session: + session.rollback() + if onerror: + onerror() + else: + log.warning("failed to invoke thread callable: %s", func, exc_info=True) + if progress: + progress.handle_error(error) + + else: + if session: + session.commit() + if progress: + progress.handle_success() + + finally: + if session: + session.close() + ############################## # row methods ############################## diff --git a/src/wuttaweb/views/people.py b/src/wuttaweb/views/people.py index d832ed4..b726772 100644 --- a/src/wuttaweb/views/people.py +++ b/src/wuttaweb/views/people.py @@ -28,6 +28,7 @@ import sqlalchemy as sa from wuttjamaican.db.model import Person from wuttaweb.views import MasterView +from wuttaweb.util import make_users_grid class PersonView(MasterView): # pylint: disable=abstract-method @@ -107,12 +108,9 @@ class PersonView(MasterView): # pylint: disable=abstract-method :returns: Fully configured :class:`~wuttaweb.grids.base.Grid` instance. """ - model = self.app.model - route_prefix = self.get_route_prefix() - - grid = self.make_grid( - key=f"{route_prefix}.view.users", - model_class=model.User, + return make_users_grid( + self.request, + route_prefix=self.get_route_prefix(), data=person.users, columns=[ "username", @@ -120,23 +118,6 @@ class PersonView(MasterView): # pylint: disable=abstract-method ], ) - if self.request.has_perm("users.view"): - - def view_url(user, i): # pylint: disable=unused-argument - return self.request.route_url("users.view", uuid=user.uuid) - - grid.add_action("view", icon="eye", url=view_url) - grid.set_link("username") - - if self.request.has_perm("users.edit"): - - def edit_url(user, i): # pylint: disable=unused-argument - return self.request.route_url("users.edit", uuid=user.uuid) - - grid.add_action("edit", url=edit_url) - - return grid - def objectify(self, form): # pylint: disable=empty-docstring """ """ person = super().objectify(form) diff --git a/src/wuttaweb/views/roles.py b/src/wuttaweb/views/roles.py index 20299c3..f1f9b1e 100644 --- a/src/wuttaweb/views/roles.py +++ b/src/wuttaweb/views/roles.py @@ -29,6 +29,7 @@ from wuttaweb.views import MasterView from wuttaweb.db import Session from wuttaweb.forms import widgets from wuttaweb.forms.schema import Permissions, RoleRef +from wuttaweb.util import make_users_grid class RoleView(MasterView): # pylint: disable=abstract-method @@ -151,12 +152,9 @@ class RoleView(MasterView): # pylint: disable=abstract-method :returns: Fully configured :class:`~wuttaweb.grids.base.Grid` instance. """ - model = self.app.model - route_prefix = self.get_route_prefix() - - grid = self.make_grid( - key=f"{route_prefix}.view.users", - model_class=model.User, + return make_users_grid( + self.request, + route_prefix=self.get_route_prefix(), data=role.users, columns=[ "username", @@ -165,24 +163,6 @@ class RoleView(MasterView): # pylint: disable=abstract-method ], ) - if self.request.has_perm("users.view"): - - def view_url(user, i): # pylint: disable=unused-argument - return self.request.route_url("users.view", uuid=user.uuid) - - grid.add_action("view", icon="eye", url=view_url) - grid.set_link("person") - grid.set_link("username") - - if self.request.has_perm("users.edit"): - - def edit_url(user, i): # pylint: disable=unused-argument - return self.request.route_url("users.edit", uuid=user.uuid) - - grid.add_action("edit", url=edit_url) - - return grid - def unique_name(self, node, value): # pylint: disable=empty-docstring """ """ model = self.app.model diff --git a/tests/test_util.py b/tests/test_util.py index 48c9695..a0285a1 100644 --- a/tests/test_util.py +++ b/tests/test_util.py @@ -16,6 +16,7 @@ from wuttjamaican.util import resource_path from wuttaweb import util as mod from wuttaweb.app import establish_theme +from wuttaweb.grids import Grid from wuttaweb.testing import WebTestCase @@ -665,6 +666,52 @@ class TestMakeJsonSafe(TestCase): ) +class TestRenderVueFinalize(TestCase): + + def basic(self): + html = mod.render_vue_finalize("wutta-grid", "WuttaGrid") + self.assertIn("