mirror of
https://github.com/EDCD/EDMarketConnector.git
synced 2025-04-15 08:40:34 +03:00
Added support for logging from properties
This is some best effort support for using logging in properties. This works by using the (as suggested by reporter) inspect `getattr_static` method, and failing that (as it can possibly fail), wrapping a `getattr` in a try/catch for a RecursionError--don't want to catch other things, probably best if that explodes on its own. From there as the `property` object will not have location information, we rebuild as best we can to an approximation of what the path would be. With a healthy dash of defensive programming "Just in case". I don't think that this will have any adverse effects to other logging methods, as all the new code should only be touched if we hit a property object. Closes #808
This commit is contained in:
parent
b5f98d7ced
commit
1cb876c594
@ -296,9 +296,32 @@ class EDMCContextFilter(logging.Filter):
|
|||||||
name = f'_{frame_class.__class__.__name__}{frame_info.function}'
|
name = f'_{frame_class.__class__.__name__}{frame_info.function}'
|
||||||
|
|
||||||
# Find __qualname__ of the caller
|
# Find __qualname__ of the caller
|
||||||
fn = getattr(frame_class, name, None)
|
fn = inspect.getattr_static(frame_class, name, None)
|
||||||
if fn and fn.__qualname__:
|
if fn is None:
|
||||||
caller_qualname = fn.__qualname__
|
# For some reason getattr_static cant grab this. Try and grab it with getattr, bail out
|
||||||
|
# if we get a RecursionError indicating a property
|
||||||
|
try:
|
||||||
|
fn = getattr(frame_class, name, None)
|
||||||
|
except RecursionError:
|
||||||
|
print(
|
||||||
|
"EDMCLogging:EDMCContextFilter:caller_attributes():"
|
||||||
|
"Failed to get attribute for function info. Bailing out"
|
||||||
|
)
|
||||||
|
return "??", "??", "??"
|
||||||
|
|
||||||
|
if fn is not None:
|
||||||
|
if isinstance(fn, property):
|
||||||
|
class_name = str(frame_class)
|
||||||
|
# If somehow you make your __class__ or __class__.__qualname__ recursive, I'll be impressed.
|
||||||
|
if hasattr(frame_class, '__class__') and hasattr(frame_class.__class__, "__qualname__"):
|
||||||
|
class_name = frame_class.__class__.__qualname__
|
||||||
|
caller_qualname = f"{class_name}.{name}(property)"
|
||||||
|
|
||||||
|
else:
|
||||||
|
caller_qualname = f"<property {name} on {class_name}>"
|
||||||
|
|
||||||
|
elif fn.__qualname__:
|
||||||
|
caller_qualname = fn.__qualname__
|
||||||
|
|
||||||
# Find containing class name(s) of caller, if any
|
# Find containing class name(s) of caller, if any
|
||||||
if frame_class.__class__ and frame_class.__class__.__qualname__:
|
if frame_class.__class__ and frame_class.__class__.__qualname__:
|
||||||
|
@ -1238,7 +1238,6 @@ executable: {sys.executable}
|
|||||||
sys.path: {sys.path}'''
|
sys.path: {sys.path}'''
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# We prefer a UTF-8 encoding gets set, but older Windows versions have
|
# We prefer a UTF-8 encoding gets set, but older Windows versions have
|
||||||
# issues with this. From Windows 10 1903 onwards we can rely on the
|
# issues with this. From Windows 10 1903 onwards we can rely on the
|
||||||
# manifest ActiveCodePage to set this, but that is silently ignored on
|
# manifest ActiveCodePage to set this, but that is silently ignored on
|
||||||
@ -1287,7 +1286,8 @@ sys.path: {sys.path}'''
|
|||||||
logger.exception(f"Could not set LC_ALL to ('{locale_startup[0]}', 'UTF_8')")
|
logger.exception(f"Could not set LC_ALL to ('{locale_startup[0]}', 'UTF_8')")
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.exception(f"Exception other than locale.Error on setting LC_ALL=('{locale_startup[0]}', 'UTF_8')")
|
logger.exception(
|
||||||
|
f"Exception other than locale.Error on setting LC_ALL=('{locale_startup[0]}', 'UTF_8')")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
log_locale('After switching to UTF-8 encoding (same language)')
|
log_locale('After switching to UTF-8 encoding (same language)')
|
||||||
@ -1303,10 +1303,16 @@ sys.path: {sys.path}'''
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
logger.debug('A call from A.B.__init__')
|
logger.debug('A call from A.B.__init__')
|
||||||
self.__test()
|
self.__test()
|
||||||
|
_ = self.test_prop
|
||||||
|
|
||||||
def __test(self):
|
def __test(self):
|
||||||
logger.debug("A call from A.B.__test")
|
logger.debug("A call from A.B.__test")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def test_prop(self):
|
||||||
|
logger.debug("test log from property")
|
||||||
|
return "Test property is testy"
|
||||||
|
|
||||||
# abinit = A.B()
|
# abinit = A.B()
|
||||||
|
|
||||||
# Plain, not via `logger`
|
# Plain, not via `logger`
|
||||||
|
Loading…
x
Reference in New Issue
Block a user