3
0
Fork 0

fix: fix 'attribute-defined-outside-init' for pylint

This commit is contained in:
Lance Edgar 2025-08-31 11:42:30 -05:00
parent d9db40fddc
commit 957c334d1d
8 changed files with 34 additions and 58 deletions

View file

@ -2,6 +2,5 @@
[MESSAGES CONTROL]
disable=
attribute-defined-outside-init,
fixme,
too-many-branches,

View file

@ -143,7 +143,7 @@ class AppHandler: # pylint: disable=too-many-public-methods
return self.get_enum()
if name == "providers":
self.providers = self.get_all_providers()
self.__dict__["providers"] = self.get_all_providers()
return self.providers
for provider in self.providers.values():
@ -340,7 +340,7 @@ class AppHandler: # pylint: disable=too-many-public-methods
usedb=False,
default=self.default_model_spec,
)
self.model = importlib.import_module(spec)
self.__dict__["model"] = importlib.import_module(spec)
return self.model
def get_enum(self):
@ -364,7 +364,7 @@ class AppHandler: # pylint: disable=too-many-public-methods
spec = self.config.get(
f"{self.appname}.enum_spec", usedb=False, default=self.default_enum_spec
)
self.enum = importlib.import_module(spec)
self.__dict__["enum"] = importlib.import_module(spec)
return self.enum
def load_object(self, spec):
@ -1154,6 +1154,7 @@ class GenericHandler:
self.config = config
self.app = self.config.get_app()
self.modules = {}
self.classes = {}
@property
def appname(self):

View file

