dycw-utilities 0.168.3__py3-none-any.whl → 0.168.4__py3-none-any.whl
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.
Potentially problematic release.
This version of dycw-utilities might be problematic. Click here for more details.
- {dycw_utilities-0.168.3.dist-info → dycw_utilities-0.168.4.dist-info}/METADATA +4 -4
- {dycw_utilities-0.168.3.dist-info → dycw_utilities-0.168.4.dist-info}/RECORD +6 -7
- utilities/__init__.py +1 -1
- utilities/typed_settings.py +0 -152
- {dycw_utilities-0.168.3.dist-info → dycw_utilities-0.168.4.dist-info}/WHEEL +0 -0
- {dycw_utilities-0.168.3.dist-info → dycw_utilities-0.168.4.dist-info}/entry_points.txt +0 -0
- {dycw_utilities-0.168.3.dist-info → dycw_utilities-0.168.4.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dycw-utilities
|
|
3
|
-
Version: 0.168.
|
|
3
|
+
Version: 0.168.4
|
|
4
4
|
Author-email: Derek Wan <d.wan@icloud.com>
|
|
5
5
|
License-File: LICENSE
|
|
6
6
|
Requires-Python: >=3.12
|
|
7
7
|
Requires-Dist: atomicwrites<1.5,>=1.4.1
|
|
8
8
|
Requires-Dist: typing-extensions<4.16,>=4.15.0
|
|
9
9
|
Requires-Dist: tzlocal<5.4,>=5.3.1
|
|
10
|
-
Requires-Dist: whenever<0.10,>=0.9.
|
|
10
|
+
Requires-Dist: whenever<0.10,>=0.9.2
|
|
11
11
|
Provides-Extra: logging
|
|
12
12
|
Requires-Dist: coloredlogs<15.1,>=15.0.1; extra == 'logging'
|
|
13
13
|
Provides-Extra: test
|
|
14
14
|
Requires-Dist: dycw-pytest-only<2.2,>=2.1.1; extra == 'test'
|
|
15
|
-
Requires-Dist: hypothesis<6.141,>=6.140.
|
|
15
|
+
Requires-Dist: hypothesis<6.141,>=6.140.3; extra == 'test'
|
|
16
16
|
Requires-Dist: pytest-asyncio<1.3,>=1.2.0; extra == 'test'
|
|
17
17
|
Requires-Dist: pytest-cov<7.1,>=7.0.0; extra == 'test'
|
|
18
18
|
Requires-Dist: pytest-instafail<0.6,>=0.5.0; extra == 'test'
|
|
19
|
-
Requires-Dist: pytest-lazy-fixtures<1.
|
|
19
|
+
Requires-Dist: pytest-lazy-fixtures<1.5,>=1.4.0; extra == 'test'
|
|
20
20
|
Requires-Dist: pytest-randomly<4.1,>=4.0.1; extra == 'test'
|
|
21
21
|
Requires-Dist: pytest-regressions<2.9,>=2.8.3; extra == 'test'
|
|
22
22
|
Requires-Dist: pytest-repeat<0.10,>=0.9.4; extra == 'test'
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
utilities/__init__.py,sha256=
|
|
1
|
+
utilities/__init__.py,sha256=x6cOFdPHlRzAKGeDLMvNM_wBBnw0yuamoyX4OmYbECY,60
|
|
2
2
|
utilities/aeventkit.py,sha256=OmDBhYGgbsKrB7cdC5FFpJHUatX9O76eTeKVVTksp2Y,12673
|
|
3
3
|
utilities/altair.py,sha256=nHdpWt8ZwdUwRQN970MvHd5bRWokNqzHcZQEdSHKRuE,9033
|
|
4
4
|
utilities/asyncio.py,sha256=60l1IwjnRGeaVphAFiwDIHyfKoZYKY-XGpptUxGiU-M,17034
|
|
@@ -79,7 +79,6 @@ utilities/text.py,sha256=7SvwcSR2l_5cOrm1samGnR4C-ZI6qyFLHLzSpO1zeHQ,13958
|
|
|
79
79
|
utilities/threading.py,sha256=GvBOp4CyhHfN90wGXZuA2VKe9fGzMaEa7oCl4f3nnPU,1009
|
|
80
80
|
utilities/timer.py,sha256=BGlwEVznx67scuLOUohyWJ4d5rTnwtk-IR4yLXFiNfo,2574
|
|
81
81
|
utilities/traceback.py,sha256=B_sc0TRUv-mGDnF-ek05nbqjmBiHr3-wvxliAqIF5hI,9608
|
|
82
|
-
utilities/typed_settings.py,sha256=WJikhgV_92GkjqdQQ2VxfVrwABE5d_Z6tczmcr3H57w,4581
|
|
83
82
|
utilities/types.py,sha256=IlRrCtPdLkGYVfpe-QIg2qNUgBr8OJNN7BhTKxnhh-M,18817
|
|
84
83
|
utilities/typing.py,sha256=QYoCIc71e_u5W-kBeiNzrD-GXxpLtMOGc9PqgZjMXeE,25274
|
|
85
84
|
utilities/tzdata.py,sha256=fgNVj66yUbCSI_-vrRVzSD3gtf-L_8IEJEPjP_Jel5Y,266
|
|
@@ -93,8 +92,8 @@ utilities/zoneinfo.py,sha256=tdIScrTB2-B-LH0ukb1HUXKooLknOfJNwHk10MuMYvA,3619
|
|
|
93
92
|
utilities/pytest_plugins/__init__.py,sha256=U4S_2y3zgLZVfMenHRaJFBW8yqh2mUBuI291LGQVOJ8,35
|
|
94
93
|
utilities/pytest_plugins/pytest_randomly.py,sha256=B1qYVlExGOxTywq2r1SMi5o7btHLk2PNdY_b1p98dkE,409
|
|
95
94
|
utilities/pytest_plugins/pytest_regressions.py,sha256=mnHYBfdprz50UGVkVzV1bZERZN5CFfoF8YbokGxdFwU,1639
|
|
96
|
-
dycw_utilities-0.168.
|
|
97
|
-
dycw_utilities-0.168.
|
|
98
|
-
dycw_utilities-0.168.
|
|
99
|
-
dycw_utilities-0.168.
|
|
100
|
-
dycw_utilities-0.168.
|
|
95
|
+
dycw_utilities-0.168.4.dist-info/METADATA,sha256=Po9OuIZ1OfNbLNOHnI38-vG210E3jNV08z5fpw-lWXw,1699
|
|
96
|
+
dycw_utilities-0.168.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
97
|
+
dycw_utilities-0.168.4.dist-info/entry_points.txt,sha256=BOD_SoDxwsfJYOLxhrSXhHP_T7iw-HXI9f2WVkzYxvQ,135
|
|
98
|
+
dycw_utilities-0.168.4.dist-info/licenses/LICENSE,sha256=gppZp16M6nSVpBbUBrNL6JuYfvKwZiKgV7XoKKsHzqo,1066
|
|
99
|
+
dycw_utilities-0.168.4.dist-info/RECORD,,
|
utilities/__init__.py
CHANGED
utilities/typed_settings.py
DELETED
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from dataclasses import dataclass
|
|
4
|
-
from functools import partial
|
|
5
|
-
from ipaddress import IPv4Address, IPv6Address
|
|
6
|
-
from os import environ
|
|
7
|
-
from pathlib import Path
|
|
8
|
-
from re import search
|
|
9
|
-
from typing import TYPE_CHECKING, Any, assert_never, override
|
|
10
|
-
from uuid import UUID
|
|
11
|
-
|
|
12
|
-
import typed_settings
|
|
13
|
-
from typed_settings import EnvLoader, FileLoader, find
|
|
14
|
-
from typed_settings.converters import TSConverter
|
|
15
|
-
from typed_settings.loaders import TomlFormat
|
|
16
|
-
from whenever import (
|
|
17
|
-
Date,
|
|
18
|
-
DateDelta,
|
|
19
|
-
DateTimeDelta,
|
|
20
|
-
MonthDay,
|
|
21
|
-
PlainDateTime,
|
|
22
|
-
Time,
|
|
23
|
-
TimeDelta,
|
|
24
|
-
YearMonth,
|
|
25
|
-
ZonedDateTime,
|
|
26
|
-
)
|
|
27
|
-
|
|
28
|
-
from utilities.iterables import always_iterable
|
|
29
|
-
from utilities.pathlib import to_path
|
|
30
|
-
from utilities.string import substitute_environ
|
|
31
|
-
|
|
32
|
-
if TYPE_CHECKING:
|
|
33
|
-
from collections.abc import Callable, Iterable
|
|
34
|
-
|
|
35
|
-
from typed_settings.loaders import Loader
|
|
36
|
-
from typed_settings.processors import Processor
|
|
37
|
-
|
|
38
|
-
from utilities.types import MaybeCallablePathLike, MaybeIterable, PathLike
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
type _ConverterItem = tuple[type[Any], Callable[..., Any]]
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
##
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
class ExtendedTSConverter(TSConverter):
|
|
48
|
-
"""An extension of the TSConverter for custom types."""
|
|
49
|
-
|
|
50
|
-
@override
|
|
51
|
-
def __init__(
|
|
52
|
-
self,
|
|
53
|
-
*,
|
|
54
|
-
resolve_paths: bool = True,
|
|
55
|
-
strlist_sep: str | Callable[[str], list] | None = ":",
|
|
56
|
-
extra: Iterable[_ConverterItem] = (),
|
|
57
|
-
) -> None:
|
|
58
|
-
super().__init__(resolve_paths=resolve_paths, strlist_sep=strlist_sep)
|
|
59
|
-
cases: list[_ConverterItem] = [
|
|
60
|
-
(Date, Date.parse_iso),
|
|
61
|
-
(DateDelta, DateDelta.parse_iso),
|
|
62
|
-
(DateTimeDelta, DateTimeDelta.parse_iso),
|
|
63
|
-
(IPv4Address, IPv4Address),
|
|
64
|
-
(IPv6Address, IPv6Address),
|
|
65
|
-
(MonthDay, MonthDay.parse_iso),
|
|
66
|
-
(Path, partial(_parse_path, resolve=resolve_paths, pwd=Path.cwd())),
|
|
67
|
-
(PlainDateTime, PlainDateTime.parse_iso),
|
|
68
|
-
(Time, Time.parse_iso),
|
|
69
|
-
(TimeDelta, TimeDelta.parse_iso),
|
|
70
|
-
(UUID, UUID),
|
|
71
|
-
(YearMonth, YearMonth.parse_iso),
|
|
72
|
-
(ZonedDateTime, ZonedDateTime.parse_iso),
|
|
73
|
-
*extra,
|
|
74
|
-
]
|
|
75
|
-
extras = {cls: _make_converter(cls, func) for cls, func in cases}
|
|
76
|
-
self.scalar_converters |= extras
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
def _make_converter[T](
|
|
80
|
-
cls: type[T], parser: Callable[[str], T], /
|
|
81
|
-
) -> Callable[[Any, type[Any]], Any]:
|
|
82
|
-
def hook(value: T | str, _: type[T] = cls, /) -> Any:
|
|
83
|
-
if not isinstance(value, (cls, str)): # pragma: no cover
|
|
84
|
-
msg = f"Invalid type {type(value).__name__!r}; expected '{cls.__name__}' or 'str'"
|
|
85
|
-
raise TypeError(msg)
|
|
86
|
-
if isinstance(value, str):
|
|
87
|
-
return parser(value)
|
|
88
|
-
return value
|
|
89
|
-
|
|
90
|
-
return hook
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
def _parse_path(
|
|
94
|
-
path: str, /, *, resolve: bool = False, pwd: MaybeCallablePathLike = Path.cwd
|
|
95
|
-
) -> Path:
|
|
96
|
-
path = substitute_environ(path, **environ)
|
|
97
|
-
match resolve:
|
|
98
|
-
case True:
|
|
99
|
-
return to_path(pwd).joinpath(path).resolve()
|
|
100
|
-
case False:
|
|
101
|
-
return Path(path)
|
|
102
|
-
case never:
|
|
103
|
-
assert_never(never)
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
##
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
_BASE_DIR: Path = Path()
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
def load_settings[T](
|
|
113
|
-
cls: type[T],
|
|
114
|
-
app_name: str,
|
|
115
|
-
/,
|
|
116
|
-
*,
|
|
117
|
-
filenames: MaybeIterable[str] = "settings.toml",
|
|
118
|
-
start_dir: PathLike | None = None,
|
|
119
|
-
loaders: MaybeIterable[Loader] | None = None,
|
|
120
|
-
processors: MaybeIterable[Processor] = (),
|
|
121
|
-
converters: Iterable[_ConverterItem] = (),
|
|
122
|
-
base_dir: Path = _BASE_DIR,
|
|
123
|
-
) -> T:
|
|
124
|
-
if not search(r"^[A-Za-z]+(?:_[A-Za-z]+)*$", app_name):
|
|
125
|
-
raise LoadSettingsError(appname=app_name)
|
|
126
|
-
filenames_use = list(always_iterable(filenames))
|
|
127
|
-
start_dir_use = None if start_dir is None else Path(start_dir)
|
|
128
|
-
files = [find(filename, start_dir=start_dir_use) for filename in filenames_use]
|
|
129
|
-
file_loader = FileLoader(formats={"*.toml": TomlFormat(app_name)}, files=files)
|
|
130
|
-
env_loader = EnvLoader(f"{app_name.upper()}__", nested_delimiter="__")
|
|
131
|
-
loaders_use: list[Loader] = [file_loader, env_loader]
|
|
132
|
-
if loaders is not None:
|
|
133
|
-
loaders_use.extend(always_iterable(loaders))
|
|
134
|
-
return typed_settings.load_settings(
|
|
135
|
-
cls,
|
|
136
|
-
loaders_use,
|
|
137
|
-
processors=list(always_iterable(processors)),
|
|
138
|
-
converter=ExtendedTSConverter(extra=converters),
|
|
139
|
-
base_dir=base_dir,
|
|
140
|
-
)
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
@dataclass(kw_only=True, slots=True)
|
|
144
|
-
class LoadSettingsError(Exception):
|
|
145
|
-
appname: str
|
|
146
|
-
|
|
147
|
-
@override
|
|
148
|
-
def __str__(self) -> str:
|
|
149
|
-
return f"Invalid app name; got {self.appname!r}"
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
__all__ = ["ExtendedTSConverter", "LoadSettingsError", "load_settings"]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|