Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added type aliases for Level and Logger #90

Merged
merged 3 commits into from
Feb 7, 2024
Merged
Show file tree
Hide file tree
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
4 changes: 3 additions & 1 deletion logot/_format.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from __future__ import annotations

from logot._typing import Level

def format_level(level: str | int) -> str:

def format_level(level: Level) -> str:
# Format `str` level.
if isinstance(level, str):
return level
Expand Down
5 changes: 3 additions & 2 deletions logot/_logged.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from logot._capture import Captured
from logot._format import format_level, format_log
from logot._msg import compile_msg_matcher
from logot._typing import Level
from logot._validate import validate_level


Expand Down Expand Up @@ -58,7 +59,7 @@ def _str(self, *, indent: str) -> str:
raise NotImplementedError


def log(level: str | int, msg: str) -> Logged:
def log(level: Level, msg: str) -> Logged:
"""
Creates a :doc:`log pattern </log-pattern-matching>` representing a log record at the given ``level`` with the given
``msg``.
Expand Down Expand Up @@ -122,7 +123,7 @@ def critical(msg: str) -> Logged:
class _RecordLogged(Logged):
__slots__ = ("_level", "_msg", "_msg_matcher")

def __init__(self, level: str | int, msg: str) -> None:
def __init__(self, level: Level, msg: str) -> None:
self._level = level
self._msg = msg
self._msg_matcher = compile_msg_matcher(msg)
Expand Down
5 changes: 3 additions & 2 deletions logot/_logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from logot._capture import Captured
from logot._logot import Capturer, Logot
from logot._typing import Level, Logger


class LoggingCapturer(Capturer):
Expand All @@ -17,7 +18,7 @@ class LoggingCapturer(Capturer):

__slots__ = ("_logger", "_handler", "_prev_levelno")

def start_capturing(self, logot: Logot, /, *, level: str | int, logger: str | None) -> None:
def start_capturing(self, logot: Logot, /, *, level: Level, logger: Logger) -> None:
logger = self._logger = logging.getLogger(logger)
handler = self._handler = _Handler(level, logot)
# If the logger is less verbose than the handler, force it to the necessary verboseness.
Expand All @@ -36,7 +37,7 @@ def stop_capturing(self) -> None:
class _Handler(logging.Handler):
__slots__ = ("_logot",)

def __init__(self, level: str | int, logot: Logot) -> None:
def __init__(self, level: Level, logot: Logot) -> None:
super().__init__(level)
self._logot = logot

Expand Down
13 changes: 7 additions & 6 deletions logot/_logot.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from logot._capture import Captured
from logot._import import LazyCallable
from logot._logged import Logged
from logot._typing import Level, Logger
from logot._validate import validate_level, validate_logger, validate_timeout
from logot._wait import AsyncWaiter, W, create_threading_waiter

Expand All @@ -29,12 +30,12 @@ class Logot:

__slots__ = ("capturer", "timeout", "async_waiter", "_lock", "_queue", "_wait")

DEFAULT_LEVEL: ClassVar[str | int] = "DEBUG"
DEFAULT_LEVEL: ClassVar[Level] = "DEBUG"
"""
The default ``level`` used by :meth:`capturing`.
"""

DEFAULT_LOGGER: ClassVar[str | None] = None
DEFAULT_LOGGER: ClassVar[Logger] = None
"""
The default ``logger`` used by :meth:`capturing`.

