Skip to content

Commit d47c2bb

Browse files
committed
Avoid linting failures by unconditionally defining a logger property.
Recent changes to the linting checks have resulted in any changes in and around configuration fail in CI with the complaint that logger is not defined. In trying to understand what was happening it was found that some amount of confusion was occurring having both logger and logger_obj properties. Attempt to fix this by: 1) unconditionally defining both properties 2) always setting both properties 3) determining the type of logger being assigned and set the internal properties as appropriate Expanding on the latter, loggers are almost always set as assignment to .logger, but this was not always being passed the same kind of object. At times this was a bare logger (i.e. info(), .debug() etc) but sometimes it was something with .reopen() which would then simply be thrown away and thus reload() would not actually work. Fix this by detecting a .reopen() method and correctly referencing such an object.
1 parent ba904c2 commit d47c2bb

File tree

4 files changed

+67
-15
lines changed

4 files changed

+67
-15
lines changed

mig/shared/configuration.py

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import copy
3838
import datetime
3939
import functools
40+
import inspect
4041
import os
4142
import pwd
4243
import re
@@ -67,7 +68,7 @@
6768
generic_valid_days, DEFAULT_USER_ID_FORMAT, valid_user_id_formats, \
6869
valid_filter_methods, default_twofactor_auth_apps, \
6970
mig_conf_section_dirname
70-
from mig.shared.logger import Logger, SYSLOG_GDP
71+
from mig.shared.logger import Logger, BareLoggerAdapter, SYSLOG_GDP
7172
from mig.shared.htmlgen import menu_items, vgrid_items
7273
from mig.shared.fileio import read_file, load_json, write_file
7374
except ImportError as ioe:
@@ -693,7 +694,6 @@ def get(self, *args, **kwargs):
693694
'logfile': '',
694695
'loglevel': '',
695696
'logger_obj': None,
696-
'logger': None,
697697
'gdp_logger_obj': None,
698698
'gdp_logger': None,
699699
'auth_logger_obj': None,
@@ -757,6 +757,13 @@ def __init__(self, config_file, verbose=False, skip_log=False,
757757
# Explicitly init a few helpers hot-plugged and used in ways where it's
758758
# less obvious if they are always guaranteed to already be initialized.
759759
self.default_page = None
760+
761+
# internal state
762+
self._loaded = False
763+
764+
# logging related
765+
self.logger_obj = None
766+
self._logger = None
760767
self.auth_logger_obj = None
761768
self.gdp_logger_obj = None
762769

@@ -770,6 +777,34 @@ def __init__(self, config_file, verbose=False, skip_log=False,
770777
disable_auth_log=disable_auth_log,
771778
_config_file=config_file)
772779

780+
@property
781+
def logger(self):
782+
assert self._logger, "logging attempt prior to logger availability"
783+
return self._logger
784+
785+
@logger.setter
786+
def logger(self, logger):
787+
"""Setter method that correctly sets logger related properties."""
788+
789+
# attempt to determine what type of objetc we were given - this logic
790+
# exists to deal with some fallout from having both logger_obj and
791+
# logger properties and which of them should be set
792+
793+
if inspect.ismethod(getattr(logger, 'reopen', None)):
794+
# we have a logger_obj, not a plain logger
795+
# record it that way to ensure it could be corrctly reopened where
796+
# otherwise refefences to the object that has it may be lost and it
797+
# may not occur
798+
self.logger_obj = logger
799+
self._logger = logger.logger
800+
elif inspect.ismethod(getattr(logger, 'info', None)):
801+
# we have a bare logger object based on the sanity check
802+
self._logger = logger
803+
self.logger_obj = BareLoggerAdapter(logger)
804+
else:
805+
raise
806+
807+
773808
def reload_config(self, verbose, skip_log=False, disable_auth_log=False,
774809
_config_file=None):
775810
"""Re-read and parse configuration file. Optional skip_log arg
@@ -786,12 +821,6 @@ def reload_config(self, verbose, skip_log=False, disable_auth_log=False,
786821
_config_file = _config_file or self.config_file
787822
assert _config_file is not None
788823

789-
try:
790-
if self.logger:
791-
self.logger.info('reloading configuration and reopening log')
792-
except:
793-
pass
794-
795824
try:
796825
config_file_is_path = os.path.isfile(_config_file)
797826
except TypeError:
@@ -841,13 +870,17 @@ def reload_config(self, verbose, skip_log=False, disable_auth_log=False,
841870

842871
# reopen or initialize logger
843872

844-
if self.logger_obj:
873+
if self._loaded:
874+
self.logger.info('reloading configuration and reopening log')
845875
self.logger_obj.reopen()
846876
else:
847-
self.logger_obj = Logger(self.loglevel, logfile=self.log_path)
877+
self.logger = Logger(self.loglevel, logfile=self.log_path)
878+
self.logger.info('loading configuration and opening log')
879+
880+
# record that the object has been populated
881+
self._loaded = True
848882

849-
logger = self.logger_obj.logger
850-
self.logger = logger
883+
logger = self.logger
851884

852885
# print "logger initialized (level " + logger_obj.loglevel() + ")"
853886
# logger.debug("logger initialized")

mig/shared/logger.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,23 @@ def _name_to_format(name):
6767
return formats[name]
6868

6969

70+
class BareLoggerAdapter:
71+
"""Small wrapper to adapt an arbitrary bare logger to the MiG Logger API"""
72+
73+
def __init__(self, logger):
74+
self._logger = logger
75+
76+
@property
77+
def logger(self):
78+
return self._logger
79+
80+
def reopen(self):
81+
pass
82+
83+
def shutdown(self):
84+
pass
85+
86+
7087
class SysLogLibHandler(logging.Handler):
7188
"""A logging handler that emits messages to syslog.syslog."""
7289

tests/fixture/mig_shared_configuration--new.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,6 @@
104104
],
105105
"log_dir": "",
106106
"logfile": "",
107-
"logger": null,
108-
"logger_obj": null,
109107
"loglevel": "",
110108
"lrmstypes": [],
111109
"mig_code_base": "",

tests/test_mig_shared_configuration.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
from tests.support import MigTestCase, TEST_DATA_DIR, PY2, testmain, \
3535
fixturefile
3636
from mig.shared.configuration import Configuration
37+
from mig.shared.logger import null_logger
3738

3839

3940
def _is_method(value):
@@ -42,7 +43,7 @@ def _is_method(value):
4243

4344
def _to_dict(obj):
4445
return {k: v for k, v in inspect.getmembers(obj)
45-
if not (k.startswith('__') or _is_method(v))}
46+
if not (k.startswith('_') or k.startswith('logger') or _is_method(v))}
4647

4748

4849
class MigSharedConfiguration(MigTestCase):
@@ -320,6 +321,9 @@ def test_default_object(self):
320321
'mig_shared_configuration--new', fixture_format='json')
321322

322323
configuration = Configuration(None)
324+
# attach a null logger to sidestep the useful logger before available
325+
# assertion which would otherwise blow when the object is inspected
326+
configuration.logger = null_logger("test_configuration")
323327
# TODO: the following work-around default values set for these on the
324328
# instance that no longer make total sense but fiddling with them
325329
# is better as a follow-up.

0 commit comments

Comments
 (0)