dycw-utilities 0.155.3__py3-none-any.whl → 0.155.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dycw-utilities
3
- Version: 0.155.3
3
+ Version: 0.155.4
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=G6dQZ623gragMkZmSuauyK65lWhpSPUVFQC5FFShVec,60
1
+ utilities/__init__.py,sha256=JZDiFrW90kp6d38qwQIEOcE7Gd8ts-n5Mjx7Ed2T8zc,60
2
2
  utilities/altair.py,sha256=92E2lCdyHY4Zb-vCw6rEJIsWdKipuu-Tu2ab1ufUfAk,9079
3
3
  utilities/asyncio.py,sha256=QXkTtugXkqtYt7Do23zgYErqzdp6jwzPpV_SP9fJ1gI,16780
4
4
  utilities/atomicwrites.py,sha256=tPo6r-Rypd9u99u66B9z86YBPpnLrlHtwox_8Z7T34Y,5790
@@ -10,23 +10,23 @@ utilities/contextlib.py,sha256=m2D5bwvtCZLJcJ3IwVqyErYODuwJ1gLrT2UfATAQl-w,7435
10
10
  utilities/contextvars.py,sha256=J8OhC7jqozAGYOCe2KUWysbPXNGe5JYz3HfaY_mIs08,883
11
11
  utilities/cryptography.py,sha256=5PFrzsNUGHay91dFgYnDKwYprXxahrBqztmUqViRzBk,956
12
12
  utilities/cvxpy.py,sha256=Rv1-fD-XYerosCavRF8Pohop2DBkU3AlFaGTfD8AEAA,13776
13
- utilities/dataclasses.py,sha256=G05UH-fqUbcRPjQ8arK6K0Ap2fRbzEm0SZahJKCqYfY,32643
13
+ utilities/dataclasses.py,sha256=MXrvIPSZHlpV4msRdVVDRZZo7MC3gX5C9jDUSoNOdpE,32478
14
14
  utilities/enum.py,sha256=5l6pwZD1cjSlVW4ss-zBPspWvrbrYrdtJWcg6f5_J5w,5781
15
15
  utilities/errors.py,sha256=mFlDGSM0LI1jZ1pbqwLAH3ttLZ2JVIxyZLojw8tGVZU,1479
16
16
  utilities/eventkit.py,sha256=ddoleSwW9zdc2tjX5Ge0pMKtYwV_JMxhHYOxnWX2AGM,12609
17
17
  utilities/fastapi.py,sha256=3wpd63Tw9paSyy7STpAD7GGe8fLkLaRC6TPCwIGm1BU,1361
18
18
  utilities/fpdf2.py,sha256=HgM8JSvoioDXrjC0UR3HVLjnMnnb_mML7nL2EmkTwGI,1854
19
- utilities/functions.py,sha256=0mmeZ8op3QkAooYRAyRZhpi3TgaJCiMnqbJtZl-myug,28266
19
+ utilities/functions.py,sha256=RNVAoLeT_sl-gXaBv2VI_U_EB-d-nSVosYR4gTeeojE,28261
20
20
  utilities/functools.py,sha256=I00ru2gQPakZw2SHVeKIKXfTv741655s6HI0lUoE0D4,1552
21
21
  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=2lAUvuXj_zswg-8Ot0ZuBzTbZyaRYWRmeR8qSF7Mmys,43817
25
+ utilities/hypothesis.py,sha256=qqV0O2ynV73tT-bAPXxlfWdR1X0iZgrjn7sK-eJOqBM,43812
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
29
- utilities/iterables.py,sha256=ZmXBSk_Rio-aqLwTaoX69HD81YVcndeLYQwjv0P64JM,43009
29
+ utilities/iterables.py,sha256=fM7s5072m9ram33zMk4nYQpOSxW8Zt6_XX2GCD5BMY0,43013
30
30
  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
@@ -35,7 +35,7 @@ utilities/logging.py,sha256=ihbfQJgjc7t3Pds0oPvF_J1eigiqFKzxNOijzoee8U4,18064
35
35
  utilities/math.py,sha256=7ve4RxX3g-FGGVnWV0K9bBeGnKUEjnTbH13VxdvFtGE,26847
