dycw-utilities 0.164.0__py3-none-any.whl → 0.165.0__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dycw-utilities
3
- Version: 0.164.0
3
+ Version: 0.165.0
4
4
  Author-email: Derek Wan <d.wan@icloud.com>
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.12
@@ -1,4 +1,4 @@
1
- utilities/__init__.py,sha256=cT3KdUJySCCzC99QlfI301hzQa3WEiHGbk_vNupSr98,60
1
+ utilities/__init__.py,sha256=eMWFiLSdHH55xm1PoUC4Mhq2d_wOPx62DjKIgdfFHPM,60
2
2
  utilities/aeventkit.py,sha256=ddoleSwW9zdc2tjX5Ge0pMKtYwV_JMxhHYOxnWX2AGM,12609
3
3
  utilities/altair.py,sha256=92E2lCdyHY4Zb-vCw6rEJIsWdKipuu-Tu2ab1ufUfAk,9079
4
4
  utilities/asyncio.py,sha256=PUedzQ5deqlSECQ33sam9cRzI9TnygHz3FdOqWJWPTM,15288
@@ -22,7 +22,7 @@ utilities/getpass.py,sha256=DfN5UgMAtFCqS3dSfFHUfqIMZX2shXvwphOz_6J6f6A,103
22
22
  utilities/gzip.py,sha256=fkGP3KdsBfXlstodT4wtlp-PwNyUsogpbDCVVVGdsm4,781
23
23
  utilities/hashlib.py,sha256=SVTgtguur0P4elppvzOBbLEjVM3Pea0eWB61yg2ilxo,309
24
24
  utilities/http.py,sha256=TsavEfHlRtlLaeV21Z6KZh0qbPw-kvD1zsQdZ7Kep5Q,977
25
- utilities/hypothesis.py,sha256=eoFAFnM2SdvzH6DWD5oCs8cH57LsEEXsRy8vMZDW6i8,44874
25
+ utilities/hypothesis.py,sha256=lkgPbGjTMTxSXSsZUwmkTpAUex441aWUy_V_l5LwPfM,45528
26
26
  utilities/importlib.py,sha256=mV1xT_O_zt_GnZZ36tl3xOmMaN_3jErDWY54fX39F6Y,429
27
27
  utilities/inflect.py,sha256=v7YkOWSu8NAmVghPcf4F3YBZQoJCS47_DLf9jbfWIs0,581
28
28
  utilities/ipython.py,sha256=V2oMYHvEKvlNBzxDXdLvKi48oUq2SclRg5xasjaXStw,763
@@ -31,7 +31,7 @@ utilities/json.py,sha256=-WcGtSsCr9Y42wHZzAMnfvU6ihAfVftylFfRUORaDFo,2102
31
31
  utilities/jupyter.py,sha256=ft5JA7fBxXKzP-L9W8f2-wbF0QeYc_2uLQNFDVk4Z-M,2917
32
32
  utilities/libcst.py,sha256=TKgKN4bNmtBNEE-TUfhTyd1BrTncfsl_7tTuhpesGYY,5585
33
33
  utilities/lightweight_charts.py,sha256=YM3ojBvJxuCSUBu_KrhFBmaMCvRPvupKC3qkm-UVZq4,2751
34
- utilities/logging.py,sha256=uJ-hhtkrx4xnLUzZmE1soV4O8wQzNPUB1f_YJJe6I30,18089
34
+ utilities/logging.py,sha256=W3d8Vby0mmqGWvTNlGtcfrmORDTt7abCuqjkIyCPIg8,18914
35
35
  utilities/math.py,sha256=cevB-YyEYAzJTWtkAr7qeeu-hbxorDI3gMznXlmNQkw,26897
36
36
  utilities/memory_profiler.py,sha256=XzN56jDCa5aqXS_DxEjb_K4L6aIWh_5zyKi6OhcIxw0,853
37
37
  utilities/modules.py,sha256=iuvLluJya-hvl1Q25-Jk3dLgx2Es3ck4SjJiEkAlVTs,3195
