dycw-utilities 0.176.3__py3-none-any.whl → 0.176.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.
- {dycw_utilities-0.176.3.dist-info → dycw_utilities-0.176.5.dist-info}/METADATA +2 -2
- {dycw_utilities-0.176.3.dist-info → dycw_utilities-0.176.5.dist-info}/RECORD +7 -6
- {dycw_utilities-0.176.3.dist-info → dycw_utilities-0.176.5.dist-info}/WHEEL +1 -1
- utilities/__init__.py +1 -1
- utilities/packaging.py +87 -0
- utilities/subprocess.py +8 -3
- {dycw_utilities-0.176.3.dist-info → dycw_utilities-0.176.5.dist-info}/entry_points.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: dycw-utilities
|
|
3
|
-
Version: 0.176.
|
|
3
|
+
Version: 0.176.5
|
|
4
4
|
Summary: Miscellaneous Python utilities
|
|
5
5
|
Author: Derek Wan
|
|
6
6
|
Author-email: Derek Wan <d.wan@icloud.com>
|
|
@@ -10,7 +10,7 @@ Requires-Dist: tzlocal>=5.3.1,<6
|
|
|
10
10
|
Requires-Dist: whenever>=0.9.4,<1
|
|
11
11
|
Requires-Dist: coloredlogs>=15.0.1,<16 ; extra == 'logging'
|
|
12
12
|
Requires-Dist: dycw-pytest-only>=2.1.1,<3 ; extra == 'test'
|
|
13
|
-
Requires-Dist: hypothesis>=6.
|
|
13
|
+
Requires-Dist: hypothesis>=6.149.1,<7 ; extra == 'test'
|
|
14
14
|
Requires-Dist: pytest>=9.0.2,<10 ; extra == 'test'
|
|
15
15
|
Requires-Dist: pytest-asyncio>=1.3.0,<2 ; extra == 'test'
|
|
16
16
|
Requires-Dist: pytest-cov>=7.0.0,<8 ; extra == 'test'
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
utilities/__init__.py,sha256=
|
|
1
|
+
utilities/__init__.py,sha256=chOgc1NV48pH7zK_NN0RHPlWQSfdIFGjwBbOXK_Es2A,60
|
|
2
2
|
utilities/altair.py,sha256=TLfRFbG9HwG7SLXoJ-v0r-t49ZaGgTQZD82cpjVi4vs,9085
|
|
3
3
|
utilities/asyncio.py,sha256=aJySVxBY0gqsIYnoNmH7-1r8djKuf4vSsU69VCD08t8,16772
|
|
4
4
|
utilities/atomicwrites.py,sha256=tPo6r-Rypd9u99u66B9z86YBPpnLrlHtwox_8Z7T34Y,5790
|
|
@@ -44,6 +44,7 @@ utilities/operator.py,sha256=C3NylZWGTVWRpwYHOPVhaLgRhw0DfpS4_XQ8KfPhBLQ,3613
|
|
|
44
44
|
utilities/optuna.py,sha256=C-fhWYiXHVPo1l8QctYkFJ4DyhbSrGorzP1dJb_qvd8,1933
|
|
45
45
|
utilities/orjson.py,sha256=T_0SlK811ysg46d3orvIPY3JpBa4FRMpP2wlPQo7-gU,41854
|
|
46
46
|
utilities/os.py,sha256=kjKKSQfnRqFTTZ315iavaaGd3gGuYNoSWlxVLCJjyQs,4852
|
|
47
|
+
utilities/packaging.py,sha256=kuGenKbyAwxZWL_mbkMzkNXKjhyi9a9tfZQwitrYYlM,2401
|
|
47
48
|
utilities/parse.py,sha256=g7Qm9eBOIeDId2tGA021CIaeF6jp1TI8rx4srdvlyoo,17937
|
|
48
49
|
utilities/pathlib.py,sha256=N4Ip8R9eCM-6GfvxUJ3T9oQIle2C2P52F-13BCFRdTg,9345
|
|
49
50
|
utilities/permissions.py,sha256=vLXlWztSVYffbrxptne7ksj6dU1HLekm4fEvS4ny_4Q,8944
|
|
@@ -80,7 +81,7 @@ utilities/sqlalchemy.py,sha256=HQYpd7LFxdTF5WYVWYtCJeEBI71EJm7ytvCGyAH9B-U,37163
|
|
|
80
81
|
utilities/sqlalchemy_polars.py,sha256=JCGhB37raSR7fqeWV5dTsciRTMVzIdVT9YSqKT0piT0,13370
|
|
81
82
|
utilities/statsmodels.py,sha256=koyiBHvpMcSiBfh99wFUfSggLNx7cuAw3rwyfAhoKpQ,3410
|
|
82
83
|
utilities/string.py,sha256=shmBK87zZwzGyixuNuXCiUbqzfeZ9xlrFwz6JTaRvDk,582
|
|
83
|
-
utilities/subprocess.py,sha256=
|
|
84
|
+
utilities/subprocess.py,sha256=eGRRQF-OXDy2kMSy7dv4fUzcPizvRgGBxYvPh-QVqZo,53980
|
|
84
85
|
utilities/tempfile.py,sha256=4kRGd4hyINDX4hpcYMtwzDcd-4IKjpTWT0MnjnKD4hE,4221
|
|
85
86
|
utilities/testbook.py,sha256=j1KmaVbrX9VrbeMgtPh5gk55myAsn3dyRUn7jGbPbRk,1294
|
|
86
87
|
utilities/text.py,sha256=UKW6xtF4bb0i-Gu1jctJvvQmeXk6U6UYNqoEnCLdaOo,14102
|
|
@@ -97,7 +98,7 @@ utilities/warnings.py,sha256=un1LvHv70PU-LLv8RxPVmugTzDJkkGXRMZTE2-fTQHw,1771
|
|
|
97
98
|
utilities/whenever.py,sha256=F4ek0-OBWxHYrZdmoZt76N2RnNyKY5KrEHt7rqO4AQE,60183
|
|
98
99
|
utilities/zipfile.py,sha256=24lQc9ATcJxHXBPc_tBDiJk48pWyRrlxO2fIsFxU0A8,699
|
|
99
100
|
utilities/zoneinfo.py,sha256=tdIScrTB2-B-LH0ukb1HUXKooLknOfJNwHk10MuMYvA,3619
|
|
100
|
-
dycw_utilities-0.176.
|
|
101
|
-
dycw_utilities-0.176.
|
|
102
|
-
dycw_utilities-0.176.
|
|
103
|
-
dycw_utilities-0.176.
|
|
101
|
+
dycw_utilities-0.176.5.dist-info/WHEEL,sha256=KSLUh82mDPEPk0Bx0ScXlWL64bc8KmzIPNcpQZFV-6E,79
|
|
102
|
+
dycw_utilities-0.176.5.dist-info/entry_points.txt,sha256=cOGtKeJI0KXLSV7MJ8Dhc2G8jPgDcBDm53MVNJU4ycI,136
|
|
103
|
+
dycw_utilities-0.176.5.dist-info/METADATA,sha256=g6FzLC0r4g8uwbM_zouJhCaaHM0IsQ1q33xQyS5tZp0,1398
|
|
104
|
+
dycw_utilities-0.176.5.dist-info/RECORD,,
|
utilities/__init__.py
CHANGED
utilities/packaging.py
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import TYPE_CHECKING, Self, override
|
|
5
|
+
|
|
6
|
+
import packaging._parser
|
|
7
|
+
import packaging.requirements
|
|
8
|
+
from packaging.requirements import _parse_requirement
|
|
9
|
+
from packaging.specifiers import Specifier, SpecifierSet
|
|
10
|
+
|
|
11
|
+
from utilities.iterables import OneEmptyError, one
|
|
12
|
+
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from packaging._parser import MarkerList
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass(order=True, unsafe_hash=True, kw_only=True, slots=True)
|
|
18
|
+
class Requirement:
|
|
19
|
+
requirement: str
|
|
20
|
+
_parsed_req: packaging._parser.ParsedRequirement
|
|
21
|
+
_custom_req: _CustomRequirement
|
|
22
|
+
|
|
23
|
+
def __getitem__(self, key: str, /) -> str:
|
|
24
|
+
return self.specifier_set[key]
|
|
25
|
+
|
|
26
|
+
@override
|
|
27
|
+
def __str__(self) -> str:
|
|
28
|
+
return str(self._custom_req)
|
|
29
|
+
|
|
30
|
+
@classmethod
|
|
31
|
+
def new(cls, requirement: str, /) -> Self:
|
|
32
|
+
return cls(
|
|
33
|
+
requirement=requirement,
|
|
34
|
+
_parsed_req=_parse_requirement(requirement),
|
|
35
|
+
_custom_req=_CustomRequirement(requirement),
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
@property
|
|
39
|
+
def extras(self) -> list[str]:
|
|
40
|
+
return self._parsed_req.extras
|
|
41
|
+
|
|
42
|
+
@property
|
|
43
|
+
def marker(self) -> MarkerList | None:
|
|
44
|
+
return self._parsed_req.marker
|
|
45
|
+
|
|
46
|
+
@property
|
|
47
|
+
def name(self) -> str:
|
|
48
|
+
return self._parsed_req.name
|
|
49
|
+
|
|
50
|
+
@property
|
|
51
|
+
def specifier(self) -> str:
|
|
52
|
+
return self._parsed_req.specifier
|
|
53
|
+
|
|
54
|
+
@property
|
|
55
|
+
def specifier_set(self) -> _CustomSpecifierSet:
|
|
56
|
+
return _CustomSpecifierSet(_parse_requirement(self.requirement).specifier)
|
|
57
|
+
|
|
58
|
+
@property
|
|
59
|
+
def url(self) -> str:
|
|
60
|
+
return self._parsed_req.url
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class _CustomRequirement(packaging.requirements.Requirement):
|
|
64
|
+
@override
|
|
65
|
+
def __init__(self, requirement_string: str) -> None:
|
|
66
|
+
super().__init__(requirement_string)
|
|
67
|
+
parsed = _parse_requirement(requirement_string)
|
|
68
|
+
self.specifier = _CustomSpecifierSet(parsed.specifier)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class _CustomSpecifierSet(SpecifierSet):
|
|
72
|
+
def __getitem__(self, key: str, /) -> str:
|
|
73
|
+
try:
|
|
74
|
+
return one(s.version for s in self if s.operator == key)
|
|
75
|
+
except OneEmptyError:
|
|
76
|
+
raise KeyError(key) from None
|
|
77
|
+
|
|
78
|
+
@override
|
|
79
|
+
def __str__(self) -> str:
|
|
80
|
+
specs = sorted(self._specs, key=self._key)
|
|
81
|
+
return ", ".join(map(str, specs))
|
|
82
|
+
|
|
83
|
+
def _key(self, spec: Specifier, /) -> int:
|
|
84
|
+
return [">=", "<"].index(spec.operator)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
__all__ = ["Requirement"]
|
utilities/subprocess.py
CHANGED
|
@@ -994,10 +994,15 @@ def _rsync_many_prepare(
|
|
|
994
994
|
case Path():
|
|
995
995
|
cp(src, temp_src / name)
|
|
996
996
|
case str():
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
997
|
+
try:
|
|
998
|
+
exists = Path(src).exists()
|
|
999
|
+
except OSError:
|
|
1000
1000
|
tee(temp_src / name, src)
|
|
1001
|
+
else:
|
|
1002
|
+
if exists:
|
|
1003
|
+
cp(src, temp_src / name)
|
|
1004
|
+
else:
|
|
1005
|
+
tee(temp_src / name, src)
|
|
1001
1006
|
case never:
|
|
1002
1007
|
assert_never(never)
|
|
1003
1008
|
cmds: list[list[str]] = [
|
|
File without changes
|