dycw-utilities 0.138.4__py3-none-any.whl → 0.138.5__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.138.4
3
+ Version: 0.138.5
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=AJA02WwvABRcKbyBb6aLadckmkmDr4Ah5qHq77UCnD8,60
1
+ utilities/__init__.py,sha256=8_NgkEVVSVQiH0KSjlNRZwW_d9Lb2cnfj8c1HrNPmGA,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
@@ -42,7 +42,7 @@ utilities/optuna.py,sha256=C-fhWYiXHVPo1l8QctYkFJ4DyhbSrGorzP1dJb_qvd8,1933
42
42
  utilities/orjson.py,sha256=WWV2QukCIuwT8OAOtmKhLhxezXPVbeA_fQCucmGmbRA,37106
43
43
  utilities/os.py,sha256=yMNAKMyY8oFgQ1yN3TQYnwa5-A_FXz4tCDbhIctQHSs,3736
44
44
  utilities/parse.py,sha256=JcJn5yXKhIWXBCwgBdPsyu7Hvcuw6kyEdqvaebCaI9k,17951
45
- utilities/pathlib.py,sha256=jCFPZm4rBKylEva9wDVTwQlTTVKMepu92WrTpoGa438,3248
45
+ utilities/pathlib.py,sha256=yE85i5nlXXdW9HFE2KzjmP2yyWhnZYQkMZ9TjQ8UQRk,4454
46
46
  utilities/period.py,sha256=6jEff_qAiE7xdFaQ1DnKgNf10D2wHhzt7hQXCBoKlgc,6842
47
47
  utilities/pickle.py,sha256=MBT2xZCsv0pH868IXLGKnlcqNx2IRVKYNpRcqiQQqxw,653
48
48
  utilities/platform.py,sha256=5uCKRf_ij7ukJDcbnNfhY2ay9fbrpiNLRO1t2QvcwqQ,2825
@@ -87,7 +87,7 @@ utilities/warnings.py,sha256=un1LvHv70PU-LLv8RxPVmugTzDJkkGXRMZTE2-fTQHw,1771
87
87
  utilities/whenever.py,sha256=R5d9UCNCdAOyjwLUmfH2Vn8Ykee8OHQi2skRTFfbZMM,20492
88
88
  utilities/zipfile.py,sha256=24lQc9ATcJxHXBPc_tBDiJk48pWyRrlxO2fIsFxU0A8,699
89
89
  utilities/zoneinfo.py,sha256=oEH-nL3t4h9uawyZqWDtNtDAl6M-CLpLYGI_nI6DulM,1971
90
- dycw_utilities-0.138.4.dist-info/METADATA,sha256=Am7nGDdcdeHFgK71Hso5euQ7WwzvnqcQoRuqGb-uPBw,1638
91
- dycw_utilities-0.138.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
92
- dycw_utilities-0.138.4.dist-info/licenses/LICENSE,sha256=gppZp16M6nSVpBbUBrNL6JuYfvKwZiKgV7XoKKsHzqo,1066
93
- dycw_utilities-0.138.4.dist-info/RECORD,,
90
+ dycw_utilities-0.138.5.dist-info/METADATA,sha256=49xR0EeDJd73mcxgxDir4zIZrsvAyW3Cb-iorojBolY,1638
91
+ dycw_utilities-0.138.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
92
+ dycw_utilities-0.138.5.dist-info/licenses/LICENSE,sha256=gppZp16M6nSVpBbUBrNL6JuYfvKwZiKgV7XoKKsHzqo,1066
93
+ dycw_utilities-0.138.5.dist-info/RECORD,,
utilities/__init__.py CHANGED
@@ -1,3 +1,3 @@
1
1
  from __future__ import annotations
2
2
 
3
- __version__ = "0.138.4"
3
+ __version__ = "0.138.5"
utilities/pathlib.py CHANGED
@@ -1,7 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from collections.abc import Callable
4
- from contextlib import contextmanager, suppress
4
+ from contextlib import contextmanager
5
5
  from dataclasses import dataclass
6
6
  from itertools import chain
7
7
  from os import chdir