@@ -45,7 +45,7 @@ utilities/parse.py,sha256=JcJn5yXKhIWXBCwgBdPsyu7Hvcuw6kyEdqvaebCaI9k,17951
45
45
  utilities/pathlib.py,sha256=qGuU8XPmdgGpy8tOMUgelfXx3kxI8h9IaV3TI_06QGE,8428
46
46
  utilities/pickle.py,sha256=MBT2xZCsv0pH868IXLGKnlcqNx2IRVKYNpRcqiQQqxw,653
47
47
  utilities/platform.py,sha256=pTn7gw6N4T6LdKrf0virwarof_mze9WtoQlrGMzhGVI,2798
48
- utilities/polars.py,sha256=oV63oc7qI100dHoZUu8rfnr5-bEd7iY0O79iEFtDmj4,79772
48
+ utilities/polars.py,sha256=X-TaklmHmyJazckJIRNMwwvgSp3q6EGGb0mVnwHEDrI,80811
49
49
  utilities/polars_ols.py,sha256=LNTFNLPuYW7fcAHymlbnams_DhitToblYvib3mhKbwI,5615
50
50
  utilities/postgres.py,sha256=ynCTTaF-bVEOSW-KEAR-dlLh_hYjeVVjm__-4pEU8Zk,12269
51
51
  utilities/pottery.py,sha256=ggMN72Y7wx7Js8VN6eyNyodpm8TIYqZHGghkDPXIVWk,3949
@@ -76,7 +76,7 @@ utilities/timer.py,sha256=oXfTii6ymu57niP0BDGZjFD55LEHi2a19kqZKiTgaFQ,2588
76
76
  utilities/traceback.py,sha256=b1nSvlyrGmI1MyZLkkoLVET3DQBSGt9qqIlAAQbyjEw,9629
77
77
  utilities/typed_settings.py,sha256=SFWqS3lAzV7IfNRwqFcTk0YynTcQ7BmrcW2mr_KUnos,4466
78
78
  utilities/types.py,sha256=oeH-hEC3-67Eja4nLz-Nj9WvK6Z9-3T1zobO_XJpuVg,18735
79
- utilities/typing.py,sha256=UXhQPJ25sUawgYFIzH28NyuTje9ybg6tWDuN6BiU55E,24214
79
+ utilities/typing.py,sha256=vPqxHE2G5_dbDEgWAyAaTSDbUQE0pmihIj0vdXogbRU,24185
80
80
  utilities/tzdata.py,sha256=fgNVj66yUbCSI_-vrRVzSD3gtf-L_8IEJEPjP_Jel5Y,266
81
81
  utilities/tzlocal.py,sha256=KyCXEgCTjqGFx-389JdTuhMRUaT06U1RCMdWoED-qro,728
82
82
  utilities/uuid.py,sha256=nQZs6tFX4mqtc2Ku3KqjloYCqwpTKeTj8eKwQwh3FQI,1572
@@ -88,8 +88,8 @@ utilities/zoneinfo.py,sha256=tdIScrTB2-B-LH0ukb1HUXKooLknOfJNwHk10MuMYvA,3619
88
88
  utilities/pytest_plugins/__init__.py,sha256=U4S_2y3zgLZVfMenHRaJFBW8yqh2mUBuI291LGQVOJ8,35
89
89
  utilities/pytest_plugins/pytest_randomly.py,sha256=B1qYVlExGOxTywq2r1SMi5o7btHLk2PNdY_b1p98dkE,409
90
90
  utilities/pytest_plugins/pytest_regressions.py,sha256=9v8kAXDM2ycIXJBimoiF4EgrwbUvxTycFWJiGR_GHhM,1466