36
36
  utilities/memory_profiler.py,sha256=XzN56jDCa5aqXS_DxEjb_K4L6aIWh_5zyKi6OhcIxw0,853
37
37
  utilities/modules.py,sha256=iuvLluJya-hvl1Q25-Jk3dLgx2Es3ck4SjJiEkAlVTs,3195
38
- utilities/more_itertools.py,sha256=rklJ5vpvXr_H5pAGpWmwVpqtBVehoJ0-jBGYsZbux3M,10927
38
+ utilities/more_itertools.py,sha256=syfIPhQF_WS-YiicdGe2h5F1G-Ld12Q2XsVduL2hA40,10908
39
39
  utilities/numpy.py,sha256=Xn23sA2ZbVNqwUYEgNJD3XBYH6IbCri_WkHSNhg3NkY,26122
40
40
  utilities/operator.py,sha256=nhxn5q6CFNzUm1wpTwWPCu9JGCqVHSlaJf0o1-efoII,3616
41
41
  utilities/optuna.py,sha256=C-fhWYiXHVPo1l8QctYkFJ4DyhbSrGorzP1dJb_qvd8,1933
@@ -49,7 +49,7 @@ utilities/polars.py,sha256=JOZjSpj9jitDijX044mKc-N00C5N_On3TJYJKJRhdcE,78494
49
49
  utilities/polars_ols.py,sha256=Uc9V5kvlWZ5cU93lKZ-cfAKdVFFw81tqwLW9PxtUvMs,5618
50
50
  utilities/postgres.py,sha256=ynCTTaF-bVEOSW-KEAR-dlLh_hYjeVVjm__-4pEU8Zk,12269
51
51
  utilities/pottery.py,sha256=HJ96oLRarTP37Vhg0WTyB3yAu2hETeg6HgRmpDIqyUs,6581
52
- utilities/pqdm.py,sha256=z8bSMS7QJmWun65FQZruAqT-R3wqPAzNzhWcX9Nvr0A,3087
52
+ utilities/pqdm.py,sha256=idv2seRVP2f6NeSfpeEnT5A-tQezaHZKDyeu16g2-0E,3091
53
53
  utilities/psutil.py,sha256=KUlu4lrUw9Zg1V7ZGetpWpGb9DB8l_SSDWGbANFNCPU,2104
54
54
  utilities/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
55
55
  utilities/pyinstrument.py,sha256=NZCZz2nBo0BLJ9DTf7H_Q_KGxvsf2S2M3h0qYoYh2kw,804
@@ -60,7 +60,7 @@ utilities/re.py,sha256=S4h-DLL6ScMPqjboZ_uQ1BVTJajrqV06r_81D--_HCE,4573
60
60
  utilities/redis.py,sha256=2fdveFbqL2pEAeyiVuN_Je8nSM_IZHeahPduMHhFRzY,28381
61
61
  utilities/reprlib.py,sha256=ssYTcBW-TeRh3fhCJv57sopTZHF5FrPyyUg9yp5XBlo,3953
62
62
  utilities/scipy.py,sha256=wZJM7fEgBAkLSYYvSmsg5ac-QuwAI0BGqHVetw1_Hb0,947
63
- utilities/sentinel.py,sha256=3jIwgpMekWgDAxPDA_hXMP2St43cPhciKN3LWiZ7kv0,1248
63
+ utilities/sentinel.py,sha256=A_p5jX2K0Yc5XBfoYHyBLqHsEWzE1ByOdDuzzA2pZnE,1434
64
64
  utilities/shelve.py,sha256=4OzjQI6kGuUbJciqf535rwnao-_IBv66gsT6tRGiUt0,759
65
65
  utilities/slack_sdk.py,sha256=ppFBvKgfg5IRWiIoKPtpTyzBtBF4XmwEvU3I5wLJikM,2140
66
66
  utilities/socket.py,sha256=K77vfREvzoVTrpYKo6MZakol0EYu2q1sWJnnZqL0So0,118
