diff --git a/.pylintrc b/.pylintrc index e634a21..d917385 100644 --- a/.pylintrc +++ b/.pylintrc @@ -2,4 +2,8 @@ [MESSAGES CONTROL] disable=all -enable=dangerous-default-value +enable=dangerous-default-value, + inconsistent-return-statements, + redefined-argument-from-local, + unspecified-encoding, + unused-import, diff --git a/src/wuttjamaican/app.py b/src/wuttjamaican/app.py index c7d0e23..7047f43 100644 --- a/src/wuttjamaican/app.py +++ b/src/wuttjamaican/app.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. # @@ -24,7 +24,6 @@ WuttJamaican - app handler """ -import datetime import importlib import logging import os @@ -230,7 +229,7 @@ class AppHandler: If ``obj`` is *not* specified, this behaves a bit differently. It first will look for a :term:`config setting` named - ``wutta.app_dist`` (or similar, dpending on :attr:`appname`). + ``wutta.app_dist`` (or similar, depending on :attr:`appname`). If there is such a config value, it is returned. Otherwise the "auto-locate" logic described above happens, but using ``self`` instead of ``obj``. @@ -281,8 +280,7 @@ class AppHandler: return dist # fall back to configured dist, if obj lookup failed - if obj is not None: - return self.config.get(f'{self.appname}.app_dist') + return self.config.get(f'{self.appname}.app_dist') def get_version(self, dist=None, obj=None): """ @@ -302,6 +300,7 @@ class AppHandler: dist = self.get_distribution(obj=obj) if dist: return version(dist) + return None def get_model(self): """ @@ -464,7 +463,7 @@ class AppHandler: """ output = template.render(**context) if output_path: - with open(output_path, 'wt') as f: + with open(output_path, 'wt', encoding='utf_8') as f: f.write(output) return output diff --git a/src/wuttjamaican/auth.py b/src/wuttjamaican/auth.py index 0643cff..fa3054f 100644 --- a/src/wuttjamaican/auth.py +++ b/src/wuttjamaican/auth.py @@ -93,6 +93,7 @@ class AuthHandler(GenericHandler): if user and user.active and user.password: if self.check_user_password(user, password): return user + return None def authenticate_user_token(self, session, token): """ @@ -122,6 +123,7 @@ class AuthHandler(GenericHandler): user = token.user if user.active: return user + return None def check_user_password(self, user, password, **kwargs): """ @@ -158,7 +160,7 @@ class AuthHandler(GenericHandler): model = self.app.model if not key: - return + return None # maybe it is a uuid if isinstance(key, _uuid.UUID): @@ -188,6 +190,7 @@ class AuthHandler(GenericHandler): session=session) if key: return self.get_role(session, key) + return None def get_user(self, obj, session=None, **kwargs): """ @@ -256,6 +259,7 @@ class AuthHandler(GenericHandler): person = self.app.get_person(obj) if person: return person.user + return None def make_person(self, **kwargs): """ diff --git a/src/wuttjamaican/conf.py b/src/wuttjamaican/conf.py index 3eff415..103d2cc 100644 --- a/src/wuttjamaican/conf.py +++ b/src/wuttjamaican/conf.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. # @@ -25,7 +25,6 @@ WuttJamaican - app configuration """ import configparser -import importlib import logging import logging.config import os @@ -274,7 +273,7 @@ class WuttaConfig: # re-write as temp file with "final" values fd, temp_path = tempfile.mkstemp(suffix='.ini') os.close(fd) - with open(temp_path, 'wt') as f: + with open(temp_path, 'wt', encoding='utf_8') as f: temp_config.write(f) # and finally, load that into our main config @@ -286,14 +285,14 @@ class WuttaConfig: # bring in any "required" files requires = config.get(f'{self.appname}.config.require') if requires: - for path in self.parse_list(requires): - self._load_ini_configs(path, configs, require=True) + for p in self.parse_list(requires): + self._load_ini_configs(p, configs, require=True) # bring in any "included" files includes = config.get(f'{self.appname}.config.include') if includes: - for path in self.parse_list(includes): - self._load_ini_configs(path, configs, require=False) + for p in self.parse_list(includes): + self._load_ini_configs(p, configs, require=False) def get_prioritized_files(self): """ @@ -467,6 +466,8 @@ class WuttaConfig: if default is not UNSPECIFIED: return default + return None + def get_from_db(self, key, session=None, **kwargs): """ Retrieve a config value from database settings table. @@ -511,6 +512,7 @@ class WuttaConfig: value = self.get(*args, **kwargs) if value is not None: return int(value) + return None def get_list(self, *args, **kwargs): """ @@ -525,6 +527,7 @@ class WuttaConfig: value = self.get(*args, **kwargs) if value is not None: return self.parse_list(value) + return None def get_dict(self, prefix): """ @@ -611,7 +614,7 @@ class WuttaConfig: # write INI file and return path fd, path = tempfile.mkstemp(suffix='.conf') os.close(fd) - with open(path, 'wt') as f: + with open(path, 'wt', encoding='utf_8') as f: parser.write(f) return path diff --git a/src/wuttjamaican/db/model/auth.py b/src/wuttjamaican/db/model/auth.py index eb42a47..b776d04 100644 --- a/src/wuttjamaican/db/model/auth.py +++ b/src/wuttjamaican/db/model/auth.py @@ -45,7 +45,7 @@ import sqlalchemy as sa from sqlalchemy import orm from sqlalchemy.ext.associationproxy import association_proxy -from .base import Base, uuid_column, uuid_fk_column +from . import Base, uuid_column, uuid_fk_column class Role(Base): diff --git a/src/wuttjamaican/db/model/base.py b/src/wuttjamaican/db/model/base.py index 8086cd0..9dc49ae 100644 --- a/src/wuttjamaican/db/model/base.py +++ b/src/wuttjamaican/db/model/base.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. # @@ -36,8 +36,7 @@ import sqlalchemy as sa from sqlalchemy import orm from sqlalchemy.ext.associationproxy import association_proxy -from wuttjamaican.db.util import (naming_convention, ModelBase, - uuid_column, uuid_fk_column) +from wuttjamaican.db.util import naming_convention, ModelBase, uuid_column class WuttaModelBase(ModelBase): @@ -215,3 +214,4 @@ class Person(Base): if self.users: return self.users[0] + return None diff --git a/src/wuttjamaican/db/model/batch.py b/src/wuttjamaican/db/model/batch.py index 9b414b5..e253e84 100644 --- a/src/wuttjamaican/db/model/batch.py +++ b/src/wuttjamaican/db/model/batch.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. # @@ -31,7 +31,7 @@ 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, uuid_fk_column, User +from wuttjamaican.db.model import uuid_column, User from wuttjamaican.db.util import UUID @@ -263,6 +263,7 @@ class BatchMixin: """ if self.id: return f'{self.id:08d}' + return None class BatchRowMixin: diff --git a/src/wuttjamaican/db/model/upgrades.py b/src/wuttjamaican/db/model/upgrades.py index 750a9a6..8e94abd 100644 --- a/src/wuttjamaican/db/model/upgrades.py +++ b/src/wuttjamaican/db/model/upgrades.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. # @@ -29,7 +29,7 @@ import datetime import sqlalchemy as sa from sqlalchemy import orm -from .base import Base, uuid_column, uuid_fk_column +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 diff --git a/src/wuttjamaican/db/util.py b/src/wuttjamaican/db/util.py index ff4b69b..ebaf0b1 100644 --- a/src/wuttjamaican/db/util.py +++ b/src/wuttjamaican/db/util.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. # @@ -66,6 +66,7 @@ class ModelBase: state = sa.inspect(self) if hasattr(state.attrs, key): return getattr(self, key) + raise KeyError(f"model instance has no attr with key: {key}") class UUID(sa.types.TypeDecorator): diff --git a/src/wuttjamaican/email.py b/src/wuttjamaican/email.py index af039d6..8ad9997 100644 --- a/src/wuttjamaican/email.py +++ b/src/wuttjamaican/email.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. # @@ -358,6 +358,7 @@ class EmailHandler(GenericHandler): if instance: setting = setting(self.config) return setting + return None def make_message(self, **kwargs): """ @@ -573,6 +574,7 @@ class EmailHandler(GenericHandler): if template: context = context or {} return template.render(**context) + return None def get_auto_html_body(self, key, context=None): """ @@ -585,6 +587,7 @@ class EmailHandler(GenericHandler): if template: context = context or {} return template.render(**context) + return None def get_auto_body_template(self, key, mode): """ """ @@ -601,6 +604,7 @@ class EmailHandler(GenericHandler): return templates.get_template(f'{key}.{mode}.mako') except TopLevelLookupException: pass + return None def get_notes(self, key): """ @@ -652,8 +656,8 @@ class EmailHandler(GenericHandler): :returns: True if this email type is enabled, otherwise false. """ - for key in set([key, 'default']): - enabled = self.config.get_bool(f'{self.config.appname}.email.{key}.enabled') + for k in set([key, 'default']): + enabled = self.config.get_bool(f'{self.config.appname}.email.{k}.enabled') if enabled is not None: return enabled return True diff --git a/src/wuttjamaican/install.py b/src/wuttjamaican/install.py index 28dfb60..8ca35ec 100644 --- a/src/wuttjamaican/install.py +++ b/src/wuttjamaican/install.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. # @@ -25,7 +25,6 @@ Install Handler """ import os -import shutil import stat import subprocess import sys @@ -255,6 +254,7 @@ class InstallHandler(GenericHandler): sa.inspect(engine).has_table('whatever') except Exception as error: return str(error) + return None def make_template_context(self, dbinfo, **kwargs): """ diff --git a/src/wuttjamaican/people.py b/src/wuttjamaican/people.py index 1c855a8..1cc6fda 100644 --- a/src/wuttjamaican/people.py +++ b/src/wuttjamaican/people.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. # @@ -88,3 +88,5 @@ class PeopleHandler(GenericHandler): user = obj if user.person: return user.person + + return None diff --git a/src/wuttjamaican/problems.py b/src/wuttjamaican/problems.py index 76a5282..608ef66 100644 --- a/src/wuttjamaican/problems.py +++ b/src/wuttjamaican/problems.py @@ -308,14 +308,14 @@ class ProblemHandler(GenericHandler): if not self.is_enabled(check): log.debug("problem check is not enabled: %s", key) if not force: - return + return None weekday = datetime.date.today().weekday() if not self.should_run_for_weekday(check, weekday): log.debug("problem check is not scheduled for %s: %s", calendar.day_name[weekday], key) if not force: - return + return None check_instance = check(self.config) problems = self.find_problems(check_instance) diff --git a/src/wuttjamaican/reports.py b/src/wuttjamaican/reports.py index 6d5cb88..7a55a19 100644 --- a/src/wuttjamaican/reports.py +++ b/src/wuttjamaican/reports.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. # @@ -196,6 +196,7 @@ class ReportHandler(GenericHandler): if instance: report = report(self.config) return report + return None def make_report_data(self, report, params=None, progress=None, **kwargs): """ diff --git a/src/wuttjamaican/testing.py b/src/wuttjamaican/testing.py index 5d34960..3ec7ae8 100644 --- a/src/wuttjamaican/testing.py +++ b/src/wuttjamaican/testing.py @@ -95,7 +95,7 @@ class FileTestCase(TestCase): myconf = self.write_file('my.conf', '') """ path = os.path.join(self.tempdir, filename) - with open(path, 'wt') as f: + with open(path, 'wt', encoding='utf_8') as f: f.write(content) return path diff --git a/src/wuttjamaican/util.py b/src/wuttjamaican/util.py index 161dbce..6296bb5 100644 --- a/src/wuttjamaican/util.py +++ b/src/wuttjamaican/util.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. # @@ -256,11 +256,11 @@ def parse_list(value): parser.whitespace += ',' parser.whitespace_split = True values = list(parser) - for i, value in enumerate(values): - if value.startswith('"') and value.endswith('"'): - values[i] = value[1:-1] - elif value.startswith("'") and value.endswith("'"): - values[i] = value[1:-1] + for i, val in enumerate(values): + if val.startswith('"') and val.endswith('"'): + values[i] = val[1:-1] + elif val.startswith("'") and val.endswith("'"): + values[i] = val[1:-1] return values @@ -354,8 +354,8 @@ def resource_path(path): package, filename = path.split(':') ref = files(package) / filename - with as_file(ref) as path: - return str(path) + with as_file(ref) as p: + return str(p) return path diff --git a/tests/db/model/test_batch.py b/tests/db/model/test_batch.py index fa16d25..308cb6f 100644 --- a/tests/db/model/test_batch.py +++ b/tests/db/model/test_batch.py @@ -27,6 +27,10 @@ else: batch = MyBatch(id=42, uuid=_uuid.UUID('0675cdac-ffc9-7690-8000-6023de1c8cfd')) self.assertEqual(repr(batch), "MyBatch(uuid=UUID('0675cdac-ffc9-7690-8000-6023de1c8cfd'))") self.assertEqual(str(batch), "00000042") + self.assertEqual(batch.id_str, "00000042") + + batch2 = MyBatch() + self.assertIsNone(batch2.id_str) class TestBatchRowMixin(DataTestCase): diff --git a/tests/db/test_util.py b/tests/db/test_util.py index 44ff6f0..f2002b8 100644 --- a/tests/db/test_util.py +++ b/tests/db/test_util.py @@ -22,9 +22,11 @@ else: def test_dict_behavior(self): setting = Setting() self.assertEqual(list(iter(setting)), [('name', None), ('value', None)]) + self.assertIsNone(setting.name) self.assertIsNone(setting['name']) setting.name = 'foo' self.assertEqual(setting['name'], 'foo') + self.assertRaises(KeyError, lambda: setting['notfound']) class TestUUID(TestCase): diff --git a/tests/test_app.py b/tests/test_app.py index e20e324..e05334d 100644 --- a/tests/test_app.py +++ b/tests/test_app.py @@ -375,6 +375,10 @@ app_title = WuttaTest ver = self.app.get_version(obj=query) self.assertEqual(ver, version('SQLAlchemy')) + # random object will not yield a dist nor version + ver = self.app.get_version(obj=42) + self.assertIsNone(ver) + # can override dist via config self.config.setdefault('wuttatest.app_dist', 'python-configuration') ver = self.app.get_version() diff --git a/tests/test_reports.py b/tests/test_reports.py index 7b19385..7d730e7 100644 --- a/tests/test_reports.py +++ b/tests/test_reports.py @@ -94,6 +94,10 @@ class TestReportHandler(ConfigTestCase): self.assertTrue(issubclass(report, mod.Report)) self.assertIs(report, MockFooReport) + # not found + report = handler.get_report('unknown') + self.assertIsNone(report) + def test_make_report_data(self): providers = { 'wuttatest': MagicMock(report_modules=['tests.test_reports']),