Skip to content
This repository has been archived by the owner on Jan 25, 2024. It is now read-only.

Add DEBUG-level logging of all Interface method calls #369

Merged
merged 1 commit into from
Aug 6, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions j5/backends/backend.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
"""The base classes for backends."""

import inspect
import logging
from abc import ABCMeta, abstractmethod
from functools import wraps
from typing import TYPE_CHECKING, Dict, Optional, Set, Type

if TYPE_CHECKING: # pragma: nocover
Expand All @@ -17,6 +20,38 @@ class CommunicationError(Exception):
"""


def _wrap_method_with_logging(
backend_class: Type['Backend'],
method_name: str,
logger: logging.Logger,
) -> None:
old_method = getattr(backend_class, method_name)
signature = inspect.signature(old_method)
@wraps(old_method)
def new_method(*args, **kwargs): # type: ignore
retval = old_method(*args, **kwargs)
arg_map = signature.bind(*args, **kwargs).arguments
args_str = ", ".join(
f"{name}={value!r}"
for name, value in arg_map.items()
if name != "self"
)
retval_str = (f" -> {retval!r}" if retval is not None else "")
message = f"{method_name}({args_str}){retval_str}"
logger.debug(message)
return retval
setattr(backend_class, method_name, new_method)


def _wrap_methods_with_logging(backend_class: Type['Backend']) -> None:
component_classes = backend_class.board.supported_components() # type: ignore
for component_class in component_classes:
logger = logging.getLogger(component_class.__module__)
interface_class = component_class.interface_class()
for method_name in interface_class.__abstractmethods__:
_wrap_method_with_logging(backend_class, method_name, logger)


class BackendMeta(ABCMeta):
"""
The metaclass for a backend.
Expand All @@ -43,6 +78,7 @@ def __new__(mcs, name, bases, namespace, **kwargs): # type:ignore
mcs._check_component_interfaces(cls)

cls.environment.register_backend(cls.board, cls)
_wrap_methods_with_logging(cls)
return cls

# The following line should never run, as _check_compatibility should fail first.
Expand Down