dycw-utilities 0.136.4__py3-none-any.whl → 0.136.6__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.136.4
3
+ Version: 0.136.6
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=dsiNRoGm7Boxbp7neOt74yIhZx6QM31tZ2CTGJY7K20,60
1
+ utilities/__init__.py,sha256=AkTwc_IslcficXaKXyPr9mQYVL_PcizHlUpq1xo5QTc,60
2
2
  utilities/aiolimiter.py,sha256=mD0wEiqMgwpty4XTbawFpnkkmJS6R4JRsVXFUaoitSU,628
3
3
  utilities/altair.py,sha256=HeZBVUocjkrTNwwKrClppsIqgNFF-ykv05HfZSoHYno,9104
4
4
  utilities/asyncio.py,sha256=dcGeKQzjLBXxKzZkVIk5oZsFXEcynVbRB9iNB5XEDZk,38526
@@ -23,13 +23,13 @@ utilities/getpass.py,sha256=DfN5UgMAtFCqS3dSfFHUfqIMZX2shXvwphOz_6J6f6A,103
23
23
  utilities/git.py,sha256=oi7-_l5e9haSANSCvQw25ufYGoNahuUPHAZ6114s3JQ,1191
24
24
  utilities/hashlib.py,sha256=SVTgtguur0P4elppvzOBbLEjVM3Pea0eWB61yg2ilxo,309
25
25
  utilities/http.py,sha256=WcahTcKYRtZ04WXQoWt5EGCgFPcyHD3EJdlMfxvDt-0,946
26
- utilities/hypothesis.py,sha256=_OFFvb8rVvMgXo04zaIFYw4p32QGrVHzJsR8pL3G8l4,36195
26
+ utilities/hypothesis.py,sha256=Ru3ZBhtGiuj-1vJjGuclymlYDAV_NC0WoUg9LY873d8,38044
27
27
  utilities/importlib.py,sha256=mV1xT_O_zt_GnZZ36tl3xOmMaN_3jErDWY54fX39F6Y,429
28
28
  utilities/inflect.py,sha256=DbqB5Q9FbRGJ1NbvEiZBirRMxCxgrz91zy5jCO9ZIs0,347
29
29
  utilities/ipython.py,sha256=V2oMYHvEKvlNBzxDXdLvKi48oUq2SclRg5xasjaXStw,763
30
30
  utilities/iterables.py,sha256=wlcm0PS2fKG-H0r0k367NOLrryMbfXLlwzUeAmBSvv8,43392
31
31
  utilities/jupyter.py,sha256=ft5JA7fBxXKzP-L9W8f2-wbF0QeYc_2uLQNFDVk4Z-M,2917
32
- utilities/libcst.py,sha256=Jto5ppzRzsxn4AD32IS8n0lbgLYXwsVJB6EY8giNZyY,4974
32
+ utilities/libcst.py,sha256=XTT8cCYAYfI9ZIdxjiTCqbF45cN-viDNDa7GE5mR2T4,5615
33
33
  utilities/lightweight_charts.py,sha256=JrkrAZMo6JID2Eoc9QCc05Y_pK4l2zsApIhmii1z2Ig,2764
34
34
  utilities/logging.py,sha256=j0xS7bNdZcMAobWSRahpg_d7GWewd_99oXvexrjWm6k,17841
35
35
  utilities/luigi.py,sha256=wK7cB3y8NXeSa8d6r_yTKRmjMguNmIPmy52yg10vPaI,4774
@@ -88,7 +88,7 @@ utilities/warnings.py,sha256=un1LvHv70PU-LLv8RxPVmugTzDJkkGXRMZTE2-fTQHw,1771
88
88
  utilities/whenever.py,sha256=A-yoOqBqrcVD1yDINDsTFDw7dq9-zgUGn_f8CxVUQJs,23332
89
89
  utilities/zipfile.py,sha256=24lQc9ATcJxHXBPc_tBDiJk48pWyRrlxO2fIsFxU0A8,699
90
90
  utilities/zoneinfo.py,sha256=oEH-nL3t4h9uawyZqWDtNtDAl6M-CLpLYGI_nI6DulM,1971
