1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
|
From: Delgan <delgan.py@gmail.com>
Date: Sat, 2 Aug 2025 10:35:00 +0200
Subject: Fix Mypy unit tests due to deprecated "force_uppercase_builtins"
option
The latest version of Mypy removes this configuration parameter, which
we used to standardize the expected output across the different tested
versions of Python.
As a workaround, this feature is reimplemented using a basic regex.
This'll likely become more complicated if they later force a change in
the syntax of "Union" as well.
Note that we're patching the expected output (differs for each Python
version) in the test cases, not the actual Mypy output.
---
tests/conftest.py | 15 ++++++++++++++-
tests/typesafety/test_logger.yml | 18 +++++++++---------
2 files changed, 23 insertions(+), 10 deletions(-)
diff --git a/tests/conftest.py b/tests/conftest.py
index a2db04f..8166ff9 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -6,6 +6,7 @@ import io
import logging
import os
import pathlib
+import re
import sys
import threading
import time
@@ -57,12 +58,21 @@ if sys.version_info >= (3, 6):
# Also patch the "severity" attribute because there is a parsing bug in the plugin.
output.severity = output.severity.replace(", /", "")
+ def _fix_builtins_uppercase(item: YamlTestItem):
+ """Adapt case of builtins from the expected output for Python 3.6 to 3.8."""
+ for output in item.expected_output:
+ for builtin in ["dict", "list", "set", "tuple"]:
+ # Quite hacky, but should work for all tested cases.
+ pattern = re.compile(r"(?<![a-zA-Z0-9.])" + builtin + r"\[")
+ replacement = builtin.capitalize() + "["
+ output.message = pattern.sub(replacement, output.message)
+ output.severity = pattern.sub(replacement, output.severity)
+
def _add_mypy_config(item: YamlTestItem):
"""Add some extra options to the mypy configuration for Python 3.7+."""
item.additional_mypy_config += "\n".join(
[
"show_error_codes = false",
- "force_uppercase_builtins = true",
"force_union_syntax = true",
]
)
@@ -78,6 +88,9 @@ if sys.version_info >= (3, 6):
else:
_fix_positional_only_args(item)
+ if sys.version_info < (3, 9):
+ _fix_builtins_uppercase(item)
+
@contextlib.contextmanager
def new_event_loop_context():
diff --git a/tests/typesafety/test_logger.yml b/tests/typesafety/test_logger.yml
index 319845f..82ddf6f 100644
--- a/tests/typesafety/test_logger.yml
+++ b/tests/typesafety/test_logger.yml
@@ -205,7 +205,7 @@
level = logger.level("INFO")
reveal_type(level)
out: |
- main:4: note: Revealed type is "Tuple[builtins.str, builtins.int, builtins.str, builtins.str, fallback=loguru.Level]"
+ main:4: note: Revealed type is "tuple[builtins.str, builtins.int, builtins.str, builtins.str, fallback=loguru.Level]"
- case: level_set
main: |
@@ -214,7 +214,7 @@
level = logger.level("FOO", no=11, icon="!", color="<blue>")
reveal_type(level)
out: |
- main:4: note: Revealed type is "Tuple[builtins.str, builtins.int, builtins.str, builtins.str, fallback=loguru.Level]"
+ main:4: note: Revealed type is "tuple[builtins.str, builtins.int, builtins.str, builtins.str, fallback=loguru.Level]"
- case: level_update
main: |
@@ -223,7 +223,7 @@
level = logger.level("INFO", color="<blue>")
reveal_type(level)
out: |
- main:4: note: Revealed type is "Tuple[builtins.str, builtins.int, builtins.str, builtins.str, fallback=loguru.Level]"
+ main:4: note: Revealed type is "tuple[builtins.str, builtins.int, builtins.str, builtins.str, fallback=loguru.Level]"
- case: enable_and_disable_logger
main: |
@@ -285,9 +285,9 @@
out: |
main:2: error: No overload variant of "add" of "Logger" matches argument types "Callable[[Any], None]", "int"
main:2: note: Possible overload variants:
- main:2: note: def add(self, sink: Union[TextIO, Writable, Callable[[Message], None], Handler], *, level: Union[str, int] = ..., format: Union[str, Callable[[Record], str]] = ..., filter: Union[str, Callable[[Record], bool], Dict[Optional[str], Union[str, int, bool]], None] = ..., colorize: Optional[bool] = ..., serialize: bool = ..., backtrace: bool = ..., diagnose: bool = ..., enqueue: bool = ..., context: Union[str, BaseContext, None] = ..., catch: bool = ...) -> int
- main:2: note: def add(self, sink: Callable[[Message], Awaitable[None]], *, level: Union[str, int] = ..., format: Union[str, Callable[[Record], str]] = ..., filter: Union[str, Callable[[Record], bool], Dict[Optional[str], Union[str, int, bool]], None] = ..., colorize: Optional[bool] = ..., serialize: bool = ..., backtrace: bool = ..., diagnose: bool = ..., enqueue: bool = ..., catch: bool = ..., context: Union[str, BaseContext, None] = ..., loop: Optional[AbstractEventLoop] = ...) -> int
- main:2: note: def add(self, sink: Union[str, PathLike[str]], *, level: Union[str, int] = ..., format: Union[str, Callable[[Record], str]] = ..., filter: Union[str, Callable[[Record], bool], Dict[Optional[str], Union[str, int, bool]], None] = ..., colorize: Optional[bool] = ..., serialize: bool = ..., backtrace: bool = ..., diagnose: bool = ..., enqueue: bool = ..., context: Union[str, BaseContext, None] = ..., catch: bool = ..., rotation: Union[str, int, time, timedelta, Callable[[Message, TextIO], bool], None] = ..., retention: Union[str, int, timedelta, Callable[[List[str]], None], None] = ..., compression: Union[str, Callable[[str], None], None] = ..., delay: bool = ..., watch: bool = ..., mode: str = ..., buffering: int = ..., encoding: str = ..., errors: Optional[str] = ..., newline: Optional[str] = ..., closefd: bool = ..., opener: Optional[Callable[[str, int], int]] = ...) -> int
+ main:2: note: def add(self, sink: Union[TextIO, Writable, Callable[[Message], None], Handler], *, level: Union[str, int] = ..., format: Union[str, Callable[[Record], str]] = ..., filter: Union[str, Callable[[Record], bool], dict[Optional[str], Union[str, int, bool]], None] = ..., colorize: Optional[bool] = ..., serialize: bool = ..., backtrace: bool = ..., diagnose: bool = ..., enqueue: bool = ..., context: Union[str, BaseContext, None] = ..., catch: bool = ...) -> int
+ main:2: note: def add(self, sink: Callable[[Message], Awaitable[None]], *, level: Union[str, int] = ..., format: Union[str, Callable[[Record], str]] = ..., filter: Union[str, Callable[[Record], bool], dict[Optional[str], Union[str, int, bool]], None] = ..., colorize: Optional[bool] = ..., serialize: bool = ..., backtrace: bool = ..., diagnose: bool = ..., enqueue: bool = ..., catch: bool = ..., context: Union[str, BaseContext, None] = ..., loop: Optional[AbstractEventLoop] = ...) -> int
+ main:2: note: def add(self, sink: Union[str, PathLike[str]], *, level: Union[str, int] = ..., format: Union[str, Callable[[Record], str]] = ..., filter: Union[str, Callable[[Record], bool], dict[Optional[str], Union[str, int, bool]], None] = ..., colorize: Optional[bool] = ..., serialize: bool = ..., backtrace: bool = ..., diagnose: bool = ..., enqueue: bool = ..., context: Union[str, BaseContext, None] = ..., catch: bool = ..., rotation: Union[str, int, time, timedelta, Callable[[Message, TextIO], bool], None] = ..., retention: Union[str, int, timedelta, Callable[[list[str]], None], None] = ..., compression: Union[str, Callable[[str], None], None] = ..., delay: bool = ..., watch: bool = ..., mode: str = ..., buffering: int = ..., encoding: str = ..., errors: Optional[str] = ..., newline: Optional[str] = ..., closefd: bool = ..., opener: Optional[Callable[[str, int], int]] = ...) -> int
- case: invalid_logged_object_formatting
main: |
@@ -310,8 +310,8 @@
extra=[1],
)
out: |
- main:3: error: List item 0 has incompatible type "Dict[str, str]"; expected "Union[BasicHandlerConfig, FileHandlerConfig, AsyncHandlerConfig]"
+ main:3: error: List item 0 has incompatible type "dict[str, str]"; expected "Union[BasicHandlerConfig, FileHandlerConfig, AsyncHandlerConfig]"
main:4: error: Extra key "baz" for TypedDict "LevelConfig"
main:5: error: Argument "patcher" to "configure" of "Logger" has incompatible type "int"; expected "Optional[Callable[[Record], None]]"
- main:6: error: List item 0 has incompatible type "Dict[str, str]"; expected "Tuple[Optional[str], bool]"
- main:7: error: Argument "extra" to "configure" of "Logger" has incompatible type "List[int]"; expected "Optional[Dict[Any, Any]]"
+ main:6: error: List item 0 has incompatible type "dict[str, str]"; expected "tuple[Optional[str], bool]"
+ main:7: error: Argument "extra" to "configure" of "Logger" has incompatible type "list[int]"; expected "Optional[dict[Any, Any]]"
|