Python: Make semantic_kernel.NullLogger match logging.Logger function signatures (#2892)

### Motivation and Context

<!-- Thank you for your contribution to the semantic-kernel repo!
Please help reviewers and future users, providing the following
information:
  1. Why is this change required?
  2. What problem does it solve?
  3. What scenario does it contribute to?
  4. If it fixes an open issue, please link to the issue here.
-->
1. #2889 
2. Allows Contributors and Devs to seamlessly use `NullLogger` or
generalized `Logger` class without having to do attribute checks
3. See details in #2889 
4. #2889 

### Description

<!-- Describe your changes, the overall approach, the underlying design.
These notes will help understanding how your code works. Thanks! -->

* I added in a `_NullerMeta` metaclass to the `NullLogger` to iterate
over all the function signatures in the `Logger` class and have them
issue no returns.
* This is backward compatible and breaks no existing implementations.

### Contribution Checklist

<!-- Before submitting this PR, please make sure: -->

- [x] The code builds clean without any errors or warnings
- [x] The PR follows the [SK Contribution
Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md)
and the [pre-submission formatting
script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts)
raises no violations
- [x] All unit tests pass, and I have added new tests where possible
- [x] I didn't break anyone 😄

---------

Co-authored-by: Abby Harrison <[email protected]>
This commit is contained in:
Jib
2023-09-27 19:30:22 +00:00
committed by GitHub
co-authored by Abby Harrison
parent 8217c21e43
commit 56bcccfab6
+29 -13
View File
@@ -1,24 +1,40 @@
# Copyright (c) Microsoft. All rights reserved.
from functools import wraps
from logging import Logger
from typing import Any, Callable
class NullLogger(Logger):
def _nullify(fn) -> Callable[[Any], None]:
"""General wrapper to not call wrapped function"""
@wraps(fn)
def _inner_nullify(*args, **kwargs) -> None:
return
return _inner_nullify
class _NullerMeta(type):
def __new__(cls, classname, base_classes, class_dict):
"""Return a Class that nullifies all Logger object callbacks"""
nullified_dict = {
attr_name: _nullify(attr)
for attr_name, attr in Logger.__dict__.items()
if callable(attr)
}
return type.__new__(
cls, classname, base_classes, {**class_dict, **nullified_dict}
)
class NullLogger(Logger, metaclass=_NullerMeta):
"""
A logger that does nothing.
"""
def __init__(self) -> None:
pass
def __init__(self):
super().__init__(None)
def debug(self, _: str) -> None:
pass
def info(self, _: str) -> None:
pass
def warning(self, _: str) -> None:
pass
def error(self, _: str) -> None:
pass
__all__ = ["NullLogger"]