@ -189,6 +189,7 @@ class WuttaConfig: # pylint: disable=too-many-instance-attributes
See also :ref:`where-config-settings-come-from`.
"""
_app = None
default_app_handler_spec = "wuttjamaican.app:AppHandler"
default_engine_maker_spec = "wuttjamaican.db.conf:make_engine_from_config"
@ -640,7 +641,7 @@ class WuttaConfig: # pylint: disable=too-many-instance-attributes
See also :doc:`/narr/handlers/app`.
"""
if not hasattr(self, "_app"):
if not self._app:
spec = self.get(
f"{self.appname}.app.handler",
usedb=False,

View file

@ -323,8 +323,8 @@ class EmailHandler(GenericHandler): # pylint: disable=too-many-public-methods
This calls :meth:`get_email_modules()` and for each module, it
discovers all the email settings it contains.
"""
if not hasattr(self, "_email_settings"):
self._email_settings = {}
if "email_settings" not in self.classes:
self.classes["email_settings"] = {}
for module in self.get_email_modules():
for name in dir(module):
obj = getattr(module, name)
@ -333,9 +333,9 @@ class EmailHandler(GenericHandler): # pylint: disable=too-many-public-methods
and obj is not EmailSetting
and issubclass(obj, EmailSetting)
):
self._email_settings[obj.__name__] = obj
self.classes["email_settings"][obj.__name__] = obj
return self._email_settings
return self.classes["email_settings"]
def get_email_setting(self, key, instance=True):
"""

View file

@ -85,6 +85,7 @@ class InstallHandler(GenericHandler):
app_title = None
pypi_name = None
egg_name = None
schema_installed = False
def __init__(self, config, **kwargs):
super().__init__(config)
@ -100,24 +101,6 @@ class InstallHandler(GenericHandler):
if not self.egg_name:
self.egg_name = self.pypi_name.replace("-", "_")
def run(self):
"""
Run the interactive command-line installer.
This does the following:
* check for ``prompt_toolkit`` and maybe ask to install it
* define the template lookup paths, for making config files
* call :meth:`show_welcome()`
* call :meth:`sanity_check()`
* call :meth:`do_install_steps()`
* call :meth:`show_goodbye()`
Although if a problem is encountered then not all calls may
happen.
"""
self.require_prompt_toolkit()
paths = [
self.app.resource_path("wuttjamaican:templates/install"),
]
@ -131,6 +114,22 @@ class InstallHandler(GenericHandler):
self.templates = TemplateLookup(directories=paths)
def run(self):
"""
Run the interactive command-line installer.
This does the following:
* check for ``prompt_toolkit`` and maybe ask to install it
* call :meth:`show_welcome()`
* call :meth:`sanity_check()`
* call :meth:`do_install_steps()`
* call :meth:`show_goodbye()`
Although if a problem is encountered then not all calls may
happen.
"""
self.require_prompt_toolkit()
self.show_welcome()
self.sanity_check()
self.schema_installed = False

View file

@ -157,8 +157,8 @@ class ReportHandler(GenericHandler):
This calls :meth:`get_report_modules()` and for each module,
it discovers all the reports it contains.
"""
if not hasattr(self, "_reports"):
self._reports = {}
if "reports" not in self.classes:
self.classes["reports"] = {}
for module in self.get_report_modules():
for name in dir(module):
obj = getattr(module, name)
@ -167,9 +167,9 @@ class ReportHandler(GenericHandler):
and obj is not Report
and issubclass(obj, Report)
):
self._reports[obj.report_key] = obj
self.classes["reports"][obj.report_key] = obj
return self._reports
return self.classes["reports"]
def get_report(self, key, instance=True):
"""

View file

@ -17,7 +17,6 @@ from wuttjamaican.testing import FileTestCase, ConfigTestCase
class TestWuttaConfig(FileTestCase):
def make_config(self, **kwargs):
return mod.WuttaConfig(**kwargs)
@ -291,7 +290,6 @@ configure_logging = true
)
with patch.object(conf.WuttaConfig, "_configure_logging") as method:
# no logging config by default
config = conf.WuttaConfig()
method.assert_not_called()
@ -319,7 +317,6 @@ configure_logging = true
)
with patch("wuttjamaican.conf.logging") as logging:
# basic constructor attempts logging config
config = conf.WuttaConfig(configure_logging=True)
logging.config.fileConfig.assert_called_once()
@ -338,14 +335,14 @@ configure_logging = true
logging.config.fileConfig.assert_called_once()
def test_config_has_no_app_after_init(self):
# initial config should *not* have an app yet, otherwise
# extensions cannot specify a default app handler
config = conf.WuttaConfig()
self.assertFalse(hasattr(config, "_app"))
self.assertIsNone(config._app)
# but after that we can get an app okay
app = config.get_app()
self.assertIsNotNone(app)
self.assertIs(app, config._app)
def test_setdefault(self):
@ -628,7 +625,6 @@ configure_logging = true
self.assertEqual(value[2], "baz")
def test_get_app(self):
# default handler
config = conf.WuttaConfig()
self.assertEqual(config.default_app_handler_spec, "wuttjamaican.app:AppHandler")
@ -686,7 +682,6 @@ def custom_make_engine_from_config():
class TestWuttaConfigExtension(TestCase):
def test_basic(self):
config = conf.WuttaConfig()
ext = conf.WuttaConfigExtension()
@ -695,7 +690,6 @@ class TestWuttaConfigExtension(TestCase):
class TestGenericDefaultFiles(TestCase):
def test_linux(self):
files = conf.generic_default_files("wuttatest")
self.assertIsInstance(files, list)
@ -707,7 +701,6 @@ class TestGenericDefaultFiles(TestCase):
win32com.shell.SHGetSpecialFolderPath.return_value = r"C:" + os.sep
with patch.dict("sys.modules", **{"win32com.shell": win32com}):
with patch("wuttjamaican.conf.sys", platform="win32"):
files = conf.generic_default_files("wuttatest")
self.assertIsInstance(files, list)
self.assertTrue(len(files) > 1)
@ -723,14 +716,12 @@ class TestGenericDefaultFiles(TestCase):
with patch("builtins.__import__", side_effect=mock_import):
with patch("wuttjamaican.conf.sys", platform="win32"):
files = conf.generic_default_files("wuttatest")
self.assertIsInstance(files, list)
self.assertEqual(len(files), 0)
class TestGetConfigPaths(FileTestCase):
def test_winsvc(self):
myconf = self.write_file(
"my.conf",
@ -753,7 +744,6 @@ winsvc.RattailFileMonitor = /path/to/other/file
class TestMakeConfig(FileTestCase):
# nb. we use appname='wuttatest' in this suite to avoid any
# "valid" default config files, env vars etc. which may be present
# on the dev machine
@ -763,7 +753,6 @@ class TestMakeConfig(FileTestCase):
with patch("wuttjamaican.conf.generic_default_files") as generic_default_files:
with patch("wuttjamaican.conf.WuttaConfig") as WuttaConfig:
# generic files are used if nothing is specified
generic_default_files.return_value = [generic]
config = conf.make_config(appname="wuttatest")
@ -788,7 +777,6 @@ class TestMakeConfig(FileTestCase):
with patch("wuttjamaican.conf.generic_default_files") as generic_default_files:
with patch("wuttjamaican.conf.WuttaConfig") as WuttaConfig:
# generic defaults are used if nothing specified
generic_default_files.return_value = [generic]
config = conf.make_config(appname="wuttatest")
@ -832,7 +820,6 @@ class TestMakeConfig(FileTestCase):
with patch("wuttjamaican.conf.generic_default_files") as generic_default_files:
with patch("wuttjamaican.conf.WuttaConfig") as WuttaConfig:
generic_default_files.return_value = [generic]
# no plus files by default
@ -877,7 +864,6 @@ class TestMakeConfig(FileTestCase):
with patch("wuttjamaican.conf.generic_default_files") as generic_default_files:
with patch("wuttjamaican.conf.WuttaConfig") as WuttaConfig:
generic_default_files.return_value = [generic]
# generic files by default
@ -922,7 +908,6 @@ class TestMakeConfig(FileTestCase):
with patch.object(mod, "WuttaConfig") as WuttaConfig:
with patch.object(mod, "load_entry_points") as load_entry_points:
# no entry points loaded if extend=False
config = mod.make_config(appname="wuttatest", extend=False)
WuttaConfig.assert_called_once_with(
@ -967,7 +952,6 @@ class TestMakeConfig(FileTestCase):
class TestWuttaConfigProfile(ConfigTestCase):
def make_profile(self, key):
return mod.WuttaConfigProfile(self.config, key)

View file

@ -12,7 +12,6 @@ from wuttjamaican.testing import ConfigTestCase
class TestInstallHandler(ConfigTestCase):
def make_handler(self, **kwargs):
return mod.InstallHandler(self.config, **kwargs)
@ -38,7 +37,6 @@ class TestInstallHandler(ConfigTestCase):
with patch.object(mod, "sys") as sys:
with patch.object(handler, "rprint") as rprint:
with patch.object(handler, "prompt_bool") as prompt_bool:
# user continues
prompt_bool.return_value = True
handler.show_welcome()
@ -54,7 +52,6 @@ class TestInstallHandler(ConfigTestCase):
with patch.object(mod, "sys") as sys:
with patch.object(mod, "os") as os:
with patch.object(handler, "rprint") as rprint:
# pretend appdir does not exist
os.path.exists.return_value = False
handler.sanity_check()
@ -79,10 +76,9 @@ class TestInstallHandler(ConfigTestCase):
with patch.object(handler, "get_dbinfo", return_value=dbinfo):
with patch.object(handler, "make_appdir") as make_appdir:
with patch.object(handler, "install_db_schema") as install_db_schema:
# nb. just for sanity/coverage
install_db_schema.return_value = True
self.assertFalse(hasattr(handler, "schema_installed"))
self.assertFalse(handler.schema_installed)
handler.do_install_steps()
self.assertTrue(make_appdir.called)
self.assertTrue(handler.schema_installed)
@ -109,7 +105,6 @@ class TestInstallHandler(ConfigTestCase):
with patch.object(handler, "prompt_generic", side_effect=prompt_generic):
with patch.object(handler, "test_db_connection") as test_db_connection:
with patch.object(handler, "rprint") as rprint:
# bad dbinfo
test_db_connection.return_value = "bad dbinfo"
sys.exit.side_effect = RuntimeError
@ -220,7 +215,6 @@ default.url = {db_url}
db_url = sa.create_engine(db_url).url
with patch.object(mod, "subprocess") as subprocess:
# user declines offer to install schema
with patch.object(handler, "prompt_bool", return_value=False):
self.assertFalse(handler.install_db_schema(db_url, appdir=self.tempdir))
@ -321,7 +315,6 @@ default.url = {db_url}
with patch("builtins.__import__", side_effect=mock_import):
with patch.object(handler, "get_prompt_style", return_value=style):
with patch.object(handler, "rprint") as rprint:
# no input or default value
mock_prompt.return_value = ""
result = handler.prompt_generic("foo")
@ -452,7 +445,6 @@ default.url = {db_url}
with patch("builtins.__import__", side_effect=mock_import):
with patch.object(handler, "rprint") as rprint:
# no default; true input
mock_prompt.reset_mock()
mock_prompt.return_value = "Y"