dycw-utilities 0.129.10__py3-none-any.whl → 0.175.17__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.
Files changed (103) hide show
  1. dycw_utilities-0.175.17.dist-info/METADATA +34 -0
  2. dycw_utilities-0.175.17.dist-info/RECORD +103 -0
  3. dycw_utilities-0.175.17.dist-info/WHEEL +4 -0
  4. dycw_utilities-0.175.17.dist-info/entry_points.txt +4 -0
  5. utilities/__init__.py +1 -1
  6. utilities/altair.py +14 -14
  7. utilities/asyncio.py +350 -819
  8. utilities/atomicwrites.py +18 -6
  9. utilities/atools.py +77 -22
  10. utilities/cachetools.py +24 -29
  11. utilities/click.py +393 -237
  12. utilities/concurrent.py +8 -11
  13. utilities/contextlib.py +216 -17
  14. utilities/contextvars.py +20 -1
  15. utilities/cryptography.py +3 -3
  16. utilities/dataclasses.py +83 -118
  17. utilities/docker.py +293 -0
  18. utilities/enum.py +26 -23
  19. utilities/errors.py +17 -3
  20. utilities/fastapi.py +29 -65
  21. utilities/fpdf2.py +3 -3
  22. utilities/functions.py +169 -416
  23. utilities/functools.py +18 -19
  24. utilities/git.py +9 -30
  25. utilities/grp.py +28 -0
  26. utilities/gzip.py +31 -0
  27. utilities/http.py +3 -2
  28. utilities/hypothesis.py +738 -589
  29. utilities/importlib.py +17 -1
  30. utilities/inflect.py +25 -0
  31. utilities/iterables.py +194 -262
  32. utilities/jinja2.py +148 -0
  33. utilities/json.py +70 -0
  34. utilities/libcst.py +38 -17
  35. utilities/lightweight_charts.py +5 -9
  36. utilities/logging.py +345 -543
  37. utilities/math.py +18 -13
  38. utilities/memory_profiler.py +11 -15
  39. utilities/more_itertools.py +200 -131
  40. utilities/operator.py +33 -29
  41. utilities/optuna.py +6 -6
  42. utilities/orjson.py +272 -137
  43. utilities/os.py +61 -4
  44. utilities/parse.py +59 -61
  45. utilities/pathlib.py +281 -40
  46. utilities/permissions.py +298 -0
  47. utilities/pickle.py +2 -2
  48. utilities/platform.py +24 -5
  49. utilities/polars.py +1214 -430
  50. utilities/polars_ols.py +1 -1
  51. utilities/postgres.py +408 -0
  52. utilities/pottery.py +113 -26
  53. utilities/pqdm.py +10 -11
  54. utilities/psutil.py +6 -57
  55. utilities/pwd.py +28 -0
  56. utilities/pydantic.py +4 -54
  57. utilities/pydantic_settings.py +240 -0
  58. utilities/pydantic_settings_sops.py +76 -0
  59. utilities/pyinstrument.py +8 -10
  60. utilities/pytest.py +227 -121
  61. utilities/pytest_plugins/__init__.py +1 -0
  62. utilities/pytest_plugins/pytest_randomly.py +23 -0
  63. utilities/pytest_plugins/pytest_regressions.py +56 -0
  64. utilities/pytest_regressions.py +26 -46
  65. utilities/random.py +13 -9
  66. utilities/re.py +58 -28
  67. utilities/redis.py +401 -550
  68. utilities/scipy.py +1 -1
  69. utilities/sentinel.py +10 -0
  70. utilities/shelve.py +4 -1
  71. utilities/shutil.py +25 -0
  72. utilities/slack_sdk.py +36 -106
  73. utilities/sqlalchemy.py +502 -473
  74. utilities/sqlalchemy_polars.py +38 -94
  75. utilities/string.py +2 -3
  76. utilities/subprocess.py +1572 -0
  77. utilities/tempfile.py +86 -4
  78. utilities/testbook.py +50 -0
  79. utilities/text.py +165 -42
  80. utilities/timer.py +37 -65
  81. utilities/traceback.py +158 -929
  82. utilities/types.py +146 -116
  83. utilities/typing.py +531 -71
  84. utilities/tzdata.py +1 -53
  85. utilities/tzlocal.py +6 -23
  86. utilities/uuid.py +43 -5
  87. utilities/version.py +27 -26
  88. utilities/whenever.py +1776 -386
  89. utilities/zoneinfo.py +84 -22
  90. dycw_utilities-0.129.10.dist-info/METADATA +0 -241
  91. dycw_utilities-0.129.10.dist-info/RECORD +0 -96
  92. dycw_utilities-0.129.10.dist-info/WHEEL +0 -4
  93. dycw_utilities-0.129.10.dist-info/licenses/LICENSE +0 -21
  94. utilities/datetime.py +0 -1409
  95. utilities/eventkit.py +0 -402
  96. utilities/loguru.py +0 -144
  97. utilities/luigi.py +0 -228
  98. utilities/period.py +0 -324
  99. utilities/pyrsistent.py +0 -89
  100. utilities/python_dotenv.py +0 -105
  101. utilities/streamlit.py +0 -105
  102. utilities/sys.py +0 -87
  103. utilities/tenacity.py +0 -145