91
- dycw_utilities-0.136.4.dist-info/METADATA,sha256=2ONGjvk-6Ada8oSDMVX6w1cxOniaJPZpMI-Spv4Lhzs,1637
92
- dycw_utilities-0.136.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
93
- dycw_utilities-0.136.4.dist-info/licenses/LICENSE,sha256=gppZp16M6nSVpBbUBrNL6JuYfvKwZiKgV7XoKKsHzqo,1066
94
- dycw_utilities-0.136.4.dist-info/RECORD,,
91
+ dycw_utilities-0.136.6.dist-info/METADATA,sha256=abfQoeh81tTgbJfqO9Sh2xjiQ-Vj3pAI_jR9eOHdnGw,1637
92
+ dycw_utilities-0.136.6.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
93
+ dycw_utilities-0.136.6.dist-info/licenses/LICENSE,sha256=gppZp16M6nSVpBbUBrNL6JuYfvKwZiKgV7XoKKsHzqo,1066
94
+ dycw_utilities-0.136.6.dist-info/RECORD,,
utilities/__init__.py CHANGED
@@ -1,3 +1,3 @@
1
1
  from __future__ import annotations
2
2
 
3
- __version__ = "0.136.4"
3
+ __version__ = "0.136.6"
utilities/hypothesis.py CHANGED
@@ -106,6 +106,7 @@ if TYPE_CHECKING:
106
106
  from collections.abc import Collection, Hashable, Iterable, Iterator
107
107
 
108
108
  from hypothesis.database import ExampleDatabase
109
+ from libcst import Import, ImportFrom
109
110
  from numpy.random import RandomState
110
111
 
111
112
  from utilities.numpy import NDArrayB, NDArrayF, NDArrayI, NDArrayO
@@ -555,6 +556,59 @@ def hashables() -> SearchStrategy[Hashable]:
555
556
  ##
556
557
 
557
558
 
559
+ @composite
560
+ def import_froms(
561
+ draw: DrawFn,
562
+ /,
563
+ *,
564
+ min_depth: MaybeSearchStrategy[int | None] = None,
565
+ max_depth: MaybeSearchStrategy[int | None] = None,
566
+ ) -> ImportFrom:
567
+ """Strategy for generating import-froms."""
568
+ from utilities.libcst import generate_import_from
569
+
570
+ min_depth_, max_depth_ = [draw2(draw, d) for d in [min_depth, max_depth]]
571
+ path = draw(
572
+ paths(
573
+ min_depth=1 if min_depth_ is None else max(min_depth_, 1),
574
+ max_depth=max_depth_,
575
+ )
576
+ )
577
+ module = ".".join(path.parts)
578
+ name = draw(text_ascii(min_size=1))
579
+ asname = draw(text_ascii(min_size=1) | none())
580
+ return generate_import_from(module, name, asname=asname)
581
+
582
+
583
+ ##
584
+
585
+
586
+ @composite
587
+ def imports(
588
+ draw: DrawFn,
589
+ /,
590
+ *,
591
+ min_depth: MaybeSearchStrategy[int | None] = None,
592
+ max_depth: MaybeSearchStrategy[int | None] = None,
593
+ ) -> Import:
594
+ """Strategy for generating imports."""
595
+ from utilities.libcst import generate_import
596
+
597
+ min_depth_, max_depth_ = [draw2(draw, d) for d in [min_depth, max_depth]]
598
+ path = draw(
599
+ paths(
600
+ min_depth=1 if min_depth_ is None else max(min_depth_, 1),
601
+ max_depth=max_depth_,
602
+ )
603
+ )
604
+ module = ".".join(path.parts)
605
+ asname = draw(text_ascii(min_size=1) | none())
606
+ return generate_import(module, asname=asname)
607
+
608
+
609
+ ##
610
+
611
+
558
612
  @composite