Expand Down Expand Up @@ -102,8 +103,8 @@ def __init__(
def capturing(
self,
*,
level: str | int = DEFAULT_LEVEL,
logger: str | None = DEFAULT_LOGGER,
level: Level = DEFAULT_LEVEL,
logger: Logger = DEFAULT_LOGGER,
capturer: Callable[[], Capturer] | None = None,
) -> AbstractContextManager[Logot]:
"""
Expand Down Expand Up @@ -292,7 +293,7 @@ class Capturer(ABC):
__slots__ = ()

@abstractmethod
def start_capturing(self, logot: Logot, /, *, level: str | int, logger: str | None) -> None:
def start_capturing(self, logot: Logot, /, *, level: Level, logger: Logger) -> None:
"""
Starts capturing logs for the given :class:`Logot`.

Expand All @@ -315,7 +316,7 @@ def stop_capturing(self) -> None:
class _Capturing:
__slots__ = ("_logot", "_capturer_obj", "_level", "_logger")

def __init__(self, logot: Logot, capturer: Capturer, *, level: str | int, logger: str | None) -> None:
def __init__(self, logot: Logot, capturer: Capturer, *, level: Level, logger: Logger) -> None:
self._logot = logot
self._capturer_obj = capturer
self._level = level
Expand Down
10 changes: 5 additions & 5 deletions logot/_pytest.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from logot._import import import_any_parsed
from logot._logot import Capturer, Logot
from logot._typing import MISSING, T
from logot._typing import MISSING, Level, Logger, T
from logot._wait import AsyncWaiter


Expand Down Expand Up @@ -47,8 +47,8 @@ def pytest_addoption(parser: pytest.Parser, pluginmanager: pytest.PytestPluginMa

@pytest.fixture()
def logot(
logot_level: str | int,
logot_logger: str | None,
logot_level: Level,
logot_logger: Logger,
logot_capturer: Callable[[], Capturer],
logot_timeout: float,
logot_async_waiter: Callable[[], AsyncWaiter],
Expand All @@ -62,15 +62,15 @@ def logot(


@pytest.fixture(scope="session")
def logot_level(request: pytest.FixtureRequest) -> str | int:
def logot_level(request: pytest.FixtureRequest) -> Level:
"""
The `level` used for automatic log capturing.
"""
return _get_option(request, name="level", parser=str, default=Logot.DEFAULT_LEVEL)


@pytest.fixture(scope="session")
def logot_logger(request: pytest.FixtureRequest) -> str | None:
def logot_logger(request: pytest.FixtureRequest) -> Logger:
"""
The `logger` used for automatic log capturing.
"""
Expand Down
6 changes: 5 additions & 1 deletion logot/_typing.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from __future__ import annotations

import sys
from typing import Any, TypeVar
from typing import Any, TypeVar, Union

if sys.version_info >= (3, 10):
from typing import ParamSpec as ParamSpec
Expand All @@ -13,4 +13,8 @@
P = ParamSpec("P")
T = TypeVar("T")

# TODO: Use `UnionType` when we only need to support Python 3.10+.
Level: TypeAlias = Union[str, int]
Logger: TypeAlias = Union[str, None]

MISSING: Any = object()
5 changes: 3 additions & 2 deletions logot/_unittest.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from unittest import TestCase, TestResult

from logot._logot import Capturer, Logot
from logot._typing import Level, Logger
from logot._wait import AsyncWaiter


Expand All @@ -19,14 +20,14 @@ class LogotTestCase(TestCase):
Use this to make log assertions in your tests.
"""

logot_level: ClassVar[str | int] = Logot.DEFAULT_LEVEL
logot_level: ClassVar[Level] = Logot.DEFAULT_LEVEL
"""
The ``level`` used for automatic :doc:`log capturing </log-capturing>`.

Defaults to :attr:`logot.Logot.DEFAULT_LEVEL`.
"""

logot_logger: ClassVar[str | None] = Logot.DEFAULT_LOGGER
logot_logger: ClassVar[Logger] = Logot.DEFAULT_LOGGER
"""
The ``logger`` used for automatic :doc:`log capturing </log-capturing>`.

Expand Down
6 changes: 4 additions & 2 deletions logot/_validate.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
from __future__ import annotations

from logot._typing import Level, Logger

def validate_level(level: str | int) -> str | int:

def validate_level(level: Level) -> Level:
# Handle `str` or `int` level.
if isinstance(level, (str, int)):
return level
# Handle invalid level.
raise TypeError(f"Invalid level: {level!r}")


def validate_logger(logger: str | None) -> str | None:
def validate_logger(logger: Logger) -> Logger:
# Handle `None` or `str` logger.
if logger is None or isinstance(logger, str):
return logger
Expand Down
6 changes: 3 additions & 3 deletions tests/test_pytest.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

from logot import Capturer, Logot
from logot._pytest import get_optname, get_qualname
from logot._typing import MISSING
from logot._typing import MISSING, Level, Logger
from logot._wait import AsyncWaiter
from logot.asyncio import AsyncioWaiter
from logot.logging import LoggingCapturer
Expand Down Expand Up @@ -56,15 +56,15 @@ def test_{name}({qualname}):
EXPECTED_VAR.reset(expected_token)


def test_level_default(logot_level: str | int) -> None:
def test_level_default(logot_level: Level) -> None:
assert logot_level == Logot.DEFAULT_LEVEL


def test_level_config_pass(pytester: pytest.Pytester) -> None:
assert_fixture_config(pytester, "level", "INFO")


def test_logger_default(logot_logger: str | int) -> None:
def test_logger_default(logot_logger: Logger) -> None:
assert logot_logger == Logot.DEFAULT_LOGGER


Expand Down