dycw-utilities 0.148.5__py3-none-any.whl → 0.174.12__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.

Files changed (83) hide show
  1. dycw_utilities-0.174.12.dist-info/METADATA +41 -0
  2. dycw_utilities-0.174.12.dist-info/RECORD +104 -0
  3. dycw_utilities-0.174.12.dist-info/WHEEL +4 -0
  4. {dycw_utilities-0.148.5.dist-info → dycw_utilities-0.174.12.dist-info}/entry_points.txt +3 -0
  5. utilities/__init__.py +1 -1
  6. utilities/{eventkit.py → aeventkit.py} +12 -11
  7. utilities/altair.py +7 -6
  8. utilities/asyncio.py +113 -64
  9. utilities/atomicwrites.py +1 -1
  10. utilities/atools.py +64 -4
  11. utilities/cachetools.py +9 -6
  12. utilities/click.py +145 -49
  13. utilities/concurrent.py +1 -1
  14. utilities/contextlib.py +4 -2
  15. utilities/contextvars.py +20 -1
  16. utilities/cryptography.py +3 -3
  17. utilities/dataclasses.py +15 -28
  18. utilities/docker.py +292 -0
  19. utilities/enum.py +2 -2
  20. utilities/errors.py +1 -1
  21. utilities/fastapi.py +8 -3
  22. utilities/fpdf2.py +2 -2
  23. utilities/functions.py +20 -297
  24. utilities/git.py +19 -0
  25. utilities/grp.py +28 -0
  26. utilities/hypothesis.py +360 -78
  27. utilities/inflect.py +1 -1
  28. utilities/iterables.py +12 -58
  29. utilities/jinja2.py +148 -0
  30. utilities/json.py +1 -1
  31. utilities/libcst.py +7 -7
  32. utilities/logging.py +74 -85
  33. utilities/math.py +8 -4
  34. utilities/more_itertools.py +4 -6
  35. utilities/operator.py +1 -1
  36. utilities/orjson.py +86 -34
  37. utilities/os.py +49 -2
  38. utilities/parse.py +2 -2
  39. utilities/pathlib.py +66 -34
  40. utilities/permissions.py +297 -0
  41. utilities/platform.py +5 -5
  42. utilities/polars.py +932 -420
  43. utilities/polars_ols.py +1 -1
  44. utilities/postgres.py +296 -174
  45. utilities/pottery.py +8 -73
  46. utilities/pqdm.py +3 -3
  47. utilities/pwd.py +28 -0
  48. utilities/pydantic.py +11 -0
  49. utilities/pydantic_settings.py +240 -0
  50. utilities/pydantic_settings_sops.py +76 -0
  51. utilities/pyinstrument.py +5 -5
  52. utilities/pytest.py +155 -46
  53. utilities/pytest_plugins/pytest_randomly.py +1 -1
  54. utilities/pytest_plugins/pytest_regressions.py +7 -3
  55. utilities/pytest_regressions.py +2 -3
  56. utilities/random.py +11 -6
  57. utilities/re.py +1 -1
  58. utilities/redis.py +101 -64
  59. utilities/sentinel.py +10 -0
  60. utilities/shelve.py +4 -1
  61. utilities/shutil.py +25 -0
  62. utilities/slack_sdk.py +8 -3
  63. utilities/sqlalchemy.py +422 -352
  64. utilities/sqlalchemy_polars.py +28 -52
  65. utilities/string.py +1 -1
  66. utilities/subprocess.py +864 -0
  67. utilities/tempfile.py +62 -4
  68. utilities/testbook.py +50 -0
  69. utilities/text.py +165 -42
  70. utilities/timer.py +2 -2
  71. utilities/traceback.py +46 -36
  72. utilities/types.py +62 -23
  73. utilities/typing.py +479 -19
  74. utilities/uuid.py +42 -5
  75. utilities/version.py +27 -26
  76. utilities/whenever.py +661 -151
  77. utilities/zoneinfo.py +80 -22
  78. dycw_utilities-0.148.5.dist-info/METADATA +0 -41
  79. dycw_utilities-0.148.5.dist-info/RECORD +0 -95
  80. dycw_utilities-0.148.5.dist-info/WHEEL +0 -4
  81. dycw_utilities-0.148.5.dist-info/licenses/LICENSE +0 -21
  82. utilities/period.py +0 -237
  83. utilities/typed_settings.py +0 -144