@@ -87,8 +87,8 @@ utilities/zoneinfo.py,sha256=FBMcUQ4662Aq8SsuCL1OAhDQiyANmVjtb-C30DRrWoE,1966
87
87
  utilities/pytest_plugins/__init__.py,sha256=U4S_2y3zgLZVfMenHRaJFBW8yqh2mUBuI291LGQVOJ8,35
88
88
  utilities/pytest_plugins/pytest_randomly.py,sha256=B1qYVlExGOxTywq2r1SMi5o7btHLk2PNdY_b1p98dkE,409
89
89
  utilities/pytest_plugins/pytest_regressions.py,sha256=9v8kAXDM2ycIXJBimoiF4EgrwbUvxTycFWJiGR_GHhM,1466
90
- dycw_utilities-0.155.3.dist-info/METADATA,sha256=9E4nOucqtl9XU96ns1fqx2UfqBw-JEyXeH867ENuMu4,1643
91
- dycw_utilities-0.155.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
92
- dycw_utilities-0.155.3.dist-info/entry_points.txt,sha256=BOD_SoDxwsfJYOLxhrSXhHP_T7iw-HXI9f2WVkzYxvQ,135
93
- dycw_utilities-0.155.3.dist-info/licenses/LICENSE,sha256=gppZp16M6nSVpBbUBrNL6JuYfvKwZiKgV7XoKKsHzqo,1066
94
- dycw_utilities-0.155.3.dist-info/RECORD,,
90
+ dycw_utilities-0.155.4.dist-info/METADATA,sha256=zStuqB5LeQevJmpVVzbnSRhmBY8h9OGkYNoTAsm4DVA,1643
91
+ dycw_utilities-0.155.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
92
+ dycw_utilities-0.155.4.dist-info/entry_points.txt,sha256=BOD_SoDxwsfJYOLxhrSXhHP_T7iw-HXI9f2WVkzYxvQ,135
93
+ dycw_utilities-0.155.4.dist-info/licenses/LICENSE,sha256=gppZp16M6nSVpBbUBrNL6JuYfvKwZiKgV7XoKKsHzqo,1066
94
+ dycw_utilities-0.155.4.dist-info/RECORD,,
utilities/__init__.py CHANGED
@@ -1,3 +1,3 @@
1
1
  from __future__ import annotations
2
2
 
3
- __version__ = "0.155.3"
3
+ __version__ = "0.155.4"
utilities/dataclasses.py CHANGED
@@ -25,7 +25,7 @@ from utilities.parse import (
25
25
  serialize_object,
26
26
  )
27
27
  from utilities.re import ExtractGroupError, extract_group
