1
0
mirror of https://github.com/EDCD/EDMarketConnector.git synced 2025-06-09 03:42:16 +03:00

Fixed error when logging out of a class var

This also adds an insane amount of paranoia around getting SOMETHING
dumped when an exception happens.

Fixes #1044
This commit is contained in:
A_D 2021-05-10 15:24:26 +02:00
parent 71e3f8d2b3
commit 92e580e0c7
No known key found for this signature in database
GPG Key ID: 4BE9EB7DF45076C4

View File

@ -41,10 +41,12 @@ import logging.handlers
import os import os
import pathlib import pathlib
import tempfile import tempfile
from contextlib import suppress
# So that any warning about accessing a protected member is only in one place. # So that any warning about accessing a protected member is only in one place.
from sys import _getframe as getframe from sys import _getframe as getframe
from threading import get_native_id as thread_native_id from threading import get_native_id as thread_native_id
from typing import TYPE_CHECKING, Tuple, cast from typing import TYPE_CHECKING, Tuple, cast
from traceback import print_exc
from config import appcmdname, appname, config from config import appcmdname, appname, config
@ -85,7 +87,10 @@ logging.Logger.trace = lambda self, message, *args, **kwargs: self._log( # type
) )
if TYPE_CHECKING: if TYPE_CHECKING:
from types import FrameType
# Fake type that we can use here to tell type checkers that trace exists # Fake type that we can use here to tell type checkers that trace exists
class LoggerMixin(logging.Logger): class LoggerMixin(logging.Logger):
"""LoggerMixin is a fake class that tells type checkers that trace exists on a given type.""" """LoggerMixin is a fake class that tells type checkers that trace exists on a given type."""
@ -318,7 +323,7 @@ class EDMCContextFilter(logging.Filter):
# We've given up, so just return '??' to signal we couldn't get the info # We've given up, so just return '??' to signal we couldn't get the info
return '??', '??', module_name return '??', '??', module_name
try:
args, _, _, value_dict = inspect.getargvalues(frame) args, _, _, value_dict = inspect.getargvalues(frame)
if len(args) and args[0] in ('self', 'cls'): if len(args) and args[0] in ('self', 'cls'):
frame_class: 'object' = value_dict[args[0]] frame_class: 'object' = value_dict[args[0]]
@ -349,7 +354,8 @@ class EDMCContextFilter(logging.Filter):
if fn is not None: if fn is not None:
if isinstance(fn, property): if isinstance(fn, property):
class_name = str(frame_class) class_name = str(frame_class)
# If somehow you make your __class__ or __class__.__qualname__ recursive, I'll be impressed. # 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__"): if hasattr(frame_class, '__class__') and hasattr(frame_class.__class__, "__qualname__"):
class_name = frame_class.__class__.__qualname__ class_name = frame_class.__class__.__qualname__
caller_qualname = f"{class_name}.{name}(property)" caller_qualname = f"{class_name}.{name}(property)"
@ -357,11 +363,14 @@ class EDMCContextFilter(logging.Filter):
else: else:
caller_qualname = f"<property {name} on {class_name}>" caller_qualname = f"<property {name} on {class_name}>"
elif fn.__qualname__: elif hasattr(fn, '__qualname__') and fn.__qualname__:
caller_qualname = 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 hasattr(frame_class.__class__, '__qualname__')
and frame_class.__class__.__qualname__
):
caller_class_names = frame_class.__class__.__qualname__ caller_class_names = frame_class.__class__.__qualname__
# It's a call from the top level module file # It's a call from the top level module file
@ -375,6 +384,20 @@ class EDMCContextFilter(logging.Filter):
module_name = cls.munge_module_name(frame_info, module_name) module_name = cls.munge_module_name(frame_info, module_name)
except Exception as e:
print("ALERT! Something went VERY wrong in handling finding info to log")
print("ALERT! Information is as follows")
with suppress(Exception):
print(f"ALERT! {e=}")
print_exc()
print(f"ALERT! {frame=}")
with suppress(Exception):
print(f"ALERT! {fn=}") # type: ignore
with suppress(Exception):
print(f"ALERT! {cls=}")
finally: # Ensure this always happens
# https://docs.python.org/3.7/library/inspect.html#the-interpreter-stack # https://docs.python.org/3.7/library/inspect.html#the-interpreter-stack
del frame del frame
@ -398,19 +421,19 @@ class EDMCContextFilter(logging.Filter):
# Go up through stack frames until we find the first with a # Go up through stack frames until we find the first with a
# type(f_locals.self) of logging.Logger. This should be the start # type(f_locals.self) of logging.Logger. This should be the start
# of the frames internal to logging. # of the frames internal to logging.
frame: 'frame' = getframe(0) frame: 'FrameType' = getframe(0)
while frame: while frame:
if isinstance(frame.f_locals.get('self'), logging.Logger): if isinstance(frame.f_locals.get('self'), logging.Logger):
frame = frame.f_back # Want to start on the next frame below frame = cast('FrameType', frame.f_back) # Want to start on the next frame below
break break
frame = frame.f_back frame = cast('FrameType', frame.f_back)
# Now continue up through frames until we find the next one where # Now continue up through frames until we find the next one where
# that is *not* true, as it should be the call site of the logger # that is *not* true, as it should be the call site of the logger
# call # call
while frame: while frame:
if not isinstance(frame.f_locals.get('self'), logging.Logger): if not isinstance(frame.f_locals.get('self'), logging.Logger):
break # We've found the frame we want break # We've found the frame we want
frame = frame.f_back frame = cast('FrameType', frame.f_back)
return frame return frame
@classmethod @classmethod