91
- dycw_utilities-0.164.0.dist-info/METADATA,sha256=OTRhIzWSdVocu0RE1zn25hIns4nLsKu0TIBD8i2KdOs,1696
92
- dycw_utilities-0.164.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
93
- dycw_utilities-0.164.0.dist-info/entry_points.txt,sha256=BOD_SoDxwsfJYOLxhrSXhHP_T7iw-HXI9f2WVkzYxvQ,135
94
- dycw_utilities-0.164.0.dist-info/licenses/LICENSE,sha256=gppZp16M6nSVpBbUBrNL6JuYfvKwZiKgV7XoKKsHzqo,1066
95
- dycw_utilities-0.164.0.dist-info/RECORD,,
91
+ dycw_utilities-0.165.0.dist-info/METADATA,sha256=PpOe9KFVyH8YGS5XUPPs54AKrihmPXvCuD5aauG9to0,1696
92
+ dycw_utilities-0.165.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
93
+ dycw_utilities-0.165.0.dist-info/entry_points.txt,sha256=BOD_SoDxwsfJYOLxhrSXhHP_T7iw-HXI9f2WVkzYxvQ,135
94
+ dycw_utilities-0.165.0.dist-info/licenses/LICENSE,sha256=gppZp16M6nSVpBbUBrNL6JuYfvKwZiKgV7XoKKsHzqo,1066
95
+ dycw_utilities-0.165.0.dist-info/RECORD,,
utilities/__init__.py CHANGED
@@ -1,3 +1,3 @@
1
1
  from __future__ import annotations
2
2
 
3
- __version__ = "0.164.0"
3
+ __version__ = "0.165.0"
utilities/hypothesis.py CHANGED
@@ -412,6 +412,8 @@ def float32s(
412
412
  *,
413
413
  min_value: MaybeSearchStrategy[float | None] = None,
414
414
  max_value: MaybeSearchStrategy[float | None] = None,
415
+ exclude_min: MaybeSearchStrategy[bool] = False,
416
+ exclude_max: MaybeSearchStrategy[bool] = False,
415
417
  ) -> float:
416
418
  """Strategy for generating float32s."""
417
419
  min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