28
- from utilities.sentinel import Sentinel, sentinel
28
+ from utilities.sentinel import Sentinel, is_sentinel, sentinel
29
29
  from utilities.text import (
30
30
  BRACKETS,
31
31
  LIST_SEPARATOR,
@@ -275,8 +275,7 @@ def mapping_to_dataclass[T: Dataclass](
275
275
  default = {
276
276
  f.name
277
277
  for f in fields_use
278
- if (not isinstance(f.default, Sentinel))
279
- or (not isinstance(f.default_factory, Sentinel))
278
+ if (not is_sentinel(f.default)) or (not is_sentinel(f.default_factory))
280
279
  }
281
280
  have = set(field_names_to_values) | default
282
281
  missing = {f.name for f in fields_use} - have
@@ -434,12 +433,10 @@ def replace_non_sentinel[T: Dataclass](
434
433
  """Replace attributes on a dataclass, filtering out sentinel values."""
435
434
  if in_place:
436
435
  for k, v in kwargs.items():
437
- if not isinstance(v, Sentinel):
436
+ if not is_sentinel(v):
438
437
  setattr(obj, k, v)
439
438
  return None
440
- return replace(
441
- obj, **{k: v for k, v in kwargs.items() if not isinstance(v, Sentinel)}
442
- )
439
+ return replace(obj, **{k: v for k, v in kwargs.items() if not is_sentinel(v)})
443
440
 
444
441
 
445
442
  ##
@@ -912,17 +909,11 @@ class _YieldFieldsInstance[T]:
912
909
  extra: Mapping[type[U], Callable[[U, U], bool]] | None = None,
913
910
  ) -> bool:
914
911
  """Check if the field value equals its default."""
915
- if isinstance(self.default, Sentinel) and isinstance(
916
- self.default_factory, Sentinel
917
- ):
912
+ if is_sentinel(self.default) and is_sentinel(self.default_factory):
918
913
  return False
919
- if (not isinstance(self.default, Sentinel)) and isinstance(
920
- self.default_factory, Sentinel
921
- ):
914
+ if (not is_sentinel(self.default)) and is_sentinel(self.default_factory):
922
915
  expected = self.default
923
- elif isinstance(self.default, Sentinel) and (
924
- not isinstance(self.default_factory, Sentinel)
925
- ):
916
+ elif is_sentinel(self.default) and (not is_sentinel(self.default_factory)):
926
917
  expected = self.default_factory()
927
918
  else: # pragma: no cover
928
919
  raise ImpossibleCaseError(
utilities/functions.py CHANGED
@@ -19,7 +19,7 @@ from typing import TYPE_CHECKING, Any, Literal, TypeGuard, cast, overload, overr
19
19
  from whenever import Date, PlainDateTime, Time, TimeDelta, ZonedDateTime
20
20
 
21
21
  from utilities.reprlib import get_repr, get_repr_and_class
22
- from utilities.sentinel import Sentinel, sentinel
22
+ from utilities.sentinel import Sentinel, is_sentinel, sentinel
23
23
  from utilities.types import (
24
24
  Dataclass,
25
25
  Number,
@@ -864,7 +864,7 @@ def min_nullable[T: SupportsRichComparison, U](
864
864
  ) -> T | U:
865
865
  """Compute the minimum of a set of values; ignoring nulls."""
866
866
  values = (i for i in iterable if i is not None)
867
- if isinstance(default, Sentinel):
867
+ if is_sentinel(default):
868
868
  try:
869
869
  return min(values)
870
870
  except ValueError:
@@ -894,7 +894,7 @@ def max_nullable[T: SupportsRichComparison, U](
894
894
  ) -> T | U:
895
895
  """Compute the maximum of a set of values; ignoring nulls."""
896
896
  values = (i for i in iterable if i is not None)
897
- if isinstance(default, Sentinel):
897
+ if is_sentinel(default):
898
898
  try:
899
899
  return max(values)
900
900
  except ValueError:
utilities/hypothesis.py CHANGED
@@ -77,7 +77,7 @@ from utilities.math import (
77
77
  from utilities.os import get_env_var
78
78
  from utilities.pathlib import module_path, temp_cwd
79
79
  from utilities.platform import IS_WINDOWS
80
- from utilities.sentinel import Sentinel, sentinel
80
+ from utilities.sentinel import Sentinel, is_sentinel, sentinel
81
81
  from utilities.tempfile import TEMP_DIR, TemporaryDirectory
82
82
  from utilities.version import Version
83
83
  from utilities.whenever import (
@@ -363,14 +363,14 @@ def draw2[T](
363
363
  return value
364
364
  case None, SearchStrategy(), False:
365
365
  value2 = draw(default)
366
- if isinstance(value2, Sentinel):
366
+ if is_sentinel(value2):
367
367
  raise _Draw2DefaultGeneratedSentinelError
368
368
  return value2
369
369
  case Sentinel(), None, _:
370
370
  raise _Draw2InputResolvedToSentinelError
371
371
  case Sentinel(), SearchStrategy(), True:
372
372
  value2 = draw(default)
373
- if isinstance(value2, Sentinel):
373
+ if is_sentinel(value2):
374
374
  raise _Draw2DefaultGeneratedSentinelError
375
375
  return value2
376
376
  case Sentinel(), SearchStrategy(), False:
utilities/iterables.py CHANGED
@@ -40,7 +40,7 @@ from utilities.math import (
40
40
  check_integer,
41
41
  )
42
42
  from utilities.reprlib import get_repr
43
- from utilities.sentinel import Sentinel, sentinel
43
+ from utilities.sentinel import Sentinel, is_sentinel, sentinel
44
44
  from utilities.types import SupportsAdd, SupportsLT
45
45
 
46
46
  if TYPE_CHECKING:
@@ -1237,7 +1237,7 @@ def reduce_mappings[K, V, W](
1237
1237
  ) -> Mapping[K, V | W]:
1238
1238
  """Reduce a function over the values of a set of mappings."""
1239
1239
  chained = chain_mappings(*sequence)
1240
- if isinstance(initial, Sentinel):
1240
+ if is_sentinel(initial):
1241
1241
  func2 = cast("Callable[[V, V], V]", func)
1242
1242
  return {k: reduce(func2, v) for k, v in chained.items()}
1243
1243
  func2 = cast("Callable[[W, V], W]", func)
@@ -21,7 +21,7 @@ from more_itertools import peekable as _peekable
21
21
  from utilities.functions import get_class_name
22
22
  from utilities.iterables import OneNonUniqueError, one
23
23
  from utilities.reprlib import get_repr
24
- from utilities.sentinel import Sentinel, sentinel
24
+ from utilities.sentinel import Sentinel, is_sentinel, sentinel
25
25
 
26
26
  if TYPE_CHECKING:
27
27
  from collections.abc import Iterable, Iterator, Mapping, Sequence
@@ -290,9 +290,7 @@ class peekable[T](_peekable): # noqa: N801
290
290
  def peek[U](self, *, default: U) -> T | U: ...
291
291
  @override
292
292
  def peek(self, *, default: Any = sentinel) -> Any: # pyright: ignore[reportIncompatibleMethodOverride]
293
- if isinstance(default, Sentinel):
294
- return super().peek()
295
- return super().peek(default=default)
293
+ return super().peek() if is_sentinel(default) else super().peek(default=default)
296
294
 
297
295
  def takewhile(self, predicate: Callable[[T], bool], /) -> Iterator[T]:
298
296
  while bool(self) and predicate(self.peek()):
utilities/pqdm.py CHANGED
@@ -9,7 +9,7 @@ from tqdm.auto import tqdm as tqdm_auto
9
9
  from utilities.functions import get_func_name
10
10
  from utilities.iterables import apply_to_varargs
11
11
  from utilities.os import get_cpu_use
12
- from utilities.sentinel import Sentinel, sentinel
12
+ from utilities.sentinel import Sentinel, is_sentinel, sentinel
13
13
 
14
14
  if TYPE_CHECKING:
15
15
  from collections.abc import Callable, Iterable
@@ -98,7 +98,7 @@ def pqdm_starmap[T](
98
98
  def _get_desc(
99
99
  desc: str | None | Sentinel, func: Callable[..., Any], /
100
100
  ) -> dict[str, str]:
101
- desc_use = get_func_name(func) if isinstance(desc, Sentinel) else desc
101
+ desc_use = get_func_name(func) if is_sentinel(desc) else desc
102
102
  return {} if desc_use is None else {"desc": desc_use}
103
103
 
104
104
 
utilities/sentinel.py CHANGED
@@ -4,6 +4,8 @@ from dataclasses import dataclass
4
4
  from re import IGNORECASE, search
5
5
  from typing import Any, override
6
6
 
7
+ from typing_extensions import TypeIs
8
+
7
9
 
8
10
  class _Meta(type):
9
11
  """Metaclass for the sentinel."""
@@ -34,6 +36,13 @@ class Sentinel(metaclass=_Meta):
34
36
 
35
37
  sentinel = Sentinel()
36
38
 
39
+ ##
40
+
41
+
42
+ def is_sentinel(obj: Any, /) -> TypeIs[Sentinel]:
43
+ """Check if an object is the sentinel."""
44
+ return obj is sentinel
45
+
37
46
 
38
47
  ##
39
48
 
@@ -58,6 +67,7 @@ __all__ = [
58
67
  "SENTINEL_REPR",
59
68
  "ParseSentinelError",
60
69
  "Sentinel",
70
+ "is_sentinel",
61
71
  "parse_sentinel",
62
72
  "sentinel",
63
73
  ]