559
613
  def int_arrays(
560
614
  draw: DrawFn,
@@ -746,11 +800,32 @@ def _pairs_map[T](elements: list[T], /) -> tuple[T, T]:
746
800
  ##
747
801
 
748
802
 
749
- def paths() -> SearchStrategy[Path]:
803
+ @composite
804
+ def paths(
805
+ draw: DrawFn,
806
+ /,
807
+ *,
808
+ min_depth: MaybeSearchStrategy[int | None] = None,
809
+ max_depth: MaybeSearchStrategy[int | None] = None,
810
+ ) -> Path:
750
811
  """Strategy for generating `Path`s."""
812
+ min_depth_, max_depth_ = [draw2(draw, d) for d in [min_depth, max_depth]]
813
+ parts = draw(
814
+ lists(
815
+ _path_parts(),
816
+ min_size=0 if min_depth_ is None else min_depth_,
817
+ max_size=max_depth_,
818
+ )
819
+ )
820
+ return Path(*parts)
821
+
822
+
823
+ @composite
824
+ def _path_parts(draw: DrawFn, /) -> str:
825
+ part = draw(text_ascii(min_size=1, max_size=10))
751
826
  reserved = {"AUX", "NUL"}
752
- strategy = text_ascii(min_size=1, max_size=10).filter(lambda x: x not in reserved)
753
- return lists(strategy, max_size=10).map(lambda parts: Path(*parts))
827
+ _ = assume(part not in reserved)
828
+ return part
754
829
 
755
830
 
756
831
  ##
@@ -1292,6 +1367,8 @@ __all__ = [
1292
1367
  "freqs",
1293
1368
  "git_repos",
1294
1369
  "hashables",
1370
+ "import_froms",
1371
+ "imports",
1295
1372
  "int32s",
1296
1373
  "int64s",
1297
1374
  "int_arrays",
utilities/libcst.py CHANGED
@@ -23,16 +23,6 @@ from libcst import (
23
23
  from utilities.errors import ImpossibleCaseError
24
24
 
25
25
 
26
- def generate_from_import(
27
- module: str, name: str, /, *, asname: str | None = None
28
- ) -> ImportFrom:
29
- """Generate an `ImportFrom` object."""
30
- alias = ImportAlias(
31
- name=Name(name), asname=AsName(Name(asname)) if asname else None
32
- )
33
- return ImportFrom(module=split_dotted_str(module), names=[alias])
34
-
35
-
36
26
  def generate_f_string(var: str, suffix: str, /) -> FormattedString:
37
27
  """Generate an f-string."""
38
28
  return FormattedString([
@@ -49,6 +39,36 @@ def generate_import(module: str, /, *, asname: str | None = None) -> Import:
49
39
  return Import(names=[alias])
50
40
 
51
41
 
42
+ def generate_import_from(
43
+ module: str, name: str, /, *, asname: str | None = None
44
+ ) -> ImportFrom:
45
+ """Generate an `ImportFrom` object."""
46
+ match name, asname:
47
+ case "*", None:
48
+ names = ImportStar()
49
+ case "*", str():
50
+ raise GenerateImportFromError(module=module, asname=asname)
51
+ case _, None:
52
+ alias = ImportAlias(name=Name(name))
53
+ names = [alias]
54
+ case _, str():
55
+ alias = ImportAlias(name=Name(name), asname=AsName(Name(asname)))
56
+ names = [alias]
57
+ case _ as never:
58
+ assert_never(never)
59
+ return ImportFrom(module=split_dotted_str(module), names=names)
60
+
61
+
62
+ @dataclass(kw_only=True, slots=True)
63
+ class GenerateImportFromError(Exception):
64
+ module: str
65
+ asname: str | None = None
66
+
67
+ @override
68
+ def __str__(self) -> str:
69
+ return f"Invalid import: 'from {self.module} import * as {self.asname}'"
70
+
71
+
52
72
  ##
53
73
 
54
74
 
@@ -168,10 +188,11 @@ def render_module(source: str | Module, /) -> str:
168
188
 
169
189
 
170
190
  __all__ = [
191
+ "GenerateImportFromError",
171
192
  "ParseImportError",
172
193
  "generate_f_string",
173
- "generate_from_import",
174
194
  "generate_import",
195
+ "generate_import_from",
175
196
  "join_dotted_str",
176
197
  "parse_import",
177
198
  "render_module",