@@ -419,7 +421,16 @@ def float32s(
419
421
  max_value_ = min_nullable([max_value_, MAX_FLOAT32])
420
422
  if is_zero(min_value_) and is_zero(max_value_):
421
423
  min_value_ = max_value_ = 0.0
422
- return draw(floats(min_value_, max_value_, width=32))
424
+ exclude_min_, exclude_max_ = [draw2(draw, e) for e in [exclude_min, exclude_max]]
425
+ return draw(
426
+ floats(
427
+ min_value_,
428
+ max_value_,
429
+ width=32,
430
+ exclude_min=exclude_min_,
431
+ exclude_max=exclude_max_,
432
+ )
433
+ )
423
434
 
424
435
 
425
436
  @composite
@@ -429,6 +440,8 @@ def float64s(
429
440
  *,
430
441
  min_value: MaybeSearchStrategy[float | None] = None,
431
442
  max_value: MaybeSearchStrategy[float | None] = None,
443
+ exclude_min: MaybeSearchStrategy[bool] = False,
444
+ exclude_max: MaybeSearchStrategy[bool] = False,
432
445
  ) -> float:
433
446
  """Strategy for generating float64s."""
434
447
  min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
@@ -436,7 +449,16 @@ def float64s(
436
449
  max_value_ = min_nullable([max_value_, MAX_FLOAT64])
437
450
  if is_zero(min_value_) and is_zero(max_value_):
438
451
  min_value_ = max_value_ = 0.0
439
- return draw(floats(min_value_, max_value_, width=64))
452
+ exclude_min_, exclude_max_ = [draw2(draw, e) for e in [exclude_min, exclude_max]]
453
+ return draw(
454
+ floats(
455
+ min_value_,
456
+ max_value_,
457
+ width=64,
458
+ exclude_min=exclude_min_,
459
+ exclude_max=exclude_max_,
460
+ )
461
+ )
440
462
 
441
463
 
442
464
  ##
utilities/logging.py CHANGED
@@ -8,6 +8,7 @@ from logging import (
8
8
  Formatter,
9
9
  Handler,
10
10
  Logger,
11
+ LoggerAdapter,
11
12
  LogRecord,
12
13
  StreamHandler,
13
14
  basicConfig,
@@ -22,6 +23,7 @@ from socket import gethostname
22
23
  from typing import (
23
24
  TYPE_CHECKING,
24
25
  Any,
26
+ Concatenate,
25
27
  Literal,
26
28
  NotRequired,
27
29
  Self,
@@ -53,7 +55,7 @@ from utilities.whenever import (
53
55
  )
54
56
 
55
57
  if TYPE_CHECKING:
56
- from collections.abc import Iterable, Mapping
58
+ from collections.abc import Callable, Iterable, Mapping, MutableMapping
57
59
  from datetime import time
58
60
  from logging import _FilterType
59
61
 
@@ -63,6 +65,7 @@ if TYPE_CHECKING:
63
65
  MaybeCallablePathLike,
64
66
  MaybeIterable,
65
67
  PathLike,
68
+ StrMapping,
66
69
  )
67
70
 
68
71
 
@@ -75,6 +78,35 @@ _DEFAULT_WHEN: _When = "D"
75
78
  ##
76
79
 
77
80
 
81
+ def add_adapter[**P](
82
+ logger: Logger,
83
+ process: Callable[Concatenate[str, P], str],
84
+ /,
85
+ *args: P.args,
86
+ **kwargs: P.kwargs,
87
+ ) -> LoggerAdapter:
88
+ """Add an adapter to a logger."""
89
+
90
+ class CustomAdapter(LoggerAdapter):
91
+ @override
92
+ def process(
93
+ self, msg: str, kwargs: MutableMapping[str, Any]
94
+ ) -> tuple[str, MutableMapping[str, Any]]:
95
+ extra = cast("_ArgsAndKwargs", self.extra)
96
+ new_msg = process(msg, *extra["args"], **extra["kwargs"])
97
+ return new_msg, kwargs
98
+
99
+ return CustomAdapter(logger, extra=_ArgsAndKwargs(args=args, kwargs=kwargs))
100
+
101
+
102
+ class _ArgsAndKwargs(TypedDict):
103
+ args: tuple[Any, ...]
104
+ kwargs: StrMapping
105
+
106
+
107
+ ##
108
+
109
+
78
110
  def add_filters(handler: Handler, /, *filters: _FilterType) -> None:
79
111
  """Add a set of filters to a handler."""
80
112
  for filter_i in filters:
@@ -589,6 +621,7 @@ def to_logger(logger: LoggerLike | None = None, /) -> Logger:
589
621
  __all__ = [
590
622
  "GetLoggingLevelNumberError",
591
623
  "SizeAndTimeRotatingFileHandler",
624
+ "add_adapter",
592
625
  "add_filters",
593
626
  "basic_config",
594
627
  "get_format_str",
utilities/polars.py CHANGED
@@ -6,7 +6,7 @@ from collections.abc import Set as AbstractSet
6
6
  from dataclasses import asdict, dataclass
7
7
  from functools import partial, reduce
8
8
  from itertools import chain, pairwise, product
9
- from math import ceil, log
9
+ from math import ceil, log, pi, sqrt
10
10
  from pathlib import Path
11
11
  from typing import TYPE_CHECKING, Any, Literal, assert_never, cast, overload, override
12
12
  from uuid import UUID
@@ -1929,7 +1929,49 @@ def nan_sum_horizontal(*columns: IntoExprColumn) -> ExprOrSeries:
1929
1929
  ##
1930
1930
 
1931
1931
 
1932
- def normal(
1932
+ @overload
1933
+ def normal_pdf(
1934
+ x: ExprLike,
1935
+ /,
1936
+ *,
1937
+ loc: float | IntoExprColumn = 0.0,
1938
+ scale: float | IntoExprColumn = 1.0,
1939
+ ) -> Expr: ...
1940
+ @overload
1941
+ def normal_pdf(
1942
+ x: Series,
1943
+ /,
1944
+ *,
1945
+ loc: float | IntoExprColumn = 0.0,
1946
+ scale: float | IntoExprColumn = 1.0,
1947
+ ) -> Series: ...
1948
+ @overload
1949
+ def normal_pdf(
1950
+ x: IntoExprColumn,
1951
+ /,
1952
+ *,
1953
+ loc: float | IntoExprColumn = 0.0,
1954
+ scale: float | IntoExprColumn = 1.0,
1955
+ ) -> ExprOrSeries: ...
1956
+ def normal_pdf(
1957
+ x: IntoExprColumn,
1958
+ /,
1959
+ *,
1960
+ loc: float | IntoExprColumn = 0.0,
1961
+ scale: float | IntoExprColumn = 1.0,
1962
+ ) -> ExprOrSeries:
1963
+ """Compute the PDF of a normal distribution."""
1964
+ x = ensure_expr_or_series(x)
1965
+ loc = loc if isinstance(loc, int | float) else ensure_expr_or_series(loc)
1966
+ scale = scale if isinstance(scale, int | float) else ensure_expr_or_series(scale)
1967
+ expr = (1 / (scale * sqrt(2 * pi))) * (-(1 / 2) * ((x - loc) / scale) ** 2).exp()
1968
+ return try_reify_expr(expr, x)
1969
+
1970
+
1971
+ ##
1972
+
1973
+
1974
+ def normal_rv(
1933
1975
  obj: int | Series | DataFrame,
1934
1976
  /,
1935
1977
  *,
@@ -1948,11 +1990,11 @@ def normal(
1948
1990
  values = rng.normal(loc=loc, scale=scale, size=height)
1949
1991
  return Series(name=name, values=values, dtype=dtype)
1950
1992
  case Series() as series:
1951
- return normal(
1993
+ return normal_rv(
1952
1994
  series.len(), loc=loc, scale=scale, seed=seed, name=name, dtype=dtype
1953
1995
  )
1954
1996
  case DataFrame() as df:
1955
- return normal(
1997
+ return normal_rv(
1956
1998
  df.height, loc=loc, scale=scale, seed=seed, name=name, dtype=dtype
1957
1999
  )
1958
2000
  case never:
@@ -1964,22 +2006,22 @@ def normal(
1964
2006
 
1965
2007
  @overload
1966
2008
  def number_of_decimals(
1967
- series: ExprLike, /, *, max_decimals: int = MAX_DECIMALS
2009
+ column: ExprLike, /, *, max_decimals: int = MAX_DECIMALS
1968
2010
  ) -> Expr: ...
1969
2011
  @overload
1970
2012
  def number_of_decimals(
1971
- series: Series, /, *, max_decimals: int = MAX_DECIMALS
2013
+ column: Series, /, *, max_decimals: int = MAX_DECIMALS
1972
2014
  ) -> Series: ...
1973
2015
  @overload
1974
2016
  def number_of_decimals(
1975
- series: IntoExprColumn, /, *, max_decimals: int = MAX_DECIMALS
2017
+ column: IntoExprColumn, /, *, max_decimals: int = MAX_DECIMALS
1976
2018
  ) -> ExprOrSeries: ...
1977
2019
  def number_of_decimals(
1978
- series: IntoExprColumn, /, *, max_decimals: int = MAX_DECIMALS
2020
+ column: IntoExprColumn, /, *, max_decimals: int = MAX_DECIMALS
1979
2021
  ) -> ExprOrSeries:
1980
2022
  """Get the number of decimals."""
1981
- series = ensure_expr_or_series(series)
1982
- frac = series - series.floor()
2023
+ column = ensure_expr_or_series(column)
2024
+ frac = column - column.floor()
1983
2025
  results = (
1984
2026
  _number_of_decimals_check_scale(frac, s) for s in range(max_decimals + 1)
1985
2027
  )
@@ -2697,7 +2739,8 @@ __all__ = [
2697
2739
  "map_over_columns",
2698
2740
  "nan_sum_agg",
2699
2741
  "nan_sum_horizontal",
2700
- "normal",
2742
+ "normal_pdf",
2743
+ "normal_rv",
2701
2744
  "number_of_decimals",
2702
2745
  "offset_datetime",
2703
2746
  "one_column",
utilities/typing.py CHANGED
@@ -333,7 +333,7 @@ def is_instance_gen(
333
333
  warn_name_errors=warn_name_errors,
334
334
  )
335
335
  for t in type_
336
- ) # skipif-ci-and-not-windows
336
+ )
337
337
  if is_literal_type(type_):
338
338
  return obj in get_args(type_)
339
339
  if is_union_type(type_):