@@ -11,6 +11,7 @@ from re import IGNORECASE, search
11
11
  from subprocess import PIPE, CalledProcessError, check_output
12
12
  from typing import TYPE_CHECKING, assert_never, overload, override
13
13
 
14
+ from utilities.errors import ImpossibleCaseError
14
15
  from utilities.sentinel import Sentinel, sentinel
15
16
 
16
17
  if TYPE_CHECKING:
@@ -73,23 +74,50 @@ def get_path(
73
74
  def get_root(*, path: MaybeCallablePathLike | None = None) -> Path:
74
75
  """Get the root of a path."""
75
76
  path = get_path(path=path)
77
+ path_dir = path.parent if path.is_file() else path
76
78
  try:
77
79
  output = check_output(
78
- ["git", "rev-parse", "--show-toplevel"], stderr=PIPE, cwd=path, text=True
80
+ ["git", "rev-parse", "--show-toplevel"],
81
+ stderr=PIPE,
82
+ cwd=path_dir,
83
+ text=True,
79
84
  )
80
85
  except CalledProcessError as error:
81
86
  # newer versions of git report "Not a git repository", whilst older
82
87
  # versions report "not a git repository"
83
88
  if not search("fatal: not a git repository", error.stderr, flags=IGNORECASE):
84
89
  raise # pragma: no cover
90
+ root_git = None
85
91
  else:
86
- return Path(output.strip("\n"))
87
- all_paths = list(chain([path], path.parents))
88
- with suppress(StopIteration):
89
- return next(
90
- p for p in all_paths if any(p_i.name == ".envrc" for p_i in p.iterdir())
92
+ root_git = Path(output.strip("\n")).resolve()
93
+ all_paths = list(chain([path_dir], path_dir.parents))
94
+ try:
95
+ root_envrc = next(
96
+ p.resolve()
97
+ for p in all_paths
98
+ if any(p_i.name == ".envrc" for p_i in p.iterdir())
91
99
  )
92
- raise GetRootError(path=path)
100
+ except StopIteration:
101
+ root_envrc = None
102
+ match root_git, root_envrc:
103
+ case None, None:
104
+ raise GetRootError(path=path)
105
+ case Path(), None:
106
+ return root_git
107
+ case None, Path():
108
+ return root_envrc
109
+ case Path(), Path():
110
+ if root_git == root_envrc:
111
+ return root_git
112
+ if is_sub_path(root_git, root_envrc, strict=True):
113
+ return root_git
114
+ if is_sub_path(root_envrc, root_git, strict=True):
115
+ return root_envrc
116
+ raise ImpossibleCaseError( # pragma: no cover
117
+ case=[f"{root_git=}", f"{root_envrc=}"]
118
+ )
119
+ case _ as never:
120
+ assert_never(never)
93
121
 
94
122
 
95
123
  @dataclass(kw_only=True, slots=True)
@@ -104,6 +132,15 @@ class GetRootError(Exception):
104
132
  ##
105
133
 
106
134
 
135
+ def is_sub_path(x: PathLike, y: PathLike, /, *, strict: bool = False) -> bool:
136
+ """Check if a path is a sub path of another."""
137
+ x, y = [Path(i).resolve() for i in [x, y]]
138
+ return x.is_relative_to(y) and not (strict and y.is_relative_to(x))
139
+
140
+
141
+ ##
142
+
143
+
107
144
  def list_dir(path: PathLike, /) -> Sequence[Path]:
108
145
  """List the contents of a directory."""
109
146
  return sorted(Path(path).iterdir())
@@ -123,4 +160,12 @@ def temp_cwd(path: PathLike, /) -> Iterator[None]:
123
160
  chdir(prev)
124
161
 
125
162
 
126
- __all__ = ["PWD", "ensure_suffix", "expand_path", "get_path", "list_dir", "temp_cwd"]
163
+ __all__ = [
164
+ "PWD",
165
+ "ensure_suffix",
166
+ "expand_path",
167
+ "get_path",
168
+ "is_sub_path",
169
+ "list_dir",
170
+ "temp_cwd",
171
+ ]