From 3137f0a3da86c4a59dd3441c722a1d224c1fec84 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Sat, 30 Aug 2025 18:46:06 -0500 Subject: [PATCH 01/26] fix: fix 'invalid-name' for pylint --- .pylintrc | 1 + src/wuttjamaican/app.py | 4 ++-- src/wuttjamaican/db/sess.py | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.pylintrc b/.pylintrc index bcf5b0b..11efb26 100644 --- a/.pylintrc +++ b/.pylintrc @@ -5,6 +5,7 @@ disable=all enable=anomalous-backslash-in-string, dangerous-default-value, inconsistent-return-statements, + invalid-name, redefined-argument-from-local, unspecified-encoding, unused-argument, diff --git a/src/wuttjamaican/app.py b/src/wuttjamaican/app.py index aba810b..c43752d 100644 --- a/src/wuttjamaican/app.py +++ b/src/wuttjamaican/app.py @@ -929,8 +929,8 @@ class AppHandler: # registered via entry points registered = [] - for Handler in load_entry_points(f'{self.appname}.batch.{key}').values(): - spec = Handler.get_spec() + for handler in load_entry_points(f'{self.appname}.batch.{key}').values(): + spec = handler.get_spec() if spec not in handlers: registered.append(spec) if registered: diff --git a/src/wuttjamaican/db/sess.py b/src/wuttjamaican/db/sess.py index 7fd7a62..9033832 100644 --- a/src/wuttjamaican/db/sess.py +++ b/src/wuttjamaican/db/sess.py @@ -2,7 +2,7 @@ ################################################################################ # # WuttJamaican -- Base package for Wutta Framework -# Copyright © 2023 Lance Edgar +# Copyright © 2023-2025 Lance Edgar # # This file is part of Wutta Framework. # @@ -38,7 +38,7 @@ from sqlalchemy import orm Session = orm.sessionmaker() -class short_session: +class short_session: # pylint: disable=invalid-name """ Context manager for a short-lived database session. From dfe2b94f4f9390e2f87dcb177e36ee8d380472cd Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Sat, 30 Aug 2025 18:50:56 -0500 Subject: [PATCH 02/26] fix: fix 'too-few-public-methods' for pylint --- .pylintrc | 1 + src/wuttjamaican/app.py | 2 +- src/wuttjamaican/db/model/auth.py | 10 +++++----- src/wuttjamaican/db/model/base.py | 4 ++-- src/wuttjamaican/db/model/batch.py | 2 +- src/wuttjamaican/db/model/upgrades.py | 2 +- src/wuttjamaican/email.py | 2 +- 7 files changed, 12 insertions(+), 11 deletions(-) diff --git a/.pylintrc b/.pylintrc index 11efb26..dbdf127 100644 --- a/.pylintrc +++ b/.pylintrc @@ -7,6 +7,7 @@ enable=anomalous-backslash-in-string, inconsistent-return-statements, invalid-name, redefined-argument-from-local, + too-few-public-methods, unspecified-encoding, unused-argument, unused-import, diff --git a/src/wuttjamaican/app.py b/src/wuttjamaican/app.py index c43752d..8b5f671 100644 --- a/src/wuttjamaican/app.py +++ b/src/wuttjamaican/app.py @@ -1045,7 +1045,7 @@ class AppHandler: self.get_email_handler().send_email(*args, **kwargs) -class AppProvider: +class AppProvider: # pylint: disable=too-few-public-methods """ Base class for :term:`app providers`. diff --git a/src/wuttjamaican/db/model/auth.py b/src/wuttjamaican/db/model/auth.py index b776d04..abdd7f2 100644 --- a/src/wuttjamaican/db/model/auth.py +++ b/src/wuttjamaican/db/model/auth.py @@ -48,7 +48,7 @@ from sqlalchemy.ext.associationproxy import association_proxy from . import Base, uuid_column, uuid_fk_column -class Role(Base): +class Role(Base): # pylint: disable=too-few-public-methods """ Represents an authentication role within the system; used for permission management. @@ -120,7 +120,7 @@ class Role(Base): return self.name or "" -class Permission(Base): +class Permission(Base): # pylint: disable=too-few-public-methods """ Represents a permission granted to a role. """ @@ -145,7 +145,7 @@ class Permission(Base): return self.permission or "" -class User(Base): +class User(Base): # pylint: disable=too-few-public-methods """ Represents a user of the system. @@ -231,7 +231,7 @@ class User(Base): return self.username or "" -class UserRole(Base): +class UserRole(Base): # pylint: disable=too-few-public-methods """ Represents the association between a user and a role; i.e. the user "belongs" or "is assigned" to the role. @@ -260,7 +260,7 @@ class UserRole(Base): """) -class UserAPIToken(Base): +class UserAPIToken(Base): # pylint: disable=too-few-public-methods """ User authentication token for use with HTTP API """ diff --git a/src/wuttjamaican/db/model/base.py b/src/wuttjamaican/db/model/base.py index 9dc49ae..b2858ff 100644 --- a/src/wuttjamaican/db/model/base.py +++ b/src/wuttjamaican/db/model/base.py @@ -39,7 +39,7 @@ from sqlalchemy.ext.associationproxy import association_proxy from wuttjamaican.db.util import naming_convention, ModelBase, uuid_column -class WuttaModelBase(ModelBase): +class WuttaModelBase(ModelBase): # pylint: disable=too-few-public-methods """ Base class for data models, from which :class:`Base` inherits. @@ -123,7 +123,7 @@ metadata = sa.MetaData(naming_convention=naming_convention) Base = orm.declarative_base(metadata=metadata, cls=WuttaModelBase) -class Setting(Base): +class Setting(Base): # pylint: disable=too-few-public-methods """ Represents a :term:`config setting`. """ diff --git a/src/wuttjamaican/db/model/batch.py b/src/wuttjamaican/db/model/batch.py index e253e84..a922354 100644 --- a/src/wuttjamaican/db/model/batch.py +++ b/src/wuttjamaican/db/model/batch.py @@ -266,7 +266,7 @@ class BatchMixin: return None -class BatchRowMixin: +class BatchRowMixin: # pylint: disable=too-few-public-methods """ Mixin base class for :term:`data models ` which represent a :term:`batch row`. diff --git a/src/wuttjamaican/db/model/upgrades.py b/src/wuttjamaican/db/model/upgrades.py index 8e94abd..bc5f54c 100644 --- a/src/wuttjamaican/db/model/upgrades.py +++ b/src/wuttjamaican/db/model/upgrades.py @@ -35,7 +35,7 @@ from wuttjamaican.db.util import UUID from wuttjamaican.util import make_true_uuid -class Upgrade(Base): +class Upgrade(Base): # pylint: disable=too-few-public-methods """ Represents an app upgrade. """ diff --git a/src/wuttjamaican/email.py b/src/wuttjamaican/email.py index 14c5c87..389d580 100644 --- a/src/wuttjamaican/email.py +++ b/src/wuttjamaican/email.py @@ -41,7 +41,7 @@ from wuttjamaican.util import resource_path log = logging.getLogger(__name__) -class EmailSetting: +class EmailSetting: # pylint: disable=too-few-public-methods """ Base class for all :term:`email settings `. From 3deab0b747c8b699e39f31020278f35f15b433b3 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Sat, 30 Aug 2025 18:52:52 -0500 Subject: [PATCH 03/26] fix: fix 'bare-except' for pylint --- .pylintrc | 1 + src/wuttjamaican/util.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.pylintrc b/.pylintrc index dbdf127..5b05e20 100644 --- a/.pylintrc +++ b/.pylintrc @@ -3,6 +3,7 @@ [MESSAGES CONTROL] disable=all enable=anomalous-backslash-in-string, + bare-except, dangerous-default-value, inconsistent-return-statements, invalid-name, diff --git a/src/wuttjamaican/util.py b/src/wuttjamaican/util.py index 843a87c..6d8c437 100644 --- a/src/wuttjamaican/util.py +++ b/src/wuttjamaican/util.py @@ -115,7 +115,7 @@ def load_entry_points(group, ignore_errors=False): for entry_point in eps: try: ep = entry_point.load() - except: + except Exception: if not ignore_errors: raise log.warning("failed to load entry point: %s", entry_point, From 1a0fee358286736d964dcfa20c005c6960734610 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Sat, 30 Aug 2025 18:54:30 -0500 Subject: [PATCH 04/26] fix: fix 'broad-exception-caught' for pylint --- .pylintrc | 1 + src/wuttjamaican/install.py | 2 +- src/wuttjamaican/util.py | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.pylintrc b/.pylintrc index 5b05e20..4be7c31 100644 --- a/.pylintrc +++ b/.pylintrc @@ -4,6 +4,7 @@ disable=all enable=anomalous-backslash-in-string, bare-except, + broad-exception-caught, dangerous-default-value, inconsistent-return-statements, invalid-name, diff --git a/src/wuttjamaican/install.py b/src/wuttjamaican/install.py index 28035f1..231ea3b 100644 --- a/src/wuttjamaican/install.py +++ b/src/wuttjamaican/install.py @@ -252,7 +252,7 @@ class InstallHandler(GenericHandler): # just need to test interaction and this is a neutral way try: sa.inspect(engine).has_table('whatever') - except Exception as error: + except Exception as error: # pylint: disable=broad-exception-caught return str(error) return None diff --git a/src/wuttjamaican/util.py b/src/wuttjamaican/util.py index 6d8c437..6897fe1 100644 --- a/src/wuttjamaican/util.py +++ b/src/wuttjamaican/util.py @@ -115,7 +115,7 @@ def load_entry_points(group, ignore_errors=False): for entry_point in eps: try: ep = entry_point.load() - except Exception: + except Exception: # pylint: disable=broad-exception-caught if not ignore_errors: raise log.warning("failed to load entry point: %s", entry_point, From 74c3db6e3a1215cabf4ed72056ccf0fbb52b8c96 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Sat, 30 Aug 2025 18:56:04 -0500 Subject: [PATCH 05/26] fix: fix 'trailing-whitespace' for pylint --- .pylintrc | 1 + src/wuttjamaican/progress.py | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.pylintrc b/.pylintrc index 4be7c31..c1e63e1 100644 --- a/.pylintrc +++ b/.pylintrc @@ -10,6 +10,7 @@ enable=anomalous-backslash-in-string, invalid-name, redefined-argument-from-local, too-few-public-methods, + trailing-whitespace, unspecified-encoding, unused-argument, unused-import, diff --git a/src/wuttjamaican/progress.py b/src/wuttjamaican/progress.py index 712675c..31c862d 100644 --- a/src/wuttjamaican/progress.py +++ b/src/wuttjamaican/progress.py @@ -2,7 +2,7 @@ ################################################################################ # # WuttJamaican -- Base package for Wutta Framework -# Copyright © 2023-2024 Lance Edgar +# Copyright © 2023-2025 Lance Edgar # # This file is part of Wutta Framework. # @@ -97,7 +97,7 @@ class ConsoleProgress(ProgressBase): def __init__(self, *args, **kwargs): super().__init__(*args) - + self.stderr = kwargs.get('stderr', sys.stderr) self.stderr.write(f"\n{self.message}...\n") From 3010c5f435fb31910fa89a6128c308c35082fd9d Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Sat, 30 Aug 2025 18:57:27 -0500 Subject: [PATCH 06/26] fix: fix 'disallowed-name' for pylint --- .pylintrc | 1 + src/wuttjamaican/progress.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.pylintrc b/.pylintrc index c1e63e1..5b6d959 100644 --- a/.pylintrc +++ b/.pylintrc @@ -6,6 +6,7 @@ enable=anomalous-backslash-in-string, bare-except, broad-exception-caught, dangerous-default-value, + disallowed-name, inconsistent-return-statements, invalid-name, redefined-argument-from-local, diff --git a/src/wuttjamaican/progress.py b/src/wuttjamaican/progress.py index 31c862d..5eaa212 100644 --- a/src/wuttjamaican/progress.py +++ b/src/wuttjamaican/progress.py @@ -101,7 +101,7 @@ class ConsoleProgress(ProgressBase): self.stderr = kwargs.get('stderr', sys.stderr) self.stderr.write(f"\n{self.message}...\n") - self.bar = Bar(message='', max=self.maximum, width=70, + self.bar = Bar(message='', max=self.maximum, width=70, # pylint: disable=disallowed-name suffix='%(index)d/%(max)d %(percent)d%% ETA %(eta)ds') def update(self, value): From 99e6b98627ed9e1ac72b1f5556bed09bda88eb95 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Sat, 30 Aug 2025 19:03:22 -0500 Subject: [PATCH 07/26] fix: fix 'empty-docstring' for pylint --- .pylintrc | 1 + src/wuttjamaican/db/handler.py | 4 ++-- src/wuttjamaican/db/util.py | 10 +++++----- src/wuttjamaican/email.py | 6 +++--- src/wuttjamaican/progress.py | 4 ++-- src/wuttjamaican/testing.py | 22 +++++++++++----------- 6 files changed, 24 insertions(+), 23 deletions(-) diff --git a/.pylintrc b/.pylintrc index 5b6d959..7a637fb 100644 --- a/.pylintrc +++ b/.pylintrc @@ -7,6 +7,7 @@ enable=anomalous-backslash-in-string, broad-exception-caught, dangerous-default-value, disallowed-name, + empty-docstring, inconsistent-return-statements, invalid-name, redefined-argument-from-local, diff --git a/src/wuttjamaican/db/handler.py b/src/wuttjamaican/db/handler.py index 849f954..5d8d8af 100644 --- a/src/wuttjamaican/db/handler.py +++ b/src/wuttjamaican/db/handler.py @@ -2,7 +2,7 @@ ################################################################################ # # WuttJamaican -- Base package for Wutta Framework -# Copyright © 2024 Lance Edgar +# Copyright © 2024-2025 Lance Edgar # # This file is part of Wutta Framework. # @@ -34,7 +34,7 @@ class DatabaseHandler(GenericHandler): Base class and default implementation for the :term:`db handler`. """ - def get_dialect(self, bind): + def get_dialect(self, bind): # pylint: disable=empty-docstring """ """ return bind.url.get_dialect().name diff --git a/src/wuttjamaican/db/util.py b/src/wuttjamaican/db/util.py index 70be40a..aa99c93 100644 --- a/src/wuttjamaican/db/util.py +++ b/src/wuttjamaican/db/util.py @@ -51,7 +51,7 @@ if Version(version('SQLAlchemy')) < Version('2'): # pragma: no cover SA2 = False -class ModelBase: +class ModelBase: # pylint: disable=empty-docstring """ """ def __iter__(self): @@ -82,16 +82,16 @@ class UUID(sa.types.TypeDecorator): """ impl = sa.CHAR cache_ok = True - """ """ # nb. suppress sphinx autodoc for cache_ok + """ """ # nb. suppress sphinx autodoc for cache_ok - def load_dialect_impl(self, dialect): + def load_dialect_impl(self, dialect): # pylint: disable=empty-docstring """ """ if dialect.name == "postgresql": return dialect.type_descriptor(PGUUID()) else: return dialect.type_descriptor(sa.CHAR(32)) - def process_bind_param(self, value, dialect): + def process_bind_param(self, value, dialect): # pylint: disable=empty-docstring """ """ if value is None: return value @@ -104,7 +104,7 @@ class UUID(sa.types.TypeDecorator): # hexstring return "%.32x" % value.int - def process_result_value(self, value, dialect): # pylint: disable=unused-argument + def process_result_value(self, value, dialect): # pylint: disable=unused-argument,empty-docstring """ """ if value is None: return value diff --git a/src/wuttjamaican/email.py b/src/wuttjamaican/email.py index 389d580..227a38d 100644 --- a/src/wuttjamaican/email.py +++ b/src/wuttjamaican/email.py @@ -196,7 +196,7 @@ class Message: self.html_body = html_body self.attachments = attachments or [] - def set_recips(self, name, value): + def set_recips(self, name, value): # pylint: disable=empty-docstring """ """ if value: if isinstance(value, str): @@ -549,7 +549,7 @@ class EmailHandler(GenericHandler): """ return self.get_auto_recips(key, 'bcc') - def get_auto_recips(self, key, typ): + def get_auto_recips(self, key, typ): # pylint: disable=empty-docstring """ """ typ = typ.lower() if typ not in ('to', 'cc', 'bcc'): @@ -589,7 +589,7 @@ class EmailHandler(GenericHandler): return template.render(**context) return None - def get_auto_body_template(self, key, mode): + def get_auto_body_template(self, key, mode): # pylint: disable=empty-docstring """ """ mode = mode.lower() if mode not in ('txt', 'html'): diff --git a/src/wuttjamaican/progress.py b/src/wuttjamaican/progress.py index 5eaa212..00d718a 100644 --- a/src/wuttjamaican/progress.py +++ b/src/wuttjamaican/progress.py @@ -104,10 +104,10 @@ class ConsoleProgress(ProgressBase): self.bar = Bar(message='', max=self.maximum, width=70, # pylint: disable=disallowed-name suffix='%(index)d/%(max)d %(percent)d%% ETA %(eta)ds') - def update(self, value): + def update(self, value): # pylint: disable=empty-docstring """ """ self.bar.next() - def finish(self): + def finish(self): # pylint: disable=empty-docstring """ """ self.bar.finish() diff --git a/src/wuttjamaican/testing.py b/src/wuttjamaican/testing.py index f566d91..dcdfe2e 100644 --- a/src/wuttjamaican/testing.py +++ b/src/wuttjamaican/testing.py @@ -53,7 +53,7 @@ class FileTestCase(TestCase): class. """ - def setUp(self): + def setUp(self): # pylint: disable=empty-docstring """ """ self.setup_files() @@ -63,14 +63,14 @@ class FileTestCase(TestCase): """ self.tempdir = tempfile.mkdtemp() - def setup_file_config(self): # pragma: no cover + def setup_file_config(self): # pragma: no cover; pylint: disable=empty-docstring """ """ warnings.warn("FileTestCase.setup_file_config() is deprecated; " "please use setup_files() instead", DeprecationWarning, stacklevel=2) self.setup_files() - def tearDown(self): + def tearDown(self): # pylint: disable=empty-docstring """ """ self.teardown_files() @@ -80,7 +80,7 @@ class FileTestCase(TestCase): """ shutil.rmtree(self.tempdir) - def teardown_file_config(self): # pragma: no cover + def teardown_file_config(self): # pragma: no cover; pylint: disable=empty-docstring """ """ warnings.warn("FileTestCase.teardown_file_config() is deprecated; " "please use teardown_files() instead", @@ -99,7 +99,7 @@ class FileTestCase(TestCase): f.write(content) return path - def mkdir(self, dirname): # pylint: disable=unused-argument + def mkdir(self, dirname): # pylint: disable=unused-argument,empty-docstring """ """ warnings.warn("FileTestCase.mkdir() is deprecated; " "please use FileTestCase.mkdtemp() instead", @@ -143,7 +143,7 @@ class ConfigTestCase(FileTestCase): methods for this class. """ - def setUp(self): + def setUp(self): # pylint: disable=empty-docstring """ """ self.setup_config() @@ -155,7 +155,7 @@ class ConfigTestCase(FileTestCase): self.config = self.make_config() self.app = self.config.get_app() - def tearDown(self): + def tearDown(self): # pylint: disable=empty-docstring """ """ self.teardown_config() @@ -165,7 +165,7 @@ class ConfigTestCase(FileTestCase): """ self.teardown_files() - def make_config(self, **kwargs): + def make_config(self, **kwargs): # pylint: disable=empty-docstring """ """ return WuttaConfig(**kwargs) @@ -203,7 +203,7 @@ class DataTestCase(FileTestCase): teardown methods, as this class handles that automatically. """ - def setUp(self): + def setUp(self): # pylint: disable=empty-docstring """ """ self.setup_db() @@ -222,7 +222,7 @@ class DataTestCase(FileTestCase): model.Base.metadata.create_all(bind=self.config.appdb_engine) self.session = self.app.make_session() - def tearDown(self): + def tearDown(self): # pylint: disable=empty-docstring """ """ self.teardown_db() @@ -232,6 +232,6 @@ class DataTestCase(FileTestCase): """ self.teardown_files() - def make_config(self, **kwargs): + def make_config(self, **kwargs): # pylint: disable=empty-docstring """ """ return WuttaConfig(**kwargs) From 3a263d272c39598ac1d60cf5630c2a19fa68d1e4 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Sat, 30 Aug 2025 19:05:40 -0500 Subject: [PATCH 08/26] fix: fix 'assignment-from-no-return' for pylint --- .pylintrc | 1 + src/wuttjamaican/batch.py | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.pylintrc b/.pylintrc index 7a637fb..782030d 100644 --- a/.pylintrc +++ b/.pylintrc @@ -3,6 +3,7 @@ [MESSAGES CONTROL] disable=all enable=anomalous-backslash-in-string, + assignment-from-no-return, bare-except, broad-exception-caught, dangerous-default-value, diff --git a/src/wuttjamaican/batch.py b/src/wuttjamaican/batch.py index 653df8b..d263360 100644 --- a/src/wuttjamaican/batch.py +++ b/src/wuttjamaican/batch.py @@ -348,7 +348,7 @@ class BatchHandler(GenericHandler): * :attr:`~wuttjamaican.db.model.batch.BatchMixin.status_text` """ - def why_not_execute(self, batch, user=None, **kwargs): + def why_not_execute(self, batch, user=None, **kwargs): # pylint: disable=unused-argument """ Returns text indicating the reason (if any) that a given batch should *not* be executed. @@ -385,6 +385,7 @@ class BatchHandler(GenericHandler): raise a ``RuntimeError`` if text was returned. This is done out of safety, to avoid relying on the user interface. """ + return None def describe_execution(self, batch, user=None, **kwargs): """ @@ -476,7 +477,7 @@ class BatchHandler(GenericHandler): batch.executed_by = user return result - def execute(self, batch, user=None, progress=None, **kwargs): + def execute(self, batch, user=None, progress=None, **kwargs): # pylint: disable=unused-argument """ Execute the given batch. @@ -502,6 +503,7 @@ class BatchHandler(GenericHandler): whatever it likes, in which case that will be also returned to the caller from :meth:`do_execute()`. """ + return None def do_delete(self, batch, user, dry_run=False, progress=None, **kwargs): # pylint: disable=unused-argument """ From 6ac1cacdb32e4f11aeb29800026d37a1250abf5a Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Sat, 30 Aug 2025 19:07:41 -0500 Subject: [PATCH 09/26] fix: fix 'assignment-from-none' for pylint --- .pylintrc | 1 + src/wuttjamaican/batch.py | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.pylintrc b/.pylintrc index 782030d..57b6b0d 100644 --- a/.pylintrc +++ b/.pylintrc @@ -4,6 +4,7 @@ disable=all enable=anomalous-backslash-in-string, assignment-from-no-return, + assignment-from-none, bare-except, broad-exception-caught, dangerous-default-value, diff --git a/src/wuttjamaican/batch.py b/src/wuttjamaican/batch.py index d263360..d87d70e 100644 --- a/src/wuttjamaican/batch.py +++ b/src/wuttjamaican/batch.py @@ -468,11 +468,11 @@ class BatchHandler(GenericHandler): if batch.executed: raise ValueError(f"batch has already been executed: {batch}") - reason = self.why_not_execute(batch, user=user, **kwargs) + reason = self.why_not_execute(batch, user=user, **kwargs) # pylint: disable=assignment-from-none if reason: raise RuntimeError(f"batch execution not allowed: {reason}") - result = self.execute(batch, user=user, progress=progress, **kwargs) + result = self.execute(batch, user=user, progress=progress, **kwargs) # pylint: disable=assignment-from-none batch.executed = datetime.datetime.now() batch.executed_by = user return result From e845c66d86ed16af4deb0ad2cdf5d7a3275ef356 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Sat, 30 Aug 2025 19:11:01 -0500 Subject: [PATCH 10/26] fix: fix 'no-else-return' for pylint --- .pylintrc | 1 + src/wuttjamaican/db/util.py | 25 ++++++++++++------------- src/wuttjamaican/install.py | 4 ++-- src/wuttjamaican/people.py | 2 +- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/.pylintrc b/.pylintrc index 57b6b0d..4cc6ce1 100644 --- a/.pylintrc +++ b/.pylintrc @@ -12,6 +12,7 @@ enable=anomalous-backslash-in-string, empty-docstring, inconsistent-return-statements, invalid-name, + no-else-return, redefined-argument-from-local, too-few-public-methods, trailing-whitespace, diff --git a/src/wuttjamaican/db/util.py b/src/wuttjamaican/db/util.py index aa99c93..bf1f117 100644 --- a/src/wuttjamaican/db/util.py +++ b/src/wuttjamaican/db/util.py @@ -88,30 +88,29 @@ class UUID(sa.types.TypeDecorator): """ """ if dialect.name == "postgresql": return dialect.type_descriptor(PGUUID()) - else: - return dialect.type_descriptor(sa.CHAR(32)) + return dialect.type_descriptor(sa.CHAR(32)) def process_bind_param(self, value, dialect): # pylint: disable=empty-docstring """ """ if value is None: return value - elif dialect.name == "postgresql": + + if dialect.name == "postgresql": return str(value) - else: - if not isinstance(value, _uuid.UUID): - return "%.32x" % _uuid.UUID(value).int - else: - # hexstring - return "%.32x" % value.int + + if not isinstance(value, _uuid.UUID): + return "%.32x" % _uuid.UUID(value).int + + # hexstring + return "%.32x" % value.int def process_result_value(self, value, dialect): # pylint: disable=unused-argument,empty-docstring """ """ if value is None: return value - else: - if not isinstance(value, _uuid.UUID): - value = _uuid.UUID(value) - return value + if not isinstance(value, _uuid.UUID): + value = _uuid.UUID(value) + return value def uuid_column(*args, **kwargs): diff --git a/src/wuttjamaican/install.py b/src/wuttjamaican/install.py index 231ea3b..9a59413 100644 --- a/src/wuttjamaican/install.py +++ b/src/wuttjamaican/install.py @@ -558,9 +558,9 @@ class InstallHandler(GenericHandler): if is_bool: if text == '': return default - elif text.upper() == 'Y': + if text.upper() == 'Y': return True - elif text.upper() == 'N': + if text.upper() == 'N': return False self.rprint("\n\t[bold yellow]ambiguous, please try again[/bold yellow]\n") return self.prompt_generic(info, default, is_bool=True) diff --git a/src/wuttjamaican/people.py b/src/wuttjamaican/people.py index 3f51240..9513b1b 100644 --- a/src/wuttjamaican/people.py +++ b/src/wuttjamaican/people.py @@ -84,7 +84,7 @@ class PeopleHandler(GenericHandler): person = obj return person - elif isinstance(obj, model.User): + if isinstance(obj, model.User): user = obj if user.person: return user.person From 1f4f613b623ebc535ac50f3017518956702f8a3e Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Sat, 30 Aug 2025 19:12:54 -0500 Subject: [PATCH 11/26] fix: fix 'wrong-import-order' for pylint --- .pylintrc | 1 + src/wuttjamaican/db/model/upgrades.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.pylintrc b/.pylintrc index 4cc6ce1..6faf62c 100644 --- a/.pylintrc +++ b/.pylintrc @@ -19,3 +19,4 @@ enable=anomalous-backslash-in-string, unspecified-encoding, unused-argument, unused-import, + wrong-import-order, diff --git a/src/wuttjamaican/db/model/upgrades.py b/src/wuttjamaican/db/model/upgrades.py index bc5f54c..eef9d0d 100644 --- a/src/wuttjamaican/db/model/upgrades.py +++ b/src/wuttjamaican/db/model/upgrades.py @@ -29,10 +29,10 @@ import datetime import sqlalchemy as sa from sqlalchemy import orm -from . import Base, uuid_column, uuid_fk_column from wuttjamaican.enum import UpgradeStatus from wuttjamaican.db.util import UUID from wuttjamaican.util import make_true_uuid +from . import Base, uuid_column, uuid_fk_column class Upgrade(Base): # pylint: disable=too-few-public-methods From 2969f3b7a5bf333cef2ff498bbbfa2ca97f05673 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Sat, 30 Aug 2025 19:29:52 -0500 Subject: [PATCH 12/26] fix: fix 'consider-using-f-string' for pylint --- .pylintrc | 1 + src/wuttjamaican/db/util.py | 4 ++-- src/wuttjamaican/install.py | 11 +++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.pylintrc b/.pylintrc index 6faf62c..9b337d7 100644 --- a/.pylintrc +++ b/.pylintrc @@ -7,6 +7,7 @@ enable=anomalous-backslash-in-string, assignment-from-none, bare-except, broad-exception-caught, + consider-using-f-string, dangerous-default-value, disallowed-name, empty-docstring, diff --git a/src/wuttjamaican/db/util.py b/src/wuttjamaican/db/util.py index bf1f117..afc29b1 100644 --- a/src/wuttjamaican/db/util.py +++ b/src/wuttjamaican/db/util.py @@ -99,10 +99,10 @@ class UUID(sa.types.TypeDecorator): return str(value) if not isinstance(value, _uuid.UUID): - return "%.32x" % _uuid.UUID(value).int + value = _uuid.UUID(value) # hexstring - return "%.32x" % value.int + return f"{value.int:032x}" def process_result_value(self, value, dialect): # pylint: disable=unused-argument,empty-docstring """ """ diff --git a/src/wuttjamaican/install.py b/src/wuttjamaican/install.py index 9a59413..5ac007e 100644 --- a/src/wuttjamaican/install.py +++ b/src/wuttjamaican/install.py @@ -141,7 +141,7 @@ class InstallHandler(GenericHandler): This is normally called by :meth:`run()`. """ - self.rprint("\n\t[blue]Welcome to {}![/blue]".format(self.app.get_title())) + self.rprint(f"\n\t[blue]Welcome to {self.app.get_title()}![/blue]") self.rprint("\n\tThis tool will install and configure the app.") self.rprint("\n\t[italic]NB. You should already have created the database in PostgreSQL or MySQL.[/italic]") @@ -221,7 +221,7 @@ class InstallHandler(GenericHandler): error = self.test_db_connection(dbinfo['dburl']) if error: self.rprint("[bold red]cannot connect![/bold red] ..error was:") - self.rprint("\n{}".format(error)) + self.rprint(f"\n{error}") self.rprint("\n\t[bold yellow]aborting mission[/bold yellow]\n") sys.exit(1) self.rprint("[bold green]good[/bold green]") @@ -446,8 +446,7 @@ class InstallHandler(GenericHandler): 'upgrade', 'heads'] subprocess.check_call(cmd) - self.rprint("\n\tdb schema installed to: [bold green]{}[/bold green]".format( - obfuscate_url_pw(db_url))) + self.rprint(f"\n\tdb schema installed to: [bold green]{obfuscate_url_pw(db_url)}[/bold green]") return True def show_goodbye(self): @@ -540,9 +539,9 @@ class InstallHandler(GenericHandler): ] if default is not None: if is_bool: - message.append(('', ' [{}]: '.format('Y' if default else 'N'))) + message.append(('', f' [{"Y" if default else "N"}]: ')) else: - message.append(('', ' [{}]: '.format(default))) + message.append(('', f' [{default}]: ')) else: message.append(('', ': ')) From ab01f552e8c113a1b51fba460be61f3a707b7c2e Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Sat, 30 Aug 2025 19:34:10 -0500 Subject: [PATCH 13/26] fix: fix 'cyclic-import' for pylint --- .pylintrc | 1 + src/wuttjamaican/db/model/auth.py | 3 ++- src/wuttjamaican/db/model/batch.py | 3 ++- src/wuttjamaican/db/model/upgrades.py | 4 ++-- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.pylintrc b/.pylintrc index 9b337d7..83c5663 100644 --- a/.pylintrc +++ b/.pylintrc @@ -8,6 +8,7 @@ enable=anomalous-backslash-in-string, bare-except, broad-exception-caught, consider-using-f-string, + cyclic-import, dangerous-default-value, disallowed-name, empty-docstring, diff --git a/src/wuttjamaican/db/model/auth.py b/src/wuttjamaican/db/model/auth.py index abdd7f2..5ba7bfe 100644 --- a/src/wuttjamaican/db/model/auth.py +++ b/src/wuttjamaican/db/model/auth.py @@ -45,7 +45,8 @@ import sqlalchemy as sa from sqlalchemy import orm from sqlalchemy.ext.associationproxy import association_proxy -from . import Base, uuid_column, uuid_fk_column +from wuttjamaican.db.util import uuid_column, uuid_fk_column +from wuttjamaican.db.model.base import Base class Role(Base): # pylint: disable=too-few-public-methods diff --git a/src/wuttjamaican/db/model/batch.py b/src/wuttjamaican/db/model/batch.py index a922354..017a549 100644 --- a/src/wuttjamaican/db/model/batch.py +++ b/src/wuttjamaican/db/model/batch.py @@ -31,7 +31,8 @@ from sqlalchemy import orm from sqlalchemy.ext.declarative import declared_attr from sqlalchemy.ext.orderinglist import ordering_list -from wuttjamaican.db.model import uuid_column, User +from wuttjamaican.db.model.base import uuid_column +from wuttjamaican.db.model.auth import User from wuttjamaican.db.util import UUID diff --git a/src/wuttjamaican/db/model/upgrades.py b/src/wuttjamaican/db/model/upgrades.py index eef9d0d..010e26e 100644 --- a/src/wuttjamaican/db/model/upgrades.py +++ b/src/wuttjamaican/db/model/upgrades.py @@ -30,9 +30,9 @@ import sqlalchemy as sa from sqlalchemy import orm from wuttjamaican.enum import UpgradeStatus -from wuttjamaican.db.util import UUID +from wuttjamaican.db.util import UUID, uuid_column, uuid_fk_column from wuttjamaican.util import make_true_uuid -from . import Base, uuid_column, uuid_fk_column +from wuttjamaican.db.model.base import Base class Upgrade(Base): # pylint: disable=too-few-public-methods From 7a0860363c9e5a9c57dda89d9b028aa19e5c4707 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Sat, 30 Aug 2025 19:38:57 -0500 Subject: [PATCH 14/26] fix: fix 'consider-using-set-comprehension' for pylint --- .pylintrc | 1 + src/wuttjamaican/problems.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.pylintrc b/.pylintrc index 83c5663..23d9777 100644 --- a/.pylintrc +++ b/.pylintrc @@ -8,6 +8,7 @@ enable=anomalous-backslash-in-string, bare-except, broad-exception-caught, consider-using-f-string, + consider-using-set-comprehension, cyclic-import, dangerous-default-value, disallowed-name, diff --git a/src/wuttjamaican/problems.py b/src/wuttjamaican/problems.py index b401ed9..3394c23 100644 --- a/src/wuttjamaican/problems.py +++ b/src/wuttjamaican/problems.py @@ -200,7 +200,7 @@ class ProblemHandler(GenericHandler): :returns: List of system keys. """ checks = self.get_all_problem_checks() - return sorted(set([check.system_key for check in checks])) + return sorted({check.system_key for check in checks}) def get_system_title(self, system_key): """ From da395e18809be54ef68685a43d010db67a96bbf3 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Sat, 30 Aug 2025 19:45:15 -0500 Subject: [PATCH 15/26] fix: fix 'consider-using-dict-comprehension' for pylint --- .pylintrc | 1 + src/wuttjamaican/db/util.py | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.pylintrc b/.pylintrc index 23d9777..f005265 100644 --- a/.pylintrc +++ b/.pylintrc @@ -8,6 +8,7 @@ enable=anomalous-backslash-in-string, bare-except, broad-exception-caught, consider-using-f-string, + consider-using-dict-comprehension, consider-using-set-comprehension, cyclic-import, dangerous-default-value, diff --git a/src/wuttjamaican/db/util.py b/src/wuttjamaican/db/util.py index afc29b1..0be74d4 100644 --- a/src/wuttjamaican/db/util.py +++ b/src/wuttjamaican/db/util.py @@ -149,8 +149,8 @@ def make_topo_sortkey(model): containing model classes. """ metadata = model.Base.metadata - tables = dict([(table.name, i) - for i, table in enumerate(metadata.sorted_tables, 1)]) + tables = {table.name: i + for i, table in enumerate(metadata.sorted_tables, 1)} def sortkey(name): cls = getattr(model, name) From f86aeff7880d2f0cdb115c8bed57eac24c827ec4 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Sat, 30 Aug 2025 20:11:10 -0500 Subject: [PATCH 16/26] fix: fix 'duplicate-code' for pylint --- .pylintrc | 1 + src/wuttjamaican/app.py | 33 +++++++++++++++++++++++++++++++++ src/wuttjamaican/email.py | 19 +++++-------------- src/wuttjamaican/reports.py | 20 +++++--------------- tests/test_app.py | 30 ++++++++++++++++++++++++++++++ 5 files changed, 74 insertions(+), 29 deletions(-) diff --git a/.pylintrc b/.pylintrc index f005265..1290b8b 100644 --- a/.pylintrc +++ b/.pylintrc @@ -13,6 +13,7 @@ enable=anomalous-backslash-in-string, cyclic-import, dangerous-default-value, disallowed-name, + duplicate-code, empty-docstring, inconsistent-return-statements, invalid-name, diff --git a/src/wuttjamaican/app.py b/src/wuttjamaican/app.py index 8b5f671..4e68a87 100644 --- a/src/wuttjamaican/app.py +++ b/src/wuttjamaican/app.py @@ -1123,6 +1123,7 @@ class GenericHandler: def __init__(self, config): self.config = config self.app = self.config.get_app() + self.modules = {} @property def appname(self): @@ -1139,3 +1140,35 @@ class GenericHandler: Returns the class :term:`spec` string for the handler. """ return f'{cls.__module__}:{cls.__name__}' + + def get_provider_modules(self, module_type): + """ + Returns a list of all available modules of the given type. + + Not all handlers would need such a thing, but notable ones + which do are the :term:`email handler` and :term:`report + handler`. Both can obtain classes (emails or reports) from + arbitrary modules, and this method is used to locate them. + + This will discover all modules exposed by the app + :term:`providers `, which expose an attribute with + name like ``f"{module_type}_modules"``. + + :param module_type: Unique name referring to a particular + "type" of modules to locate, e.g. ``'email'``. + + :returns: List of module objects. + """ + if module_type not in self.modules: + self.modules[module_type] = [] + for provider in self.app.providers.values(): + name = f'{module_type}_modules' + if hasattr(provider, name): + modules = getattr(provider, name) + if modules: + if isinstance(modules, str): + modules = [modules] + for modpath in modules: + module = importlib.import_module(modpath) + self.modules[module_type].append(module) + return self.modules[module_type] diff --git a/src/wuttjamaican/email.py b/src/wuttjamaican/email.py index 227a38d..43bc808 100644 --- a/src/wuttjamaican/email.py +++ b/src/wuttjamaican/email.py @@ -24,7 +24,6 @@ Email Handler """ -import importlib import logging import smtplib from email.mime.multipart import MIMEMultipart @@ -305,20 +304,12 @@ class EmailHandler(GenericHandler): This will discover all email modules exposed by the :term:`app`, and/or its :term:`providers `. - """ - if not hasattr(self, '_email_modules'): - self._email_modules = [] - for provider in self.app.providers.values(): - if hasattr(provider, 'email_modules'): - modules = provider.email_modules - if modules: - if isinstance(modules, str): - modules = [modules] - for module in modules: - module = importlib.import_module(module) - self._email_modules.append(module) - return self._email_modules + Calls + :meth:`~wuttjamaican.app.GenericHandler.get_provider_modules()` + under the hood, for ``email`` module type. + """ + return self.get_provider_modules('email') def get_email_settings(self): """ diff --git a/src/wuttjamaican/reports.py b/src/wuttjamaican/reports.py index 7a55a19..0f84f87 100644 --- a/src/wuttjamaican/reports.py +++ b/src/wuttjamaican/reports.py @@ -24,8 +24,6 @@ Report Utilities """ -import importlib - from wuttjamaican.app import GenericHandler @@ -143,20 +141,12 @@ class ReportHandler(GenericHandler): This will discover all report modules exposed by the :term:`app`, and/or its :term:`providers `. - """ - if not hasattr(self, '_report_modules'): - self._report_modules = [] - for provider in self.app.providers.values(): - if hasattr(provider, 'report_modules'): - modules = provider.report_modules - if modules: - if isinstance(modules, str): - modules = [modules] - for module in modules: - module = importlib.import_module(module) - self._report_modules.append(module) - return self._report_modules + Calls + :meth:`~wuttjamaican.app.GenericHandler.get_provider_modules()` + under the hood, for ``report`` module type. + """ + return self.get_provider_modules('report') def get_reports(self): """ diff --git a/tests/test_app.py b/tests/test_app.py index e05334d..e75b527 100644 --- a/tests/test_app.py +++ b/tests/test_app.py @@ -761,6 +761,9 @@ class TestGenericHandler(ConfigTestCase): kw.setdefault('appname', 'wuttatest') return super().make_config(**kw) + def make_handler(self, **kwargs): + return mod.GenericHandler(self.config, **kwargs) + def test_constructor(self): handler = mod.GenericHandler(self.config) self.assertIs(handler.config, self.config) @@ -769,3 +772,30 @@ class TestGenericHandler(ConfigTestCase): def test_get_spec(self): self.assertEqual(mod.GenericHandler.get_spec(), 'wuttjamaican.app:GenericHandler') + + def test_get_provider_modules(self): + + # no providers, no email modules + with patch.object(self.app, 'providers', new={}): + handler = self.make_handler() + self.assertEqual(handler.get_provider_modules('email'), []) + + # provider may specify modules as list + providers = { + 'wuttatest': MagicMock(email_modules=['wuttjamaican.app']), + } + with patch.object(self.app, 'providers', new=providers): + handler = self.make_handler() + modules = handler.get_provider_modules('email') + self.assertEqual(len(modules), 1) + self.assertIs(modules[0], mod) + + # provider may specify modules as string + providers = { + 'wuttatest': MagicMock(email_modules='wuttjamaican.app'), + } + with patch.object(self.app, 'providers', new=providers): + handler = self.make_handler() + modules = handler.get_provider_modules('email') + self.assertEqual(len(modules), 1) + self.assertIs(modules[0], mod) From baa291f289bb32cf3ab2f0d020bddd49e552198e Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Sat, 30 Aug 2025 20:15:03 -0500 Subject: [PATCH 17/26] fix: fix 'line-too-long' for pylint --- .pylintrc | 1 + src/wuttjamaican/cli/problems.py | 3 ++- src/wuttjamaican/db/model/auth.py | 10 +++++++--- src/wuttjamaican/install.py | 6 ++++-- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/.pylintrc b/.pylintrc index 1290b8b..642d985 100644 --- a/.pylintrc +++ b/.pylintrc @@ -17,6 +17,7 @@ enable=anomalous-backslash-in-string, empty-docstring, inconsistent-return-statements, invalid-name, + line-too-long, no-else-return, redefined-argument-from-local, too-few-public-methods, diff --git a/src/wuttjamaican/cli/problems.py b/src/wuttjamaican/cli/problems.py index 4135065..226b0fc 100644 --- a/src/wuttjamaican/cli/problems.py +++ b/src/wuttjamaican/cli/problems.py @@ -53,7 +53,8 @@ def problems( list_checks: Annotated[ bool, typer.Option('--list', '-l', - help="List available problem checks; optionally filtered per --system and --problem")] = False, + help="List available problem checks; optionally filtered " + "per --system and --problem")] = False, ): """ Find and report on problems with the data or system. diff --git a/src/wuttjamaican/db/model/auth.py b/src/wuttjamaican/db/model/auth.py index 5ba7bfe..8ff9fc5 100644 --- a/src/wuttjamaican/db/model/auth.py +++ b/src/wuttjamaican/db/model/auth.py @@ -286,9 +286,13 @@ class UserAPIToken(Base): # pylint: disable=too-few-public-methods Raw token string, to be used by API clients. """) - created = sa.Column(sa.DateTime(timezone=True), nullable=False, default=datetime.datetime.now, doc=""" - Date/time when the token was created. - """) + created = sa.Column( + sa.DateTime(timezone=True), + nullable=False, + default=datetime.datetime.now, + doc=""" + Date/time when the token was created. + """) def __str__(self): return self.description or "" diff --git a/src/wuttjamaican/install.py b/src/wuttjamaican/install.py index 5ac007e..0806b76 100644 --- a/src/wuttjamaican/install.py +++ b/src/wuttjamaican/install.py @@ -143,7 +143,8 @@ class InstallHandler(GenericHandler): """ self.rprint(f"\n\t[blue]Welcome to {self.app.get_title()}![/blue]") self.rprint("\n\tThis tool will install and configure the app.") - self.rprint("\n\t[italic]NB. You should already have created the database in PostgreSQL or MySQL.[/italic]") + self.rprint("\n\t[italic]NB. You should already have created " + "the database in PostgreSQL or MySQL.[/italic]") # shall we continue? if not self.prompt_bool("continue?", True): @@ -446,7 +447,8 @@ class InstallHandler(GenericHandler): 'upgrade', 'heads'] subprocess.check_call(cmd) - self.rprint(f"\n\tdb schema installed to: [bold green]{obfuscate_url_pw(db_url)}[/bold green]") + self.rprint("\n\tdb schema installed to: " + f"[bold green]{obfuscate_url_pw(db_url)}[/bold green]") return True def show_goodbye(self): From 967c7b5948094527407ef4699294f0d44500d82d Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Sat, 30 Aug 2025 20:19:26 -0500 Subject: [PATCH 18/26] fix: fix 'missing-function-docstring' for pylint --- .pylintrc | 1 + src/wuttjamaican/db/model/batch.py | 12 ++++++++---- src/wuttjamaican/install.py | 12 ++++++++---- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/.pylintrc b/.pylintrc index 642d985..bea7a43 100644 --- a/.pylintrc +++ b/.pylintrc @@ -18,6 +18,7 @@ enable=anomalous-backslash-in-string, inconsistent-return-statements, invalid-name, line-too-long, + missing-function-docstring, no-else-return, redefined-argument-from-local, too-few-public-methods, diff --git a/src/wuttjamaican/db/model/batch.py b/src/wuttjamaican/db/model/batch.py index 017a549..7bfa006 100644 --- a/src/wuttjamaican/db/model/batch.py +++ b/src/wuttjamaican/db/model/batch.py @@ -201,7 +201,8 @@ class BatchMixin: ) @declared_attr - def batch_type(cls): + def batch_type(cls): # pylint: disable=empty-docstring + """ """ return cls.__tablename__ uuid = uuid_column() @@ -227,7 +228,8 @@ class BatchMixin: created_by_uuid = sa.Column(UUID(), nullable=False) @declared_attr - def created_by(cls): + def created_by(cls): # pylint: disable=empty-docstring + """ """ return orm.relationship( User, primaryjoin=lambda: User.uuid == cls.created_by_uuid, @@ -239,7 +241,8 @@ class BatchMixin: executed_by_uuid = sa.Column(UUID(), nullable=True) @declared_attr - def executed_by(cls): + def executed_by(cls): # pylint: disable=empty-docstring + """ """ return orm.relationship( User, primaryjoin=lambda: User.uuid == cls.executed_by_uuid, @@ -395,7 +398,8 @@ class BatchRowMixin: # pylint: disable=too-few-public-methods batch_uuid = sa.Column(UUID(), nullable=False) @declared_attr - def batch(cls): + def batch(cls): # pylint: disable=empty-docstring + """ """ batch_class = cls.__batch_class__ row_class = cls batch_class.__row_class__ = row_class diff --git a/src/wuttjamaican/install.py b/src/wuttjamaican/install.py index 0806b76..61be2d3 100644 --- a/src/wuttjamaican/install.py +++ b/src/wuttjamaican/install.py @@ -229,7 +229,8 @@ class InstallHandler(GenericHandler): return dbinfo - def make_db_url(self, dbtype, dbhost, dbport, dbname, dbuser, dbpass): + def make_db_url(self, dbtype, dbhost, dbport, dbname, dbuser, dbpass): # pylint: disable=empty-docstring + """ """ from sqlalchemy.engine import URL if dbtype == 'mysql': @@ -244,7 +245,8 @@ class InstallHandler(GenericHandler): port=dbport, database=dbname) - def test_db_connection(self, url): + def test_db_connection(self, url): # pylint: disable=empty-docstring + """ """ import sqlalchemy as sa engine = sa.create_engine(url) @@ -470,7 +472,8 @@ class InstallHandler(GenericHandler): # console utility functions ############################## - def require_prompt_toolkit(self, answer=None): + def require_prompt_toolkit(self, answer=None): # pylint: disable=empty-docstring + """ """ try: import prompt_toolkit # pylint: disable=unused-import except ImportError: @@ -492,7 +495,8 @@ class InstallHandler(GenericHandler): """ rich.print(*args, **kwargs) - def get_prompt_style(self): + def get_prompt_style(self): # pylint: disable=empty-docstring + """ """ from prompt_toolkit.styles import Style # message formatting styles From f01f5911dad864872871c5dd850204944c65e33d Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Sat, 30 Aug 2025 20:20:33 -0500 Subject: [PATCH 19/26] fix: fix 'missing-module-docstring' for pylint --- .pylintrc | 1 + src/wuttjamaican/_version.py | 3 +++ 2 files changed, 4 insertions(+) diff --git a/.pylintrc b/.pylintrc index bea7a43..d8faf70 100644 --- a/.pylintrc +++ b/.pylintrc @@ -19,6 +19,7 @@ enable=anomalous-backslash-in-string, invalid-name, line-too-long, missing-function-docstring, + missing-module-docstring, no-else-return, redefined-argument-from-local, too-few-public-methods, diff --git a/src/wuttjamaican/_version.py b/src/wuttjamaican/_version.py index 9cd05c1..6a6bb9c 100644 --- a/src/wuttjamaican/_version.py +++ b/src/wuttjamaican/_version.py @@ -1,4 +1,7 @@ # -*- coding: utf-8; -*- +""" +Package Version +""" from importlib.metadata import version From da149e932d0914ab499e9be3dc5d8ef562e3e9d6 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Sat, 30 Aug 2025 20:23:08 -0500 Subject: [PATCH 20/26] fix: fix 'no-self-argument' for pylint --- .pylintrc | 1 + src/wuttjamaican/db/model/batch.py | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.pylintrc b/.pylintrc index d8faf70..184da3d 100644 --- a/.pylintrc +++ b/.pylintrc @@ -21,6 +21,7 @@ enable=anomalous-backslash-in-string, missing-function-docstring, missing-module-docstring, no-else-return, + no-self-argument, redefined-argument-from-local, too-few-public-methods, trailing-whitespace, diff --git a/src/wuttjamaican/db/model/batch.py b/src/wuttjamaican/db/model/batch.py index 7bfa006..0a24c8d 100644 --- a/src/wuttjamaican/db/model/batch.py +++ b/src/wuttjamaican/db/model/batch.py @@ -186,7 +186,7 @@ class BatchMixin: """ @declared_attr - def __table_args__(cls): + def __table_args__(cls): # pylint: disable=no-self-argument return cls.__default_table_args__() @classmethod @@ -201,7 +201,7 @@ class BatchMixin: ) @declared_attr - def batch_type(cls): # pylint: disable=empty-docstring + def batch_type(cls): # pylint: disable=empty-docstring,no-self-argument """ """ return cls.__tablename__ @@ -228,7 +228,7 @@ class BatchMixin: created_by_uuid = sa.Column(UUID(), nullable=False) @declared_attr - def created_by(cls): # pylint: disable=empty-docstring + def created_by(cls): # pylint: disable=empty-docstring,no-self-argument """ """ return orm.relationship( User, @@ -241,7 +241,7 @@ class BatchMixin: executed_by_uuid = sa.Column(UUID(), nullable=True) @declared_attr - def executed_by(cls): # pylint: disable=empty-docstring + def executed_by(cls): # pylint: disable=empty-docstring,no-self-argument """ """ return orm.relationship( User, @@ -381,7 +381,7 @@ class BatchRowMixin: # pylint: disable=too-few-public-methods uuid = uuid_column() @declared_attr - def __table_args__(cls): + def __table_args__(cls): # pylint: disable=no-self-argument return cls.__default_table_args__() @classmethod @@ -398,7 +398,7 @@ class BatchRowMixin: # pylint: disable=too-few-public-methods batch_uuid = sa.Column(UUID(), nullable=False) @declared_attr - def batch(cls): # pylint: disable=empty-docstring + def batch(cls): # pylint: disable=empty-docstring,no-self-argument """ """ batch_class = cls.__batch_class__ row_class = cls From a47dfbad010285c2f329eb47cbc3c610f36f0696 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Sat, 30 Aug 2025 20:25:05 -0500 Subject: [PATCH 21/26] fix: fix 'possibly-used-before-assignment' for pylint --- .pylintrc | 1 + src/wuttjamaican/email.py | 5 ++--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.pylintrc b/.pylintrc index 184da3d..78a42e4 100644 --- a/.pylintrc +++ b/.pylintrc @@ -22,6 +22,7 @@ enable=anomalous-backslash-in-string, missing-module-docstring, no-else-return, no-self-argument, + possibly-used-before-assignment, redefined-argument-from-local, too-few-public-methods, trailing-whitespace, diff --git a/src/wuttjamaican/email.py b/src/wuttjamaican/email.py index 43bc808..f5fce03 100644 --- a/src/wuttjamaican/email.py +++ b/src/wuttjamaican/email.py @@ -583,13 +583,12 @@ class EmailHandler(GenericHandler): def get_auto_body_template(self, key, mode): # pylint: disable=empty-docstring """ """ mode = mode.lower() - if mode not in ('txt', 'html'): - raise ValueError("requested mode not supported") - if mode == 'txt': templates = self.txt_templates elif mode == 'html': templates = self.html_templates + else: + raise ValueError("requested mode not supported") try: return templates.get_template(f'{key}.{mode}.mako') From 87af670df6815c3a499dac27bfd4e22c8a7da9bb Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Sat, 30 Aug 2025 20:26:55 -0500 Subject: [PATCH 22/26] fix: fix 'redefined-outer-name' for pylint --- .pylintrc | 1 + src/wuttjamaican/cli/problems.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.pylintrc b/.pylintrc index 78a42e4..486afbc 100644 --- a/.pylintrc +++ b/.pylintrc @@ -24,6 +24,7 @@ enable=anomalous-backslash-in-string, no-self-argument, possibly-used-before-assignment, redefined-argument-from-local, + redefined-outer-name, too-few-public-methods, trailing-whitespace, unspecified-encoding, diff --git a/src/wuttjamaican/cli/problems.py b/src/wuttjamaican/cli/problems.py index 226b0fc..0638fd1 100644 --- a/src/wuttjamaican/cli/problems.py +++ b/src/wuttjamaican/cli/problems.py @@ -44,7 +44,7 @@ def problems( help="System for which to perform checks; can be specified more " "than once. If not specified, all systems are assumed.")] = None, - problems: Annotated[ + problems: Annotated[ # pylint: disable=redefined-outer-name List[str], typer.Option('--problem', '-p', help="Identify a particular problem check; can be specified " From 79bab4f9e18e360dac48401685a68d4f4f31544e Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Sat, 30 Aug 2025 20:32:56 -0500 Subject: [PATCH 23/26] fix: fix 'no-member' for pylint --- .pylintrc | 1 + src/wuttjamaican/email.py | 10 +++++----- tests/test_email.py | 21 ++++++++++----------- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/.pylintrc b/.pylintrc index 486afbc..f1f7f26 100644 --- a/.pylintrc +++ b/.pylintrc @@ -22,6 +22,7 @@ enable=anomalous-backslash-in-string, missing-module-docstring, no-else-return, no-self-argument, + no-member, possibly-used-before-assignment, redefined-argument-from-local, redefined-outer-name, diff --git a/src/wuttjamaican/email.py b/src/wuttjamaican/email.py index f5fce03..77e702b 100644 --- a/src/wuttjamaican/email.py +++ b/src/wuttjamaican/email.py @@ -187,15 +187,15 @@ class Message: self.key = key self.sender = sender self.subject = subject - self.set_recips('to', to) - self.set_recips('cc', cc) - self.set_recips('bcc', bcc) + self.to = self.get_recips(to) + self.cc = self.get_recips(cc) + self.bcc = self.get_recips(bcc) self.replyto = replyto self.txt_body = txt_body self.html_body = html_body self.attachments = attachments or [] - def set_recips(self, name, value): # pylint: disable=empty-docstring + def get_recips(self, value): # pylint: disable=empty-docstring """ """ if value: if isinstance(value, str): @@ -204,7 +204,7 @@ class Message: raise ValueError("must specify a string, tuple or list value") else: value = [] - setattr(self, name, list(value)) + return list(value) def as_string(self): """ diff --git a/tests/test_email.py b/tests/test_email.py index 8cf1623..6e1a72d 100644 --- a/tests/test_email.py +++ b/tests/test_email.py @@ -30,28 +30,27 @@ class TestMessage(FileTestCase): def make_message(self, **kwargs): return mod.Message(**kwargs) - def test_set_recips(self): + def test_get_recips(self): msg = self.make_message() - self.assertEqual(msg.to, []) # set as list - msg.set_recips('to', ['sally@example.com']) - self.assertEqual(msg.to, ['sally@example.com']) + recips = msg.get_recips(['sally@example.com']) + self.assertEqual(recips, ['sally@example.com']) # set as tuple - msg.set_recips('to', ('barney@example.com',)) - self.assertEqual(msg.to, ['barney@example.com']) + recips = msg.get_recips(('barney@example.com',)) + self.assertEqual(recips, ['barney@example.com']) # set as string - msg.set_recips('to', 'wilma@example.com') - self.assertEqual(msg.to, ['wilma@example.com']) + recips = msg.get_recips('wilma@example.com') + self.assertEqual(recips, ['wilma@example.com']) # set as null - msg.set_recips('to', None) - self.assertEqual(msg.to, []) + recips = msg.get_recips(None) + self.assertEqual(recips, []) # otherwise error - self.assertRaises(ValueError, msg.set_recips, 'to', {'foo': 'foo@example.com'}) + self.assertRaises(ValueError, msg.get_recips, {'foo': 'foo@example.com'}) def test_as_string(self): From 9075159d0d0d4ba836975b3575763a2fc47a1c07 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Sat, 30 Aug 2025 20:34:37 -0500 Subject: [PATCH 24/26] fix: fix 'abstract-method' for pylint --- .pylintrc | 3 ++- src/wuttjamaican/db/util.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.pylintrc b/.pylintrc index f1f7f26..8dc9c98 100644 --- a/.pylintrc +++ b/.pylintrc @@ -2,7 +2,8 @@ [MESSAGES CONTROL] disable=all -enable=anomalous-backslash-in-string, +enable=abstract-method, + anomalous-backslash-in-string, assignment-from-no-return, assignment-from-none, bare-except, diff --git a/src/wuttjamaican/db/util.py b/src/wuttjamaican/db/util.py index 0be74d4..ee3947d 100644 --- a/src/wuttjamaican/db/util.py +++ b/src/wuttjamaican/db/util.py @@ -69,7 +69,7 @@ class ModelBase: # pylint: disable=empty-docstring raise KeyError(f"model instance has no attr with key: {key}") -class UUID(sa.types.TypeDecorator): +class UUID(sa.types.TypeDecorator): # pylint: disable=abstract-method """ Platform-independent UUID type. From faa12005fb0119c7e23bc498e7866f73113bb28e Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Sat, 30 Aug 2025 20:36:27 -0500 Subject: [PATCH 25/26] infra: explicitly disable checks for pylint finally tackled enough we can assume checks *should* run except for those we opt out of. and those can be cleaned up too hopefully but i'm out of gas for the moment --- .pylintrc | 43 +++++++++++-------------------------------- 1 file changed, 11 insertions(+), 32 deletions(-) diff --git a/.pylintrc b/.pylintrc index 8dc9c98..893bde4 100644 --- a/.pylintrc +++ b/.pylintrc @@ -1,35 +1,14 @@ # -*- mode: conf; -*- [MESSAGES CONTROL] -disable=all -enable=abstract-method, - anomalous-backslash-in-string, - assignment-from-no-return, - assignment-from-none, - bare-except, - broad-exception-caught, - consider-using-f-string, - consider-using-dict-comprehension, - consider-using-set-comprehension, - cyclic-import, - dangerous-default-value, - disallowed-name, - duplicate-code, - empty-docstring, - inconsistent-return-statements, - invalid-name, - line-too-long, - missing-function-docstring, - missing-module-docstring, - no-else-return, - no-self-argument, - no-member, - possibly-used-before-assignment, - redefined-argument-from-local, - redefined-outer-name, - too-few-public-methods, - trailing-whitespace, - unspecified-encoding, - unused-argument, - unused-import, - wrong-import-order, +disable= + attribute-defined-outside-init, + fixme, + import-outside-toplevel, + too-many-arguments, + too-many-branches, + too-many-instance-attributes, + too-many-lines, + too-many-locals, + too-many-positional-arguments, + too-many-public-methods, From f34678b30518201360fbeab9753a2bbae2e5dc59 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Sat, 30 Aug 2025 20:44:31 -0500 Subject: [PATCH 26/26] fix: more cleanup for pylint for some reason these weren't caught with local run but found some more issues running under tox --- pyproject.toml | 1 + src/wuttjamaican/db/util.py | 4 ++-- tox.ini | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 6e75b48..25fddc0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,6 +30,7 @@ dependencies = [ 'importlib-metadata; python_version < "3.10"', "importlib_resources ; python_version < '3.9'", "Mako", + "packaging", "progress", "python-configuration", "typer", diff --git a/src/wuttjamaican/db/util.py b/src/wuttjamaican/db/util.py index ee3947d..24e508f 100644 --- a/src/wuttjamaican/db/util.py +++ b/src/wuttjamaican/db/util.py @@ -26,8 +26,8 @@ Database Utilities import uuid as _uuid from importlib.metadata import version -from packaging.version import Version +from packaging.version import Version import sqlalchemy as sa from sqlalchemy import orm from sqlalchemy.dialects.postgresql import UUID as PGUUID @@ -69,7 +69,7 @@ class ModelBase: # pylint: disable=empty-docstring raise KeyError(f"model instance has no attr with key: {key}") -class UUID(sa.types.TypeDecorator): # pylint: disable=abstract-method +class UUID(sa.types.TypeDecorator): # pylint: disable=abstract-method,too-many-ancestors """ Platform-independent UUID type. diff --git a/tox.ini b/tox.ini index 2d8728a..4d28869 100644 --- a/tox.ini +++ b/tox.ini @@ -12,8 +12,9 @@ extras = tests [testenv:pylint] basepython = python3.11 -extras = +extras = db deps = pylint + prompt_toolkit commands = pylint wuttjamaican [testenv:coverage]