Skip to content

Commit f8c17ec

Browse files
committed
Added Logurud class which exposes functions such as self.info(...) to classes with loguru as logger
1 parent b34e299 commit f8c17ec

6 files changed

Lines changed: 103 additions & 11 deletions

File tree

README.rst

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,22 @@ Installation:
3636

3737
The package can be installed through `pip` (this is the recommended method):
3838

39+
.. code-block:: bash
40+
3941
pip install python-utils
4042
4143
Or if `pip` is not available, `easy_install` should work as well:
4244

45+
.. code-block:: bash
46+
4347
easy_install python-utils
4448
4549
Or download the latest release from Pypi (https://pypi.python.org/pypi/python-utils) or Github.
4650

4751
Note that the releases on Pypi are signed with my GPG key (https://pgp.mit.edu/pks/lookup?op=vindex&search=0xE81444E9CE1F695D) and can be checked using GPG:
4852

53+
.. code-block:: bash
54+
4955
gpg --verify python-utils-<version>.tar.gz.asc python-utils-<version>.tar.gz
5056
5157
Quickstart
@@ -226,6 +232,22 @@ Or add a correclty named logger to your classes which can be easily accessed:
226232
import logging
227233
my_class.log(logging.ERROR, 'log')
228234
235+
Alternatively loguru is also supported. It is largely a drop-in replacement for the logging module which is a bit more convenient to configure:
236+
237+
First install the extra loguru package:
238+
239+
.. code-block:: bash
240+
241+
pip install 'python-utils[loguru]'
242+
243+
.. code-block:: python
244+
245+
class MyClass(Logurud):
246+
...
247+
248+
Now you can use the `Logurud` class to make functions such as `self.info()`
249+
available. The benefit of this approach is that you can add extra context or
250+
options to you specific loguru instance (i.e. `self.logger`):
229251

230252
Convenient type aliases and some commonly used types:
231253

_python_utils_tests/test_logger.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import pytest
2+
3+
from python_utils.loguru import Logurud
4+
5+
6+
loguru = pytest.importorskip('loguru')
7+
8+
9+
def test_logurud():
10+
class MyClass(Logurud):
11+
pass
12+
13+
my_class = MyClass()
14+
my_class.debug('debug')
15+
my_class.info('info')
16+
my_class.warning('warning')
17+
my_class.error('error')
18+
my_class.exception('exception')
19+
my_class.log(0, 'log')

python_utils/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
from .time import timedelta_to_seconds
2727
from .time import timeout_generator
2828
from .time import aio_timeout_generator
29+
from .logger import Logged, LoggerBase
2930

3031
__all__ = [
3132
'aio',
@@ -55,4 +56,6 @@
5556
'timeout_generator',
5657
'acount',
5758
'aio_timeout_generator',
59+
'Logged',
60+
'LoggerBase',
5861
]

python_utils/logger.py

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import abc
12
import functools
23
import logging
34

@@ -6,15 +7,18 @@
67
import typing
78

89

9-
class Logged(object):
10-
'''Class which automatically adds a named logger to your class when
11-
interiting
10+
class LoggerBase(abc.ABC):
11+
'''Class which automatically adds logging utilities to your class when
12+
interiting. Expects `logger` to be a logging.Logger or compatible instance.
1213
1314
Adds easy access to debug, info, warning, error, exception and log methods
1415
15-
>>> class MyClass(Logged):
16+
>>> class MyClass(LoggerBase):
17+
... logger = logging.getLogger(__name__)
18+
...
1619
... def __init__(self):
1720
... Logged.__init__(self)
21+
1822
>>> my_class = MyClass()
1923
>>> my_class.debug('debug')
2024
>>> my_class.info('info')
@@ -23,13 +27,9 @@ class Logged(object):
2327
>>> my_class.exception('exception')
2428
>>> my_class.log(0, 'log')
2529
'''
26-
27-
logger: logging.Logger
28-
29-
def __new__(cls, *args, **kwargs):
30-
cls.logger = logging.getLogger(
31-
cls.__get_name(cls.__module__, cls.__name__))
32-
return super(Logged, cls).__new__(cls)
30+
# Being a tad lazy here and not creating a Protocol.
31+
# The actual classes define the correct type anyway
32+
logger: typing.Any
3333

3434
@classmethod
3535
def __get_name(cls, *name_parts: str) -> str:
@@ -64,3 +64,30 @@ def exception(cls, msg: str, *args: typing.Any, **kwargs: typing.Any):
6464
@functools.wraps(logging.log)
6565
def log(cls, lvl: int, msg: str, *args: typing.Any, **kwargs: typing.Any):
6666
cls.logger.log(lvl, msg, *args, **kwargs)
67+
68+
69+
class Logged(LoggerBase):
70+
'''Class which automatically adds a named logger to your class when
71+
interiting
72+
73+
Adds easy access to debug, info, warning, error, exception and log methods
74+
75+
>>> class MyClass(Logged):
76+
... def __init__(self):
77+
... Logged.__init__(self)
78+
>>> my_class = MyClass()
79+
>>> my_class.debug('debug')
80+
>>> my_class.info('info')
81+
>>> my_class.warning('warning')
82+
>>> my_class.error('error')
83+
>>> my_class.exception('exception')
84+
>>> my_class.log(0, 'log')
85+
'''
86+
87+
logger: logging.Logger
88+
89+
def __new__(cls, *args, **kwargs):
90+
cls.logger = logging.getLogger(
91+
cls._LoggerBase__get_name(cls.__module__, cls.__name__)
92+
)
93+
return super(Logged, cls).__new__(cls)

python_utils/loguru.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
from __future__ import annotations
2+
3+
from . import logger
4+
5+
import loguru
6+
7+
__all__ = ['Logurud']
8+
9+
10+
class Logurud(logger.LoggerBase):
11+
logger: loguru.Logger
12+
13+
def __new__(cls, *args, **kwargs):
14+
# Import at runtime to make loguru an optional dependency
15+
import loguru
16+
cls.logger: loguru.Loguru = loguru.logger
17+
return super().__new__(cls)

setup.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@
2929
long_description=long_description,
3030
tests_require=['pytest'],
3131
extras_require={
32+
'loguru': [
33+
'loguru',
34+
],
3235
'docs': [
3336
'mock',
3437
'sphinx',
@@ -43,6 +46,7 @@
4346
'pytest-asyncio',
4447
'sphinx',
4548
'types-setuptools',
49+
'loguru',
4650
],
4751
},
4852
classifiers=['License :: OSI Approved :: BSD License'],

0 commit comments

Comments
 (0)