utilities/eventkit.py DELETED
@@ -1,402 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from asyncio import iscoroutinefunction
4
- from dataclasses import dataclass
5
- from functools import wraps
6
- from typing import (
7
- TYPE_CHECKING,
8
- Any,
9
- Generic,
10
- Self,
11
- TypeVar,
12
- assert_never,
13
- cast,
14
- override,
15
- )
16
-
17
- from eventkit import (
18
- Constant,
19
- Count,
20
- DropWhile,
21
- Enumerate,
22
- Event,
23
- Filter,
24
- Fork,
25
- Iterate,
26
- Map,
27
- Pack,
28
- Partial,
29
- PartialRight,
30
- Pluck,
31
- Skip,
32
- Star,
33
- Take,
34
- TakeUntil,
35
- TakeWhile,
36
- Timestamp,
37
- )
38
-
39
- from utilities.functions import apply_decorators
40
- from utilities.iterables import always_iterable
41
- from utilities.logging import get_logger
42
- from utilities.types import TCallable, TCallableMaybeCoroutine1None, TypeLike
43
-
44
- if TYPE_CHECKING:
45
- from collections.abc import Callable
46
-
47
- from utilities.types import Coroutine1, LoggerOrName, MaybeCoroutine1, MaybeIterable
48
-
49
-
50
- _TEvent = TypeVar("_TEvent", bound=Event)
51
-
52
-
53
- ##
54
-
55
-
56
- def add_listener(
57
- event: _TEvent,
58
- listener: Callable[..., MaybeCoroutine1[None]],
59
- /,
60
- *,
61
- error: Callable[[Event, BaseException], MaybeCoroutine1[None]] | None = None,
62
- ignore: TypeLike[BaseException] | None = None,
63
- logger: LoggerOrName | None = None,
64
- decorators: MaybeIterable[Callable[[TCallable], TCallable]] | None = None,
65
- done: Callable[..., MaybeCoroutine1[None]] | None = None,
66
- keep_ref: bool = False,
67
- ) -> _TEvent:
68
- """Connect a listener to an event."""
69
- lifted = lift_listener(
70
- listener,
71
- event,
72
- error=error,
73
- ignore=ignore,
74
- logger=logger,
75
- decorators=decorators,
76
- )
77
- return cast("_TEvent", event.connect(lifted, done=done, keep_ref=keep_ref))
78
-
79
-
80
- ##
81
-
82
-
83
- @dataclass(repr=False, kw_only=True)
84
- class LiftedEvent(Generic[TCallableMaybeCoroutine1None]):
85
- """A lifted version of `Event`."""
86
-
87
- event: Event
88
-
89
- def name(self) -> str:
90
- return self.event.name() # pragma: no cover
91
-
92
- def done(self) -> bool:
93
- return self.event.done() # pragma: no cover
94
-
95
- def set_done(self) -> None:
96
- self.event.set_done() # pragma: no cover
97
-
98
- def value(self) -> Any:
99
- return self.event.value() # pragma: no cover
100
-
101
- def connect(
102
- self,
103
- listener: TCallableMaybeCoroutine1None,
104
- /,
105
- *,
106
- error: Callable[[Event, BaseException], MaybeCoroutine1[None]] | None = None,
107
- ignore: TypeLike[BaseException] | None = None,
108
- logger: LoggerOrName | None = None,
109
- decorators: MaybeIterable[Callable[[TCallable], TCallable]] | None = None,
110
- done: Callable[..., MaybeCoroutine1[None]] | None = None,
111
- keep_ref: bool = False,
112
- ) -> Event:
113
- return add_listener(
114
- self.event,
115
- listener,
116
- error=error,
117
- ignore=ignore,
118
- logger=logger,
119
- decorators=decorators,
120
- done=done,
121
- keep_ref=keep_ref,
122
- )
123
-
124
- def disconnect(
125
- self, listener: Any, /, *, error: Any = None, done: Any = None
126
- ) -> Any:
127
- return self.event.disconnect( # pragma: no cover
128
- listener, error=error, done=done
129
- )
130
-
131
- def disconnect_obj(self, obj: Any, /) -> None:
132
- self.event.disconnect_obj(obj) # pragma: no cover
133
-
134
- def emit(self, *args: Any) -> None:
135
- self.event.emit(*args) # pragma: no cover
136
-
137
- def emit_threadsafe(self, *args: Any) -> None:
138
- self.event.emit_threadsafe(*args) # pragma: no cover
139
-
140
- def clear(self) -> None:
141
- self.event.clear() # pragma: no cover
142
-
143
- def run(self) -> list[Any]:
144
- return self.event.run() # pragma: no cover
145
-
146
- def pipe(self, *targets: Event) -> Event:
147
- return self.event.pipe(*targets) # pragma: no cover
148
-
149
- def fork(self, *targets: Event) -> Fork:
150
- return self.event.fork(*targets) # pragma: no cover
151
-
152
- def set_source(self, source: Any, /) -> None:
153
- self.event.set_source(source) # pragma: no cover
154
-
155
- def _onFinalize(self, ref: Any) -> None: # noqa: N802
156
- self.event._onFinalize(ref) # noqa: SLF001 # pragma: no cover
157
-
158
- async def aiter(self, *, skip_to_last: bool = False, tuples: bool = False) -> Any:
159
- async for i in self.event.aiter( # pragma: no cover
160
- skip_to_last=skip_to_last, tuples=tuples
161
- ):
162
- yield i
163
-
164
- __iadd__ = connect
165
- __isub__ = disconnect
166
- __call__ = emit
167
- __or__ = pipe
168
-
169
- @override
170
- def __repr__(self) -> str:
171
- return self.event.__repr__() # pragma: no cover
172
-
173
- def __len__(self) -> int:
174
- return self.event.__len__() # pragma: no cover
175
-
176
- def __bool__(self) -> bool:
177
- return self.event.__bool__() # pragma: no cover
178
-
179
- def __getitem__(self, fork_targets: Any, /) -> Fork:
180
- return self.event.__getitem__(fork_targets) # pragma: no cover
181
-
182
- def __await__(self) -> Any:
183
- return self.event.__await__() # pragma: no cover
184
-
185
- __aiter__ = aiter
186
-
187
- def __contains__(self, c: Any, /) -> bool:
188
- return self.event.__contains__(c) # pragma: no cover
189
-
190
- @override
191
- def __reduce__(self) -> Any:
192
- return self.event.__reduce__() # pragma: no cover
193
-
194
- def filter(self, *, predicate: Any = bool) -> Filter:
195
- return self.event.filter(predicate=predicate) # pragma: no cover
196
-
197
- def skip(self, *, count: int = 1) -> Skip:
198
- return self.event.skip(count=count) # pragma: no cover
199
-
200
- def take(self, *, count: int = 1) -> Take:
201
- return self.event.take(count=count) # pragma: no cover
202
-
203
- def takewhile(self, *, predicate: Any = bool) -> TakeWhile:
204
- return self.event.takewhile(predicate=predicate) # pragma: no cover
205
-
206
- def dropwhile(self, *, predicate: Any = lambda x: not x) -> DropWhile: # pyright: ignore[reportUnknownLambdaType]
207
- return self.event.dropwhile(predicate=predicate) # pragma: no cover
208
-
209
- def takeuntil(self, notifier: Event, /) -> TakeUntil:
210
- return self.event.takeuntil(notifier) # pragma: no cover
211
-
212
- def constant(self, constant: Any, /) -> Constant:
213
- return self.event.constant(constant) # pragma: no cover
214
-
215
- def iterate(self, it: Any, /) -> Iterate:
216
- return self.event.iterate(it) # pragma: no cover
217
-
218
- def count(self, *, start: int = 0, step: int = 1) -> Count:
219
- return self.event.count(start=start, step=step) # pragma: no cover
220
-
221
- def enumerate(self, *, start: int = 0, step: int = 1) -> Enumerate:
222
- return self.event.enumerate(start=start, step=step) # pragma: no cover
223
-
224
- def timestamp(self) -> Timestamp:
225
- return self.event.timestamp() # pragma: no cover
226
-
227
- def partial(self, *left_args: Any) -> Partial:
228
- return self.event.partial(*left_args) # pragma: no cover
229
-
230
- def partial_right(self, *right_args: Any) -> PartialRight:
231
- return self.event.partial_right(*right_args) # pragma: no cover
232
-
233
- def star(self) -> Star:
234
- return self.event.star() # pragma: no cover
235
-
236
- def pack(self) -> Pack:
237
- return self.event.pack() # pragma: no cover
238
-
239
- def pluck(self, *selections: int | str) -> Pluck:
240
- return self.event.pluck(*selections) # pragma: no cover
241
-
242
- def map(
243
- self,
244
- func: Any,
245
- /,
246
- *,
247
- timeout: float | None = None,
248
- ordered: bool = True,
249
- task_limit: int | None = None,
250
- ) -> Map:
251
- return self.event.map( # pragma: no cover
252
- func, timeout=timeout, ordered=ordered, task_limit=task_limit
253
- )
254
-
255
-
256
- ##
257
-
258
-
259
- class TypedEvent(Event, Generic[TCallableMaybeCoroutine1None]):
260
- """A typed version of `Event`."""
261
-
262
- @override
263
- def connect(
264
- self,
265
- listener: TCallableMaybeCoroutine1None,
266
- error: Callable[[Self, BaseException], MaybeCoroutine1[None]] | None = None,
267
- done: Callable[[Self], MaybeCoroutine1[None]] | None = None,
268
- keep_ref: bool = False,
269
- *,
270
- ignore: TypeLike[BaseException] | None = None,
271
- logger: LoggerOrName | None = None,
272
- decorators: MaybeIterable[Callable[[TCallable], TCallable]] | None = None,
273
- ) -> Self:
274
- lifted = lift_listener(
275
- listener,
276
- self,
277
- error=cast(
278
- "Callable[[Event, BaseException], MaybeCoroutine1[None]] | None", error
279
- ),
280
- ignore=ignore,
281
- logger=logger,
282
- decorators=decorators,
283
- )
284
- return cast(
285
- "Self", super().connect(lifted, error=error, done=done, keep_ref=keep_ref)
286
- )
287
-
288
-
289
- ##
290
-
291
-
292
- def lift_listener(
293
- listener: Callable[..., MaybeCoroutine1[None]],
294
- event: Event,
295
- /,
296
- *,
297
- error: Callable[[Event, BaseException], MaybeCoroutine1[None]] | None = None,
298
- ignore: TypeLike[BaseException] | None = None,
299
- logger: LoggerOrName | None = None,
300
- decorators: MaybeIterable[Callable[[TCallable], TCallable]] | None = None,
301
- ) -> Callable[..., MaybeCoroutine1[None]]:
302
- match error, bool(iscoroutinefunction(listener)):
303
- case None, False:
304
- listener_typed = cast("Callable[..., None]", listener)
305
-
306
- @wraps(listener)
307
- def listener_no_error_sync(*args: Any, **kwargs: Any) -> None:
308
- try:
309
- listener_typed(*args, **kwargs)
310
- except Exception as exc: # noqa: BLE001
311
- if (ignore is not None) and isinstance(exc, ignore):
312
- return
313
- get_logger(logger=logger).exception("")
314
-
315
- lifted = listener_no_error_sync
316
-
317
- case None, True:
318
- listener_typed = cast("Callable[..., Coroutine1[None]]", listener)
319
-
320
- @wraps(listener)
321
- async def listener_no_error_async(*args: Any, **kwargs: Any) -> None:
322
- try:
323
- await listener_typed(*args, **kwargs)
324
- except Exception as exc: # noqa: BLE001
325
- if (ignore is not None) and isinstance(exc, ignore):
326
- return
327
- get_logger(logger=logger).exception("")
328
-
329
- lifted = listener_no_error_async
330
- case _, _:
331
- match bool(iscoroutinefunction(listener)), bool(iscoroutinefunction(error)):
332
- case False, False:
333
- listener_typed = cast("Callable[..., None]", listener)
334
- error_typed = cast("Callable[[Event, Exception], None]", error)
335
-
336
- @wraps(listener)
337
- def listener_have_error_sync(*args: Any, **kwargs: Any) -> None:
338
- try:
339
- listener_typed(*args, **kwargs)
340
- except Exception as exc: # noqa: BLE001
341
- if (ignore is not None) and isinstance(exc, ignore):
342
- return
343
- error_typed(event, exc)
344
-
345
- lifted = listener_have_error_sync
346
- case False, True:
347
- listener_typed = cast("Callable[..., None]", listener)
348
- error_typed = cast(
349
- "Callable[[Event, Exception], Coroutine1[None]]", error
350
- )
351
- raise LiftListenerError(listener=listener_typed, error=error_typed)
352
- case True, _:
353
- listener_typed = cast("Callable[..., Coroutine1[None]]", listener)
354
-
355
- @wraps(listener)
356
- async def listener_have_error_async(
357
- *args: Any, **kwargs: Any
358
- ) -> None:
359
- try:
360
- await listener_typed(*args, **kwargs)
361
- except Exception as exc: # noqa: BLE001
362
- if (ignore is not None) and isinstance(exc, ignore):
363
- return None
364
- if iscoroutinefunction(error):
365
- error_typed = cast(
366
- "Callable[[Event, Exception], Coroutine1[None]]",
367
- error,
368
- )
369
- return await error_typed(event, exc)
370
- error_typed = cast(
371
- "Callable[[Event, Exception], None]", error
372
- )
373
- error_typed(event, exc)
374
-
375
- lifted = listener_have_error_async
376
- case _ as never:
377
- assert_never(never)
378
- case _ as never:
379
- assert_never(never)
380
-
381
- if decorators is not None:
382
- lifted = apply_decorators(lifted, *always_iterable(decorators))
383
- return lifted
384
-
385
-
386
- @dataclass(kw_only=True, slots=True)
387
- class LiftListenerError(Exception):
388
- listener: Callable[..., None]
389
- error: Callable[[Event, Exception], Coroutine1[None]]
390
-
391
- @override
392
- def __str__(self) -> str:
393
- return f"Synchronous listener {self.listener} cannot be paired with an asynchronous error handler {self.error}"
394
-
395
-
396
- __all__ = [
397
- "LiftListenerError",
398
- "LiftedEvent",
399
- "TypedEvent",
400
- "add_listener",
401
- "lift_listener",
402
- ]
utilities/loguru.py DELETED
@@ -1,144 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import logging
4
- from dataclasses import dataclass
5
- from enum import StrEnum, unique
6
- from logging import Handler, LogRecord
7
- from sys import _getframe
8
- from typing import TYPE_CHECKING, cast, override
9
-
10
- from loguru import logger
11
-
12
- from utilities.iterables import OneEmptyError, OneNonUniqueError, one
13
-
14
- if TYPE_CHECKING:
15
- from collections.abc import Sequence
16
-
17
- from loguru import LevelConfig
18
-
19
-
20
- LEVEL_CONFIGS: Sequence[LevelConfig] = [
21
- {"name": "TRACE", "color": "<blue><bold>"},
22
- {"name": "DEBUG", "color": "<cyan><bold>"},
23
- {"name": "INFO", "color": "<green><bold>"},
24
- {"name": "SUCCESS", "color": "<magenta><bold>"},
25
- {"name": "WARNING", "color": "<yellow><bold>"},
26
- {"name": "ERROR", "color": "<red><bold>"},
27
- {"name": "CRITICAL", "color": "<red><bold><blink>"},
28
- ]
29
-
30
-
31
- ##
32
-
33
-
34
- class InterceptHandler(Handler):
35
- """Handler for intercepting standard logging messages.
36
-
37
- https://github.com/Delgan/loguru#entirely-compatible-with-standard-logging
38
- """
39
-
40
- @override
41
- def emit(self, record: LogRecord) -> None:
42
- # Get corresponding Loguru level if it exists.
43
- try: # pragma: no cover
44
- level = logger.level(record.levelname).name
45
- except ValueError: # pragma: no cover
46
- level = record.levelno
47
-
48
- # Find caller from where originated the logged message.
49
- frame, depth = _getframe(6), 6 # pragma: no cover
50
- while ( # pragma: no cover
51
- frame and frame.f_code.co_filename == logging.__file__
52
- ):
53
- frame = frame.f_back
54
- depth += 1
55
-
56
- logger.opt(depth=depth, exception=record.exc_info).log( # pragma: no cover
57
- level, record.getMessage()
58
- )
59
-
60
-
61
- ##
62
-
63
-
64
- @unique
65
- class LogLevel(StrEnum):
66
- """An enumeration of the logging levels."""
67
-
68
- TRACE = "TRACE"
69
- DEBUG = "DEBUG"
70
- INFO = "INFO"
71
- SUCCESS = "SUCCESS"
72
- WARNING = "WARNING"
73
- ERROR = "ERROR"
74
- CRITICAL = "CRITICAL"
75
-
76
-
77
- ##
78
-
79
-
80
- def get_logging_level_name(level: int, /) -> str:
81
- """Get the logging level name."""
82
- core = logger._core # noqa: SLF001 # pyright: ignore[reportAttributeAccessIssue]
83
- try:
84
- return one(k for k, v in core.levels.items() if v.no == level)
85
- except OneEmptyError:
86
- raise _GetLoggingLevelNameEmptyError(level=level) from None
87
- except OneNonUniqueError as error:
88
- error = cast("OneNonUniqueError[str]", error)
89
- raise _GetLoggingLevelNameNonUniqueError(
90
- level=level, first=error.first, second=error.second
91
- ) from None
92
-
93
-
94
- @dataclass(kw_only=True, slots=True)
95
- class GetLoggingLevelNameError(Exception):
96
- level: int
97
-
98
-
99
- @dataclass(kw_only=True, slots=True)
100
- class _GetLoggingLevelNameEmptyError(GetLoggingLevelNameError):
101
- @override
102
- def __str__(self) -> str:
103
- return f"There is no level with severity {self.level}"
104
-
105
-
106
- @dataclass(kw_only=True, slots=True)
107
- class _GetLoggingLevelNameNonUniqueError(GetLoggingLevelNameError):
108
- first: str
109
- second: str
110
-
111
- @override
112
- def __str__(self) -> str:
113
- return f"There must be exactly one level with severity {self.level}; got {self.first!r}, {self.second!r} and perhaps more"
114
-
115
-
116
- ##
117
-
118
-
119
- def get_logging_level_number(level: str, /) -> int:
120
- """Get the logging level number."""
121
- try:
122
- return logger.level(level).no
123
- except ValueError:
124
- raise GetLoggingLevelNumberError(level=level) from None
125
-
126
-
127
- @dataclass(kw_only=True, slots=True)
128
- class GetLoggingLevelNumberError(Exception):
129
- level: str
130
-
131
- @override
132
- def __str__(self) -> str:
133
- return f"Invalid logging level: {self.level!r}"
134
-
135
-
136
- __all__ = [
137
- "LEVEL_CONFIGS",
138
- "GetLoggingLevelNameError",
139
- "GetLoggingLevelNumberError",
140
- "InterceptHandler",
141
- "LogLevel",
142
- "get_logging_level_name",
143
- "get_logging_level_number",
144
- ]