zstdlib 0.3.0__tar.gz → 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {zstdlib-0.3.0 → zstdlib-0.4.0}/PKG-INFO +1 -1
- {zstdlib-0.3.0 → zstdlib-0.4.0}/pyproject.toml +3 -2
- {zstdlib-0.3.0 → zstdlib-0.4.0}/tests/log/base.py +5 -5
- {zstdlib-0.3.0 → zstdlib-0.4.0}/tests/log/test_cute.py +1 -1
- {zstdlib-0.3.0 → zstdlib-0.4.0}/tests/test_enum.py +2 -2
- {zstdlib-0.3.0 → zstdlib-0.4.0}/tests/test_frozen.py +8 -2
- {zstdlib-0.3.0 → zstdlib-0.4.0}/zstdlib/__init__.py +1 -1
- {zstdlib-0.3.0 → zstdlib-0.4.0}/zstdlib/ansi.py +33 -37
- {zstdlib-0.3.0 → zstdlib-0.4.0}/zstdlib/enum.py +4 -4
- {zstdlib-0.3.0 → zstdlib-0.4.0}/zstdlib/frozen.py +0 -1
- {zstdlib-0.3.0 → zstdlib-0.4.0}/zstdlib/io.py +7 -16
- {zstdlib-0.3.0 → zstdlib-0.4.0}/zstdlib/log/cute.py +10 -8
- {zstdlib-0.3.0 → zstdlib-0.4.0}/zstdlib/log/trace.py +1 -1
- {zstdlib-0.3.0 → zstdlib-0.4.0}/zstdlib/singleton.py +3 -4
- {zstdlib-0.3.0 → zstdlib-0.4.0}/zstdlib.egg-info/PKG-INFO +1 -1
- {zstdlib-0.3.0 → zstdlib-0.4.0}/LICENSE +0 -0
- {zstdlib-0.3.0 → zstdlib-0.4.0}/README.md +0 -0
- {zstdlib-0.3.0 → zstdlib-0.4.0}/setup.cfg +0 -0
- {zstdlib-0.3.0 → zstdlib-0.4.0}/tests/__init__.py +0 -0
- {zstdlib-0.3.0 → zstdlib-0.4.0}/tests/log/__init__.py +0 -0
- {zstdlib-0.3.0 → zstdlib-0.4.0}/tests/log/test_trace.py +0 -0
- {zstdlib-0.3.0 → zstdlib-0.4.0}/tests/not_set.py +0 -0
- {zstdlib-0.3.0 → zstdlib-0.4.0}/tests/test_ansi.py +0 -0
- {zstdlib-0.3.0 → zstdlib-0.4.0}/tests/test_io.py +0 -0
- {zstdlib-0.3.0 → zstdlib-0.4.0}/tests/test_singleton.py +0 -0
- {zstdlib-0.3.0 → zstdlib-0.4.0}/zstdlib/log/__init__.py +0 -0
- {zstdlib-0.3.0 → zstdlib-0.4.0}/zstdlib/not_set.py +0 -0
- {zstdlib-0.3.0 → zstdlib-0.4.0}/zstdlib/py.typed +0 -0
- {zstdlib-0.3.0 → zstdlib-0.4.0}/zstdlib.egg-info/SOURCES.txt +0 -0
- {zstdlib-0.3.0 → zstdlib-0.4.0}/zstdlib.egg-info/dependency_links.txt +0 -0
- {zstdlib-0.3.0 → zstdlib-0.4.0}/zstdlib.egg-info/top_level.txt +0 -0
|
@@ -50,14 +50,15 @@ disable = [
|
|
|
50
50
|
|
|
51
51
|
[tool.black]
|
|
52
52
|
line-length = 110
|
|
53
|
-
target-version = ["
|
|
53
|
+
target-version = ["py314"]
|
|
54
54
|
|
|
55
55
|
[tool.ruff]
|
|
56
56
|
line-length = 110
|
|
57
57
|
[tool.ruff.lint]
|
|
58
|
-
ignore=["E731"]
|
|
58
|
+
ignore=["E731", "I001"]
|
|
59
59
|
[tool.ruff.lint.per-file-ignores]
|
|
60
60
|
"__init__.py" = ["F401", "F403"]
|
|
61
|
+
"tests/*" = ["DTZ005"]
|
|
61
62
|
|
|
62
63
|
[tool.bandit]
|
|
63
64
|
skips = ["B101", "B104", "B201"]
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
from logging.handlers import QueueHandler
|
|
2
2
|
from contextlib import contextmanager
|
|
3
3
|
from collections.abc import Callable
|
|
4
|
+
from typing import ClassVar, Any
|
|
4
5
|
from threading import Lock
|
|
5
|
-
from typing import Any
|
|
6
6
|
import logging
|
|
7
7
|
import queue
|
|
8
8
|
|
|
@@ -20,12 +20,12 @@ class LeftBase:
|
|
|
20
20
|
A base class for tests that hijack loggers
|
|
21
21
|
"""
|
|
22
22
|
|
|
23
|
-
_hijacked: set[logging.Logger] = set() # Set of all loggers that have ever been hijacked
|
|
24
|
-
_qmap: dict[logging.Logger, queue.Queue[logging.LogRecord]] = {}
|
|
25
|
-
_lb_old: dict[logging.Logger, list[logging.Handler]] = {}
|
|
23
|
+
_hijacked: ClassVar[set[logging.Logger]] = set() # Set of all loggers that have ever been hijacked
|
|
24
|
+
_qmap: ClassVar[dict[logging.Logger, queue.Queue[logging.LogRecord]]] = {}
|
|
25
|
+
_lb_old: ClassVar[dict[logging.Logger, list[logging.Handler]]] = {}
|
|
26
26
|
_lb_lock = Lock()
|
|
27
27
|
|
|
28
|
-
messages: dict[logging.Logger, list[str]] = {}
|
|
28
|
+
messages: ClassVar[dict[logging.Logger, list[str]]] = {}
|
|
29
29
|
|
|
30
30
|
@classmethod
|
|
31
31
|
def hijack(cls, name: str, reuse: bool = False, fmt: logging.Formatter | None = None):
|
|
@@ -106,7 +106,7 @@ class TestCuteFormatter(LeftBase, unittest.TestCase):
|
|
|
106
106
|
try:
|
|
107
107
|
raise ValueError(name)
|
|
108
108
|
except ValueError:
|
|
109
|
-
log.
|
|
109
|
+
log.exception("test")
|
|
110
110
|
spt = self.messages[log][0].split("\n")
|
|
111
111
|
self.assertGreater(len(spt), 2)
|
|
112
112
|
self.assertEqual("Traceback (most recent call last):", spt[1].strip())
|
|
@@ -24,7 +24,7 @@ class TestEnumType(unittest.TestCase):
|
|
|
24
24
|
class ET1(metaclass=EnumType, dupes_ok=True):
|
|
25
25
|
a: int = 5
|
|
26
26
|
b: int = 5
|
|
27
|
-
c: dict = {}
|
|
27
|
+
c: dict = {} # noqa: RUF012
|
|
28
28
|
|
|
29
29
|
with self.assertRaises(ValueError):
|
|
30
30
|
|
|
@@ -35,7 +35,7 @@ class TestEnumType(unittest.TestCase):
|
|
|
35
35
|
with self.assertRaises(TypeError):
|
|
36
36
|
|
|
37
37
|
class ET3(metaclass=EnumType):
|
|
38
|
-
a: dict = {}
|
|
38
|
+
a: dict = {} # noqa: RUF012
|
|
39
39
|
|
|
40
40
|
def test_type_check(self) -> None:
|
|
41
41
|
class ET1(metaclass=EnumType, type_check=set()):
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# pylint: disable=missing-module-docstring,missing-class-docstring,missing-function-docstring,unused-variable,attribute-defined-outside-init
|
|
2
|
+
from sys import version_info
|
|
2
3
|
import unittest
|
|
3
4
|
|
|
4
5
|
from zstdlib.frozen import Freezable, frozen
|
|
@@ -104,10 +105,15 @@ class TestFrozen(unittest.TestCase):
|
|
|
104
105
|
f1 = F1()
|
|
105
106
|
self.assertEqual(f1.__init__.__doc__.strip(), "init doc")
|
|
106
107
|
self.assertEqual(f1.__init__.__name__, "__init__")
|
|
107
|
-
self.assertEqual(f1.__init__.__qualname__, "TestFrozen.test_metadata.<locals>.
|
|
108
|
+
self.assertEqual(f1.__init__.__qualname__, "TestFrozen.test_metadata.<locals>.F1.__init__")
|
|
108
109
|
self.assertTupleEqual(f1.__init__.__defaults__, (1,))
|
|
109
110
|
self.assertDictEqual(f1.__init__.__kwdefaults__, {"b": False})
|
|
110
|
-
|
|
111
|
+
if version_info < (3, 13, 0.1) or hasattr(f1.__init__, "__annotations__"):
|
|
112
|
+
self.assertDictEqual(f1.__init__.__annotations__, {"a": int, "b": bool, "return": None})
|
|
113
|
+
else: # annotations changed in 3.14, .__annotations__ *might* not exist
|
|
114
|
+
from annotationlib import get_annotations
|
|
115
|
+
|
|
116
|
+
self.assertDictEqual(get_annotations(f1.__init__), {"a": int, "b": bool, "return": None})
|
|
111
117
|
|
|
112
118
|
def test_frozen_custom(self):
|
|
113
119
|
@frozen("custom")
|
|
@@ -3,7 +3,6 @@ from functools import cache
|
|
|
3
3
|
from typing import Self
|
|
4
4
|
import re
|
|
5
5
|
|
|
6
|
-
|
|
7
6
|
MODIFIERS = ("bold", "dim", "italic", "underline", "blinking", "inverse", "hidden", "strikethrough")
|
|
8
7
|
|
|
9
8
|
_PREFIX = "\033["
|
|
@@ -31,7 +30,7 @@ class RawColor:
|
|
|
31
30
|
A class that represents a color with all possible modifiers
|
|
32
31
|
"""
|
|
33
32
|
|
|
34
|
-
__slots__ = ("
|
|
33
|
+
__slots__ = ("background", "bright", "color", "value")
|
|
35
34
|
|
|
36
35
|
def __init__(self, color: PureColor | str | int, *, bright: bool = False, background: bool = False):
|
|
37
36
|
self.color = PureColor(getattr(PureColor, color) if isinstance(color, str) else color)
|
|
@@ -39,15 +38,43 @@ class RawColor:
|
|
|
39
38
|
self.background = background
|
|
40
39
|
self.value = self.color.value + (10 if self.background else 0) + (60 if self.bright else 0)
|
|
41
40
|
|
|
41
|
+
@classmethod
|
|
42
|
+
@cache
|
|
43
|
+
def _parse_color(cls, item: str) -> str:
|
|
44
|
+
"""Construct a color following the rules defined by Color"""
|
|
45
|
+
item = item.lower()
|
|
46
|
+
if "bright_bg" in item:
|
|
47
|
+
raise ValueError("bg_ must precede bright_ in color specification")
|
|
48
|
+
pat = f"(:?bright_)?({'|'.join(list(PureColor.__members__))})"
|
|
49
|
+
shx = re.findall(f"(bg_){pat}", item)
|
|
50
|
+
if len(shx) > 1:
|
|
51
|
+
raise ValueError(f"Multiple background colors specified in {item}")
|
|
52
|
+
bg = None
|
|
53
|
+
if len(shx) == 1:
|
|
54
|
+
item = item.replace("".join(shx[0]), "")
|
|
55
|
+
bg = cls(shx[0][-1], bright="bright_" in shx[0], background=True)
|
|
56
|
+
shx = re.findall(pat, item)
|
|
57
|
+
if len(shx) > 1:
|
|
58
|
+
raise ValueError(f"Multiple foreground colors specified in {item}")
|
|
59
|
+
fg = None
|
|
60
|
+
if len(shx) == 1:
|
|
61
|
+
item = item.replace("".join(shx[0]), "")
|
|
62
|
+
fg = cls(shx[0][-1], bright="bright_" in shx[0])
|
|
63
|
+
# Determine modifiers and construct the color
|
|
64
|
+
attrs = [i for i in item.split("_") if i]
|
|
65
|
+
if any(bad := [i for i in attrs if i not in MODIFIERS]):
|
|
66
|
+
raise ValueError(f"Unknown modifiers(s): {', '.join(bad)}")
|
|
67
|
+
return _generate_code(fg, bg, {i: True for i in MODIFIERS if i in attrs})
|
|
68
|
+
|
|
42
69
|
|
|
43
70
|
class _ColorMeta(type):
|
|
44
71
|
"""
|
|
45
72
|
A metaclass that implements __getattr__ at the class level for Color
|
|
46
73
|
"""
|
|
47
74
|
|
|
48
|
-
def __getattr__(cls, item: str) ->
|
|
75
|
+
def __getattr__(cls, item: str) -> Color:
|
|
49
76
|
try:
|
|
50
|
-
return cls(code=_parse_color(item))
|
|
77
|
+
return cls(code=RawColor._parse_color(item))
|
|
51
78
|
except ValueError as e:
|
|
52
79
|
raise AttributeError(str(e)) from e
|
|
53
80
|
|
|
@@ -91,7 +118,7 @@ class Color(metaclass=_ColorMeta):
|
|
|
91
118
|
elif isinstance(fmt, RawColor):
|
|
92
119
|
self.code = f"{_PREFIX}{fmt.value}m"
|
|
93
120
|
else:
|
|
94
|
-
self.code = _parse_color(fmt) if isinstance(fmt, str) else fmt.code
|
|
121
|
+
self.code = RawColor._parse_color(fmt) if isinstance(fmt, str) else fmt.code
|
|
95
122
|
|
|
96
123
|
def __call__(self, string: str) -> str:
|
|
97
124
|
"""
|
|
@@ -117,7 +144,7 @@ class Color(metaclass=_ColorMeta):
|
|
|
117
144
|
"""
|
|
118
145
|
:return: The ansi color code this object represents
|
|
119
146
|
"""
|
|
120
|
-
return f"<Color {
|
|
147
|
+
return f"<Color {self.code!r}>"
|
|
121
148
|
|
|
122
149
|
@classmethod
|
|
123
150
|
def factory(
|
|
@@ -145,34 +172,3 @@ def _generate_code(
|
|
|
145
172
|
if background:
|
|
146
173
|
ints.append(background.value)
|
|
147
174
|
return f"{_PREFIX}{';'.join(map(str, ints))}m"
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
@cache
|
|
151
|
-
def _parse_color(item: str) -> str:
|
|
152
|
-
"""
|
|
153
|
-
Construct a color following the rules defined by Color
|
|
154
|
-
This method is not a classmethod since python3.13 deprecates mixing classmethod and cache
|
|
155
|
-
"""
|
|
156
|
-
item = item.lower()
|
|
157
|
-
if "bright_bg" in item:
|
|
158
|
-
raise ValueError("bg_ must precede bright_ in color specification")
|
|
159
|
-
pat = f"(:?bright_)?({'|'.join(list(PureColor.__members__))})"
|
|
160
|
-
shx = re.findall(f"(bg_){pat}", item)
|
|
161
|
-
if len(shx) > 1:
|
|
162
|
-
raise ValueError(f"Multiple background colors specified in {item}")
|
|
163
|
-
bg: RawColor | None = None
|
|
164
|
-
if len(shx) == 1:
|
|
165
|
-
item = item.replace("".join(shx[0]), "")
|
|
166
|
-
bg = RawColor(shx[0][-1], bright="bright_" in shx[0], background=True)
|
|
167
|
-
shx = re.findall(pat, item)
|
|
168
|
-
if len(shx) > 1:
|
|
169
|
-
raise ValueError(f"Multiple foreground colors specified in {item}")
|
|
170
|
-
fg: RawColor | None = None
|
|
171
|
-
if len(shx) == 1:
|
|
172
|
-
item = item.replace("".join(shx[0]), "")
|
|
173
|
-
fg = RawColor(shx[0][-1], bright="bright_" in shx[0])
|
|
174
|
-
# Determine modifiers and construct the color
|
|
175
|
-
attrs = [i for i in item.split("_") if i]
|
|
176
|
-
if any(bad := [i for i in attrs if i not in MODIFIERS]):
|
|
177
|
-
raise ValueError(f"Unknown modifiers(s): {', '.join(bad)}")
|
|
178
|
-
return _generate_code(fg, bg, {i: True for i in MODIFIERS if i in attrs})
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from collections.abc import Iterator
|
|
2
|
-
from typing import
|
|
2
|
+
from typing import ClassVar, Any
|
|
3
3
|
import annotationlib
|
|
4
4
|
|
|
5
5
|
|
|
@@ -22,7 +22,7 @@ class EnumType(type):
|
|
|
22
22
|
"""
|
|
23
23
|
|
|
24
24
|
_AUTO_PREFIX = "Enum_Auto_"
|
|
25
|
-
_TC_DEFAULT: set[type | None] = {int, str, float, bool, complex, bytes, None, type(None)}
|
|
25
|
+
_TC_DEFAULT: ClassVar[set[type | None]] = {int, str, float, bool, complex, bytes, None, type(None)}
|
|
26
26
|
|
|
27
27
|
class _AutoValue:
|
|
28
28
|
"""A class representing an automatically assigned enum value"""
|
|
@@ -41,7 +41,7 @@ class EnumType(type):
|
|
|
41
41
|
mcs,
|
|
42
42
|
attrs: dict,
|
|
43
43
|
dupes_ok: bool,
|
|
44
|
-
ans: dict[str, type |
|
|
44
|
+
ans: dict[str, type | None],
|
|
45
45
|
) -> dict[str, tuple[type | None, Any]]:
|
|
46
46
|
"""
|
|
47
47
|
Generate enum entries from attrs, checking for duplicates and missing annotations
|
|
@@ -163,4 +163,4 @@ def values(enum: Any) -> tuple[Any, ...]:
|
|
|
163
163
|
return tuple(k[1] for k in enum.__entries__.values()) # type: ignore[attr-defined]
|
|
164
164
|
|
|
165
165
|
|
|
166
|
-
__all__ = ("Enum", "EnumType", "
|
|
166
|
+
__all__ = ("Enum", "EnumType", "auto", "entries", "values")
|
|
@@ -1,19 +1,10 @@
|
|
|
1
|
-
from io import
|
|
2
|
-
|
|
3
|
-
TextIOBase as _PyRawTextIOBase,
|
|
4
|
-
RawIOBase as _PyRawIOBase,
|
|
5
|
-
BufferedIOBase as _PyBufferedIOBase,
|
|
6
|
-
)
|
|
1
|
+
from io import BufferedIOBase, TextIOBase, RawIOBase, IOBase
|
|
2
|
+
from weakref import WeakKeyDictionary
|
|
7
3
|
from threading import RLock
|
|
8
4
|
from itertools import chain
|
|
9
5
|
from typing import Self
|
|
10
|
-
import weakref
|
|
11
6
|
|
|
12
|
-
|
|
13
|
-
__all__ = ("TextIO", "BinaryIO", "io")
|
|
14
|
-
|
|
15
|
-
type _BinaryBase = _PyRawIOBase | _PyBufferedIOBase
|
|
16
|
-
type _TextBase = _PyRawTextIOBase
|
|
7
|
+
__all__ = ("BinaryIO", "TextIO", "io")
|
|
17
8
|
|
|
18
9
|
|
|
19
10
|
class ProtectedFile:
|
|
@@ -52,8 +43,8 @@ class _IOWrapperBase[T: (str, bytes)]:
|
|
|
52
43
|
Note: This class takes ownership of the input object, do not use it elsewhere
|
|
53
44
|
"""
|
|
54
45
|
|
|
55
|
-
__slots__ = ("
|
|
56
|
-
_instances:
|
|
46
|
+
__slots__ = ("_buffer", "_eof", "f", "lock")
|
|
47
|
+
_instances: WeakKeyDictionary[IOBase, Self] = WeakKeyDictionary()
|
|
57
48
|
_wr_lock = RLock()
|
|
58
49
|
|
|
59
50
|
def __new__(cls, f: IOBase, binary: bool) -> Self:
|
|
@@ -189,8 +180,8 @@ class _IOWrapperBase[T: (str, bytes)]:
|
|
|
189
180
|
|
|
190
181
|
def _mode(f: IOBase, binary: bool | None) -> bool:
|
|
191
182
|
mode = getattr(f, "mode", "")
|
|
192
|
-
binary = binary or "b" in mode or isinstance(f, (
|
|
193
|
-
text = (binary is False) or (mode and "b" not in mode) or isinstance(f,
|
|
183
|
+
binary = binary or "b" in mode or isinstance(f, (RawIOBase, BufferedIOBase))
|
|
184
|
+
text = (binary is False) or (mode and "b" not in mode) or isinstance(f, TextIOBase)
|
|
194
185
|
if not text and not binary:
|
|
195
186
|
raise TypeError("Cannot determine if IO object is text or binary")
|
|
196
187
|
if text and binary:
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
1
|
from logging import CRITICAL, ERROR, WARNING, INFO, DEBUG, Formatter
|
|
2
|
+
from typing import TYPE_CHECKING, ClassVar
|
|
3
3
|
from collections import defaultdict
|
|
4
|
-
from typing import TYPE_CHECKING
|
|
5
4
|
from zlib import adler32
|
|
6
5
|
from copy import copy
|
|
7
6
|
|
|
@@ -16,9 +15,9 @@ class CuteFormatter(Formatter):
|
|
|
16
15
|
A log formatter that can print log messages with colors.
|
|
17
16
|
"""
|
|
18
17
|
|
|
19
|
-
__slots__ = ("
|
|
20
|
-
DEFAULT_CUTE_WIDTHS: dict[str, int] = {"cute_levelname": 8, "cute_time": 23, "cute_name": 12}
|
|
21
|
-
DEFAULT_LEVEL_COLORS: dict[int, Color] = {
|
|
18
|
+
__slots__ = ("_cmap", "_color", "_dim_level", "_lvl_cmap", "_name_width", "colored")
|
|
19
|
+
DEFAULT_CUTE_WIDTHS: ClassVar[dict[str, int]] = {"cute_levelname": 8, "cute_time": 23, "cute_name": 12}
|
|
20
|
+
DEFAULT_LEVEL_COLORS: ClassVar[dict[int, Color]] = {
|
|
22
21
|
INFO: Color.blue,
|
|
23
22
|
WARNING: Color.yellow,
|
|
24
23
|
ERROR: Color.red,
|
|
@@ -32,9 +31,9 @@ class CuteFormatter(Formatter):
|
|
|
32
31
|
*args,
|
|
33
32
|
colored: bool = True,
|
|
34
33
|
dim_level: int = DEBUG,
|
|
35
|
-
colors: dict[str, Color] =
|
|
36
|
-
level_colors: dict[int, Color] =
|
|
37
|
-
cute_widths: dict[str, int] =
|
|
34
|
+
colors: dict[str, Color] | None = None,
|
|
35
|
+
level_colors: dict[int, Color] | None = None,
|
|
36
|
+
cute_widths: dict[str, int] | None = None,
|
|
38
37
|
**kwargs,
|
|
39
38
|
):
|
|
40
39
|
"""
|
|
@@ -52,6 +51,9 @@ class CuteFormatter(Formatter):
|
|
|
52
51
|
:param cute_widths: The widths of the cute_ columns in the log message
|
|
53
52
|
:param kwargs: Passed to logging.Formatter
|
|
54
53
|
"""
|
|
54
|
+
colors = {} if colors is None else colors
|
|
55
|
+
level_colors = {} if level_colors is None else level_colors
|
|
56
|
+
cute_widths = {} if cute_widths is None else cute_widths
|
|
55
57
|
super().__init__(fmt, *args, **kwargs)
|
|
56
58
|
self._dim_level: int = dim_level
|
|
57
59
|
self._cmap: dict[str, Color] = dict(colors)
|
|
@@ -46,7 +46,7 @@ def _define_logging_trace(method: str, value: int) -> None:
|
|
|
46
46
|
has no handlers, call basicConfig() to add a console handler with a
|
|
47
47
|
pre-defined format.
|
|
48
48
|
"""
|
|
49
|
-
logging.log(value, msg, *args, **kwargs)
|
|
49
|
+
logging.log(value, msg, *args, **kwargs) # noqa: LOG015
|
|
50
50
|
|
|
51
51
|
setattr(logging, method, trace)
|
|
52
52
|
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
from typing import TypeVar, Self, Any, cast
|
|
1
|
+
from typing import ClassVar, TypeVar, Self, Any, cast
|
|
2
2
|
from collections import defaultdict
|
|
3
3
|
from threading import RLock
|
|
4
4
|
from functools import cache
|
|
5
5
|
|
|
6
|
-
|
|
7
6
|
T = TypeVar("T")
|
|
8
7
|
|
|
9
8
|
|
|
@@ -26,9 +25,9 @@ class _SingletonType(type):
|
|
|
26
25
|
"""
|
|
27
26
|
|
|
28
27
|
_disallow_init_subclass = False # If True, disallow __init_subclass__ in __new__'s attrs
|
|
29
|
-
_instances: dict[type, Any] = {} # Fully constructed and initialized singleton types
|
|
28
|
+
_instances: ClassVar[dict[type, Any]] = {} # Fully constructed and initialized singleton types
|
|
30
29
|
# Lock is preferred to RLock, but could deadlock if user write a constructor that invokes itself
|
|
31
|
-
_cls_locks: dict[type, RLock] = defaultdict(RLock)
|
|
30
|
+
_cls_locks: ClassVar[dict[type, RLock]] = defaultdict(RLock)
|
|
32
31
|
_lock = RLock()
|
|
33
32
|
|
|
34
33
|
def __new__(mcs, name, bases, attrs, **kwargs):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|