@@ -1,144 +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
-
11
- import typed_settings
12
- from typed_settings import EnvLoader, FileLoader, find
13
- from typed_settings.converters import TSConverter
14
- from typed_settings.loaders import TomlFormat
15
- from whenever import (
16
- Date,
17
- DateDelta,
18
- DateTimeDelta,
19
- MonthDay,
20
- PlainDateTime,
21
- Time,
22
- TimeDelta,
23
- YearMonth,
24
- ZonedDateTime,
25
- )
26
-
27
- from utilities.iterables import always_iterable
28
- from utilities.pathlib import get_path
29
- from utilities.string import substitute_environ
30
-
31
- if TYPE_CHECKING:
32
- from collections.abc import Callable
33
-
34
- from typed_settings.loaders import Loader
35
- from typed_settings.processors import Processor
36
-
37
- from utilities.types import MaybeCallablePathLike, MaybeIterable, PathLike
38
-
39
-
40
- ##
41
-
42
-
43
- class ExtendedTSConverter(TSConverter):
44
- """An extension of the TSConverter for custom types."""
45
-
46
- @override
47
- def __init__(
48
- self,
49
- *,
50
- resolve_paths: bool = True,
51
- strlist_sep: str | Callable[[str], list] | None = ":",
52
- ) -> None:
53
- super().__init__(resolve_paths=resolve_paths, strlist_sep=strlist_sep)
54
- cases: list[tuple[type[Any], Callable[..., Any]]] = [
55
- (Date, Date.parse_common_iso),
56
- (DateDelta, DateDelta.parse_common_iso),
57
- (DateTimeDelta, DateTimeDelta.parse_common_iso),
58
- (IPv4Address, IPv4Address),
59
- (IPv6Address, IPv6Address),
60
- (MonthDay, MonthDay.parse_common_iso),
61
- (Path, partial(_parse_path, resolve=resolve_paths, pwd=Path.cwd())),
62
- (PlainDateTime, PlainDateTime.parse_common_iso),
63
- (Time, Time.parse_common_iso),
64
- (TimeDelta, TimeDelta.parse_common_iso),
65
- (YearMonth, YearMonth.parse_common_iso),
66
- (ZonedDateTime, ZonedDateTime.parse_common_iso),
67
- ]
68
- extras = {cls: _make_converter(cls, func) for cls, func in cases}
69
- self.scalar_converters |= extras
70
-
71
-
72
- def _make_converter[T](
73
- cls: type[T], parser: Callable[[str], T], /
74
- ) -> Callable[[Any, type[Any]], Any]:
75
- def hook(value: T | str, _: type[T] = cls, /) -> Any:
76
- if not isinstance(value, (cls, str)): # pragma: no cover
77
- msg = f"Invalid type {type(value).__name__!r}; expected '{cls.__name__}' or 'str'"
78
- raise TypeError(msg)
79
- if isinstance(value, str):
80
- return parser(value)
81
- return value
82
-
83
- return hook
84
-
85
-
86
- def _parse_path(
87
- path: str, /, *, resolve: bool = False, pwd: MaybeCallablePathLike | None = None
88
- ) -> Path:
89
- path = substitute_environ(path, **environ)
90
- match resolve:
91
- case True:
92
- return get_path(path=pwd).joinpath(path).resolve()
93
- case False:
94
- return Path(path)
95
- case _ as never:
96
- assert_never(never)
97
-
98
-
99
- ##
100
-
101
-
102
- _BASE_DIR: Path = Path()
103
-
104
-
105
- def load_settings[T](
106
- cls: type[T],
107
- app_name: str,
108
- /,
109
- *,
110
- filenames: MaybeIterable[str] = "settings.toml",
111
- start_dir: PathLike | None = None,
112
- loaders: MaybeIterable[Loader] | None = None,
113
- processors: MaybeIterable[Processor] = (),
114
- base_dir: Path = _BASE_DIR,
115
- ) -> T:
116
- if not search(r"^[A-Za-z]+(?:_[A-Za-z]+)*$", app_name):
117
- raise LoadSettingsError(appname=app_name)
118
- filenames_use = list(always_iterable(filenames))
119
- start_dir_use = None if start_dir is None else Path(start_dir)
120
- files = [find(filename, start_dir=start_dir_use) for filename in filenames_use]
121
- file_loader = FileLoader(formats={"*.toml": TomlFormat(app_name)}, files=files)
122
- env_loader = EnvLoader(f"{app_name.upper()}__", nested_delimiter="__")
123
- loaders_use: list[Loader] = [file_loader, env_loader]
124
- if loaders is not None:
125
- loaders_use.extend(always_iterable(loaders))
126
- return typed_settings.load_settings(
127
- cls,
128
- loaders_use,
129
- processors=list(always_iterable(processors)),
130
- converter=ExtendedTSConverter(),
131
- base_dir=base_dir,
132
- )
133
-
134
-
135
- @dataclass(kw_only=True, slots=True)
136
- class LoadSettingsError(Exception):
137
- appname: str
138
-
139
- @override
140
- def __str__(self) -> str:
141
- return f"Invalid app name; got {self.appname!r}"
142
-
143
-
144
- __all__ = ["ExtendedTSConverter", "LoadSettingsError", "load_settings"]