dycw-utilities 0.117.1__py3-none-any.whl → 0.119.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.
- {dycw_utilities-0.117.1.dist-info → dycw_utilities-0.119.0.dist-info}/METADATA +27 -27
- {dycw_utilities-0.117.1.dist-info → dycw_utilities-0.119.0.dist-info}/RECORD +17 -17
- utilities/__init__.py +1 -1
- utilities/asyncio.py +2 -224
- utilities/click.py +19 -19
- utilities/datetime.py +5 -5
- utilities/fastapi.py +3 -8
- utilities/hypothesis.py +44 -44
- utilities/orjson.py +2 -2
- utilities/period.py +2 -2
- utilities/redis.py +1 -18
- utilities/slack_sdk.py +2 -68
- utilities/sqlalchemy.py +1 -44
- utilities/whenever.py +66 -104
- utilities/zoneinfo.py +3 -3
- {dycw_utilities-0.117.1.dist-info → dycw_utilities-0.119.0.dist-info}/WHEEL +0 -0
- {dycw_utilities-0.117.1.dist-info → dycw_utilities-0.119.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: dycw-utilities
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.119.0
|
4
4
|
Author-email: Derek Wan <d.wan@icloud.com>
|
5
5
|
License-File: LICENSE
|
6
6
|
Requires-Python: >=3.12
|
@@ -26,7 +26,7 @@ Requires-Dist: atomicwrites<1.5,>=1.4.1; extra == 'zzz-test-altair'
|
|
26
26
|
Requires-Dist: img2pdf<0.7,>=0.6.0; extra == 'zzz-test-altair'
|
27
27
|
Requires-Dist: polars-lts-cpu<1.30,>=1.29.0; extra == 'zzz-test-altair'
|
28
28
|
Requires-Dist: vl-convert-python<1.8,>=1.7.0; extra == 'zzz-test-altair'
|
29
|
-
Requires-Dist: whenever<0.
|
29
|
+
Requires-Dist: whenever<0.9,>=0.8.0; extra == 'zzz-test-altair'
|
30
30
|
Provides-Extra: zzz-test-astor
|
31
31
|
Requires-Dist: astor<0.9,>=0.8.1; extra == 'zzz-test-astor'
|
32
32
|
Provides-Extra: zzz-test-asyncio
|
@@ -39,20 +39,20 @@ Requires-Dist: cachetools<5.6,>=5.5.2; extra == 'zzz-test-cachetools'
|
|
39
39
|
Provides-Extra: zzz-test-click
|
40
40
|
Requires-Dist: click<8.3,>=8.2.0; extra == 'zzz-test-click'
|
41
41
|
Requires-Dist: sqlalchemy<2.1,>=2.0.41; extra == 'zzz-test-click'
|
42
|
-
Requires-Dist: whenever<0.
|
42
|
+
Requires-Dist: whenever<0.9,>=0.8.0; extra == 'zzz-test-click'
|
43
43
|
Provides-Extra: zzz-test-contextlib
|
44
44
|
Provides-Extra: zzz-test-contextvars
|
45
45
|
Provides-Extra: zzz-test-cryptography
|
46
|
-
Requires-Dist: cryptography<
|
46
|
+
Requires-Dist: cryptography<45.1,>=45.0.2; extra == 'zzz-test-cryptography'
|
47
47
|
Provides-Extra: zzz-test-cvxpy
|
48
48
|
Requires-Dist: cvxpy<1.7,>=1.6.5; extra == 'zzz-test-cvxpy'
|
49
49
|
Provides-Extra: zzz-test-dataclasses
|
50
50
|
Requires-Dist: orjson<3.11,>=3.10.15; extra == 'zzz-test-dataclasses'
|
51
51
|
Requires-Dist: polars-lts-cpu<1.30,>=1.29.0; extra == 'zzz-test-dataclasses'
|
52
|
-
Requires-Dist: whenever<0.
|
52
|
+
Requires-Dist: whenever<0.9,>=0.8.0; extra == 'zzz-test-dataclasses'
|
53
53
|
Provides-Extra: zzz-test-datetime
|
54
54
|
Requires-Dist: tzlocal<5.4,>=5.3.1; extra == 'zzz-test-datetime'
|
55
|
-
Requires-Dist: whenever<0.
|
55
|
+
Requires-Dist: whenever<0.9,>=0.8.0; extra == 'zzz-test-datetime'
|
56
56
|
Provides-Extra: zzz-test-enum
|
57
57
|
Provides-Extra: zzz-test-errors
|
58
58
|
Provides-Extra: zzz-test-eventkit
|
@@ -71,29 +71,29 @@ Provides-Extra: zzz-test-git
|
|
71
71
|
Provides-Extra: zzz-test-hashlib
|
72
72
|
Requires-Dist: orjson<3.11,>=3.10.15; extra == 'zzz-test-hashlib'
|
73
73
|
Requires-Dist: polars-lts-cpu<1.30,>=1.29.0; extra == 'zzz-test-hashlib'
|
74
|
-
Requires-Dist: whenever<0.
|
74
|
+
Requires-Dist: whenever<0.9,>=0.8.0; extra == 'zzz-test-hashlib'
|
75
75
|
Provides-Extra: zzz-test-http
|
76
76
|
Requires-Dist: atomicwrites<1.5,>=1.4.1; extra == 'zzz-test-http'
|
77
77
|
Requires-Dist: orjson<3.11,>=3.10.18; extra == 'zzz-test-http'
|
78
|
-
Requires-Dist: whenever<0.
|
78
|
+
Requires-Dist: whenever<0.9,>=0.8.0; extra == 'zzz-test-http'
|
79
79
|
Provides-Extra: zzz-test-hypothesis
|
80
80
|
Requires-Dist: aiosqlite<0.22,>=0.21.0; extra == 'zzz-test-hypothesis'
|
81
81
|
Requires-Dist: asyncpg<0.31,>=0.30.0; extra == 'zzz-test-hypothesis'
|
82
82
|
Requires-Dist: greenlet<3.3,>=3.2.0; extra == 'zzz-test-hypothesis'
|
83
83
|
Requires-Dist: hypothesis<6.132,>=6.131.19; extra == 'zzz-test-hypothesis'
|
84
84
|
Requires-Dist: luigi<3.7,>=3.6.0; extra == 'zzz-test-hypothesis'
|
85
|
-
Requires-Dist: numpy<2.3,>=2.2.
|
85
|
+
Requires-Dist: numpy<2.3,>=2.2.6; extra == 'zzz-test-hypothesis'
|
86
86
|
Requires-Dist: pathvalidate<3.3,>=3.2.3; extra == 'zzz-test-hypothesis'
|
87
87
|
Requires-Dist: redis<6.2,>=6.1.0; extra == 'zzz-test-hypothesis'
|
88
88
|
Requires-Dist: sqlalchemy<2.1,>=2.0.41; extra == 'zzz-test-hypothesis'
|
89
89
|
Requires-Dist: tenacity<9.0,>=8.5.0; extra == 'zzz-test-hypothesis'
|
90
90
|
Requires-Dist: tzlocal<5.4,>=5.3.1; extra == 'zzz-test-hypothesis'
|
91
|
-
Requires-Dist: whenever<0.
|
91
|
+
Requires-Dist: whenever<0.9,>=0.8.0; extra == 'zzz-test-hypothesis'
|
92
92
|
Provides-Extra: zzz-test-ipython
|
93
93
|
Requires-Dist: ipython<9.1,>=9.0.1; extra == 'zzz-test-ipython'
|
94
94
|
Provides-Extra: zzz-test-iterables
|
95
95
|
Requires-Dist: polars-lts-cpu<1.30,>=1.29.0; extra == 'zzz-test-iterables'
|
96
|
-
Requires-Dist: whenever<0.
|
96
|
+
Requires-Dist: whenever<0.9,>=0.8.0; extra == 'zzz-test-iterables'
|
97
97
|
Provides-Extra: zzz-test-jupyter
|
98
98
|
Requires-Dist: jupyterlab<4.3,>=4.2.0; extra == 'zzz-test-jupyter'
|
99
99
|
Requires-Dist: pandas<2.3,>=2.2.2; extra == 'zzz-test-jupyter'
|
@@ -105,24 +105,24 @@ Requires-Dist: concurrent-log-handler<0.10,>=0.9.26; extra == 'zzz-test-logging'
|
|
105
105
|
Requires-Dist: rich<14.1,>=14.0.0; extra == 'zzz-test-logging'
|
106
106
|
Requires-Dist: tomlkit<0.14,>=0.13.2; extra == 'zzz-test-logging'
|
107
107
|
Requires-Dist: tzlocal<5.4,>=5.3.1; extra == 'zzz-test-logging'
|
108
|
-
Requires-Dist: whenever<0.
|
108
|
+
Requires-Dist: whenever<0.9,>=0.8.0; extra == 'zzz-test-logging'
|
109
109
|
Provides-Extra: zzz-test-loguru
|
110
110
|
Requires-Dist: loguru<0.8,>=0.7.3; extra == 'zzz-test-loguru'
|
111
111
|
Provides-Extra: zzz-test-luigi
|
112
112
|
Requires-Dist: luigi<3.7,>=3.6.0; extra == 'zzz-test-luigi'
|
113
|
-
Requires-Dist: whenever<0.
|
113
|
+
Requires-Dist: whenever<0.9,>=0.8.0; extra == 'zzz-test-luigi'
|
114
114
|
Provides-Extra: zzz-test-math
|
115
|
-
Requires-Dist: numpy<2.3,>=2.2.
|
115
|
+
Requires-Dist: numpy<2.3,>=2.2.6; extra == 'zzz-test-math'
|
116
116
|
Provides-Extra: zzz-test-memory-profiler
|
117
117
|
Requires-Dist: memory-profiler<0.62,>=0.61.0; extra == 'zzz-test-memory-profiler'
|
118
118
|
Provides-Extra: zzz-test-modules
|
119
119
|
Provides-Extra: zzz-test-more-itertools
|
120
120
|
Requires-Dist: more-itertools<10.8,>=10.7.0; extra == 'zzz-test-more-itertools'
|
121
121
|
Provides-Extra: zzz-test-numpy
|
122
|
-
Requires-Dist: numpy<2.3,>=2.2.
|
122
|
+
Requires-Dist: numpy<2.3,>=2.2.6; extra == 'zzz-test-numpy'
|
123
123
|
Provides-Extra: zzz-test-operator
|
124
124
|
Requires-Dist: polars-lts-cpu<1.30,>=1.29.0; extra == 'zzz-test-operator'
|
125
|
-
Requires-Dist: whenever<0.
|
125
|
+
Requires-Dist: whenever<0.9,>=0.8.0; extra == 'zzz-test-operator'
|
126
126
|
Provides-Extra: zzz-test-optuna
|
127
127
|
Requires-Dist: optuna<4.4,>=4.3.0; extra == 'zzz-test-optuna'
|
128
128
|
Provides-Extra: zzz-test-orjson
|
@@ -130,7 +130,7 @@ Requires-Dist: orjson<3.11,>=3.10.15; extra == 'zzz-test-orjson'
|
|
130
130
|
Requires-Dist: polars-lts-cpu<1.30,>=1.29.0; extra == 'zzz-test-orjson'
|
131
131
|
Requires-Dist: rich<14.1,>=14.0.0; extra == 'zzz-test-orjson'
|
132
132
|
Requires-Dist: tzlocal<5.4,>=5.3.1; extra == 'zzz-test-orjson'
|
133
|
-
Requires-Dist: whenever<0.
|
133
|
+
Requires-Dist: whenever<0.9,>=0.8.0; extra == 'zzz-test-orjson'
|
134
134
|
Provides-Extra: zzz-test-os
|
135
135
|
Provides-Extra: zzz-test-pathlib
|
136
136
|
Provides-Extra: zzz-test-pickle
|
@@ -138,7 +138,7 @@ Requires-Dist: atomicwrites<1.5,>=1.4.1; extra == 'zzz-test-pickle'
|
|
138
138
|
Provides-Extra: zzz-test-platform
|
139
139
|
Provides-Extra: zzz-test-polars
|
140
140
|
Requires-Dist: polars-lts-cpu<1.30,>=1.29.0; extra == 'zzz-test-polars'
|
141
|
-
Requires-Dist: whenever<0.
|
141
|
+
Requires-Dist: whenever<0.9,>=0.8.0; extra == 'zzz-test-polars'
|
142
142
|
Provides-Extra: zzz-test-pqdm
|
143
143
|
Requires-Dist: pqdm<0.3,>=0.2.0; extra == 'zzz-test-pqdm'
|
144
144
|
Provides-Extra: zzz-test-pydantic
|
@@ -153,12 +153,12 @@ Requires-Dist: pyrsistent<0.21,>=0.20.0; extra == 'zzz-test-pyrsistent'
|
|
153
153
|
Provides-Extra: zzz-test-pytest
|
154
154
|
Requires-Dist: atomicwrites<1.5,>=1.4.1; extra == 'zzz-test-pytest'
|
155
155
|
Requires-Dist: orjson<3.11,>=3.10.18; extra == 'zzz-test-pytest'
|
156
|
-
Requires-Dist: whenever<0.
|
156
|
+
Requires-Dist: whenever<0.9,>=0.8.0; extra == 'zzz-test-pytest'
|
157
157
|
Provides-Extra: zzz-test-pytest-regressions
|
158
158
|
Requires-Dist: pytest-regressions<2.8,>=2.7.0; extra == 'zzz-test-pytest-regressions'
|
159
159
|
Provides-Extra: zzz-test-python-dotenv
|
160
160
|
Requires-Dist: python-dotenv<1.2,>=1.1.0; extra == 'zzz-test-python-dotenv'
|
161
|
-
Requires-Dist: whenever<0.
|
161
|
+
Requires-Dist: whenever<0.9,>=0.8.0; extra == 'zzz-test-python-dotenv'
|
162
162
|
Provides-Extra: zzz-test-random
|
163
163
|
Provides-Extra: zzz-test-re
|
164
164
|
Provides-Extra: zzz-test-redis
|
@@ -168,7 +168,7 @@ Requires-Dist: redis<6.2,>=6.1.0; extra == 'zzz-test-redis'
|
|
168
168
|
Requires-Dist: rich<14.1,>=14.0.0; extra == 'zzz-test-redis'
|
169
169
|
Requires-Dist: tenacity<9.0,>=8.5.0; extra == 'zzz-test-redis'
|
170
170
|
Requires-Dist: tzlocal<5.4,>=5.3.1; extra == 'zzz-test-redis'
|
171
|
-
Requires-Dist: whenever<0.
|
171
|
+
Requires-Dist: whenever<0.9,>=0.8.0; extra == 'zzz-test-redis'
|
172
172
|
Provides-Extra: zzz-test-rich
|
173
173
|
Requires-Dist: rich<14.1,>=14.0.0; extra == 'zzz-test-rich'
|
174
174
|
Provides-Extra: zzz-test-scipy
|
@@ -194,7 +194,7 @@ Requires-Dist: nest-asyncio<1.7,>=1.6.0; extra == 'zzz-test-sqlalchemy-polars'
|
|
194
194
|
Requires-Dist: polars-lts-cpu<1.30,>=1.29.0; extra == 'zzz-test-sqlalchemy-polars'
|
195
195
|
Requires-Dist: sqlalchemy<2.1,>=2.0.41; extra == 'zzz-test-sqlalchemy-polars'
|
196
196
|
Requires-Dist: tenacity<9.0,>=8.5.0; extra == 'zzz-test-sqlalchemy-polars'
|
197
|
-
Requires-Dist: whenever<0.
|
197
|
+
Requires-Dist: whenever<0.9,>=0.8.0; extra == 'zzz-test-sqlalchemy-polars'
|
198
198
|
Provides-Extra: zzz-test-streamlit
|
199
199
|
Requires-Dist: streamlit<1.46,>=1.45.0; extra == 'zzz-test-streamlit'
|
200
200
|
Provides-Extra: zzz-test-sys
|
@@ -202,7 +202,7 @@ Requires-Dist: atomicwrites<1.5,>=1.4.1; extra == 'zzz-test-sys'
|
|
202
202
|
Requires-Dist: rich<14.1,>=14.0.0; extra == 'zzz-test-sys'
|
203
203
|
Requires-Dist: tomlkit<0.14,>=0.13.2; extra == 'zzz-test-sys'
|
204
204
|
Requires-Dist: tzlocal<5.4,>=5.3.1; extra == 'zzz-test-sys'
|
205
|
-
Requires-Dist: whenever<0.
|
205
|
+
Requires-Dist: whenever<0.9,>=0.8.0; extra == 'zzz-test-sys'
|
206
206
|
Provides-Extra: zzz-test-tempfile
|
207
207
|
Provides-Extra: zzz-test-tenacity
|
208
208
|
Requires-Dist: tenacity<9.0,>=8.5.0; extra == 'zzz-test-tenacity'
|
@@ -213,11 +213,11 @@ Provides-Extra: zzz-test-traceback
|
|
213
213
|
Requires-Dist: rich<14.1,>=14.0.0; extra == 'zzz-test-traceback'
|
214
214
|
Requires-Dist: tomlkit<0.14,>=0.13.2; extra == 'zzz-test-traceback'
|
215
215
|
Requires-Dist: tzlocal<5.4,>=5.3.1; extra == 'zzz-test-traceback'
|
216
|
-
Requires-Dist: whenever<0.
|
216
|
+
Requires-Dist: whenever<0.9,>=0.8.0; extra == 'zzz-test-traceback'
|
217
217
|
Provides-Extra: zzz-test-types
|
218
218
|
Provides-Extra: zzz-test-typing
|
219
219
|
Requires-Dist: polars-lts-cpu<1.30,>=1.29.0; extra == 'zzz-test-typing'
|
220
|
-
Requires-Dist: whenever<0.
|
220
|
+
Requires-Dist: whenever<0.9,>=0.8.0; extra == 'zzz-test-typing'
|
221
221
|
Provides-Extra: zzz-test-tzlocal
|
222
222
|
Requires-Dist: tzlocal<5.4,>=5.3.1; extra == 'zzz-test-tzlocal'
|
223
223
|
Provides-Extra: zzz-test-uuid
|
@@ -225,11 +225,11 @@ Provides-Extra: zzz-test-version
|
|
225
225
|
Requires-Dist: tomlkit<0.14,>=0.13.2; extra == 'zzz-test-version'
|
226
226
|
Provides-Extra: zzz-test-warnings
|
227
227
|
Provides-Extra: zzz-test-whenever
|
228
|
-
Requires-Dist: whenever<0.
|
228
|
+
Requires-Dist: whenever<0.9,>=0.8.0; extra == 'zzz-test-whenever'
|
229
229
|
Provides-Extra: zzz-test-zipfile
|
230
230
|
Provides-Extra: zzz-test-zoneinfo
|
231
231
|
Requires-Dist: tzdata<2025.3,>=2025.2; extra == 'zzz-test-zoneinfo'
|
232
|
-
Requires-Dist: whenever<0.
|
232
|
+
Requires-Dist: whenever<0.9,>=0.8.0; extra == 'zzz-test-zoneinfo'
|
233
233
|
Description-Content-Type: text/markdown
|
234
234
|
|
235
235
|
[](https://badge.fury.io/py/dycw-utilities)
|
@@ -1,22 +1,22 @@
|
|
1
|
-
utilities/__init__.py,sha256=
|
1
|
+
utilities/__init__.py,sha256=ayFWZ1qOKB0Lqd63WRIXSBg4vZDal1xvPPVJr5LEPEA,60
|
2
2
|
utilities/altair.py,sha256=Gpja-flOo-Db0PIPJLJsgzAlXWoKUjPU1qY-DQ829ek,9156
|
3
3
|
utilities/astor.py,sha256=xuDUkjq0-b6fhtwjhbnebzbqQZAjMSHR1IIS5uOodVg,777
|
4
|
-
utilities/asyncio.py,sha256=
|
4
|
+
utilities/asyncio.py,sha256=HGX79AKzpQbbDBW3paxAXrhWYeudcJjiO1ETU40d_-8,18463
|
5
5
|
utilities/atomicwrites.py,sha256=geFjn9Pwn-tTrtoGjDDxWli9NqbYfy3gGL6ZBctiqSo,5393
|
6
6
|
utilities/atools.py,sha256=IYMuFSFGSKyuQmqD6v5IUtDlz8PPw0Sr87Cub_gRU3M,1168
|
7
7
|
utilities/cachetools.py,sha256=C1zqOg7BYz0IfQFK8e3qaDDgEZxDpo47F15RTfJM37Q,2910
|
8
|
-
utilities/click.py,sha256=
|
8
|
+
utilities/click.py,sha256=SRVkUkWxyO_7AaYvvDl0hNCzdpneX04lf1O97i9MfPw,14311
|
9
9
|
utilities/concurrent.py,sha256=s2scTEd2AhXVTW4hpASU2qxV_DiVLALfms55cCQzCvM,2886
|
10
10
|
utilities/contextlib.py,sha256=OOIIEa5lXKGzFAnauaul40nlQnQko6Na4ryiMJcHkIg,478
|
11
11
|
utilities/contextvars.py,sha256=RsSGGrbQqqZ67rOydnM7WWIsM2lIE31UHJLejnHJPWY,505
|
12
12
|
utilities/cryptography.py,sha256=_CiK_K6c_-uQuUhsUNjNjTL-nqxAh4_1zTfS11Xe120,972
|
13
13
|
utilities/cvxpy.py,sha256=Rv1-fD-XYerosCavRF8Pohop2DBkU3AlFaGTfD8AEAA,13776
|
14
14
|
utilities/dataclasses.py,sha256=iiC1wpGXWhaocIikzwBt8bbLWyImoUlOlcDZJGejaIg,33011
|
15
|
-
utilities/datetime.py,sha256=
|
15
|
+
utilities/datetime.py,sha256=uYoaOi_C1YtNXGfTN9xlTrW62Re2b1_4Skuv14_MeYQ,38985
|
16
16
|
utilities/enum.py,sha256=HoRwVCWzsnH0vpO9ZEcAAIZLMv0Sn2vJxxA4sYMQgDs,5793
|
17
17
|
utilities/errors.py,sha256=gxsaa7eq7jbYl41Of40-ivjXqJB5gt4QAcJ0smZZMJE,829
|
18
18
|
utilities/eventkit.py,sha256=6M5Xu1SzN-juk9PqBHwy5dS-ta7T0qA6SMpDsakOJ0E,13039
|
19
|
-
utilities/fastapi.py,sha256=
|
19
|
+
utilities/fastapi.py,sha256=eiisloI6kQVCkPfDpBzlLrDZDi8yJ0VmrSPlJ2k84Mo,2334
|
20
20
|
utilities/fpdf2.py,sha256=y1NGXR5chWqLXWpewGV3hlRGMr_5yV1lVRkPBhPEgJI,1843
|
21
21
|
utilities/functions.py,sha256=jgt592voaHNtX56qX0SRvFveVCRmSIxCZmqvpLZCnY8,27305
|
22
22
|
utilities/functools.py,sha256=WrpHt7NLNWSUn9A1Q_ZIWlNaYZOEI4IFKyBG9HO3BC4,1643
|
@@ -24,7 +24,7 @@ utilities/getpass.py,sha256=DfN5UgMAtFCqS3dSfFHUfqIMZX2shXvwphOz_6J6f6A,103
|
|
24
24
|
utilities/git.py,sha256=wpt5dZ5Oi5931pN24_VLZYaQOvmR0OcQuVtgHzFUN1k,2359
|
25
25
|
utilities/hashlib.py,sha256=SVTgtguur0P4elppvzOBbLEjVM3Pea0eWB61yg2ilxo,309
|
26
26
|
utilities/http.py,sha256=WcahTcKYRtZ04WXQoWt5EGCgFPcyHD3EJdlMfxvDt-0,946
|
27
|
-
utilities/hypothesis.py,sha256=
|
27
|
+
utilities/hypothesis.py,sha256=a75izXg9aCBhhDkj_ZgK3TDzlzk38evP8TO7JbYYQvg,46264
|
28
28
|
utilities/importlib.py,sha256=ueY3R39hWrUtrVXs39utM2xDig-eyJfYn1FBVxWb3_w,368
|
29
29
|
utilities/ipython.py,sha256=V2oMYHvEKvlNBzxDXdLvKi48oUq2SclRg5xasjaXStw,763
|
30
30
|
utilities/iterables.py,sha256=prKXBdF5QfLTGC-q4567DwO8xzUng_Z-2a4wBkMqyDo,45360
|
@@ -40,11 +40,11 @@ utilities/more_itertools.py,sha256=6T0225gBFZtv47-B0JRFOKMz836Wg3Hct79ePPLGpuo,5
|
|
40
40
|
utilities/numpy.py,sha256=Xn23sA2ZbVNqwUYEgNJD3XBYH6IbCri_WkHSNhg3NkY,26122
|
41
41
|
utilities/operator.py,sha256=0M2yZJ0PODH47ogFEnkGMBe_cfxwZR02T_92LZVZvHo,3715
|
42
42
|
utilities/optuna.py,sha256=loyJGWTzljgdJaoLhP09PT8Jz6o_pwBOwehY33lHkhw,1923
|
43
|
-
utilities/orjson.py,sha256=
|
43
|
+
utilities/orjson.py,sha256=AvPFxzJdxC-3PBID3cqdiMyN8FeC7aW9QUgGwbvKuAM,36948
|
44
44
|
utilities/os.py,sha256=D_FyyT-6TtqiN9KSS7c9g1fnUtgxmyMtzAjmYLkk46A,3587
|
45
45
|
utilities/parse.py,sha256=vsZ2jf_ceSI_Kta9titixufysJaVXh0Whjz1T4awJZw,18938
|
46
46
|
utilities/pathlib.py,sha256=31WPMXdLIyXgYOMMl_HOI2wlo66MGSE-cgeelk-Lias,1410
|
47
|
-
utilities/period.py,sha256=
|
47
|
+
utilities/period.py,sha256=o4wXYEXVlFomop4-Ra4L0yRP4i99NZFjIe_fa7NdZck,11024
|
48
48
|
utilities/pickle.py,sha256=Bhvd7cZl-zQKQDFjUerqGuSKlHvnW1K2QXeU5UZibtg,657
|
49
49
|
utilities/platform.py,sha256=NU7ycTvAXAG-fdYmDXaM1m4EOml2cGiaYwaUzfzSqyU,1767
|
50
50
|
utilities/polars.py,sha256=fxfSm4xVHwKvRxu50IhYNKCKOagp12FdwsVf04ARKpk,63692
|
@@ -59,15 +59,15 @@ utilities/pytest_regressions.py,sha256=-SVT9647Dg6-JcdsiaDKXe3NdOmmrvGevLKWwGjxq
|
|
59
59
|
utilities/python_dotenv.py,sha256=iWcnpXbH7S6RoXHiLlGgyuH6udCupAcPd_gQ0eAenQ0,3190
|
60
60
|
utilities/random.py,sha256=lYdjgxB7GCfU_fwFVl5U-BIM_HV3q6_urL9byjrwDM8,4157
|
61
61
|
utilities/re.py,sha256=5J4d8VwIPFVrX2Eb8zfoxImDv7IwiN_U7mJ07wR2Wvs,3958
|
62
|
-
utilities/redis.py,sha256=
|
62
|
+
utilities/redis.py,sha256=OHw3J2dBA5QssDluKXAG1zIAK2mJJTd6uBuf_1YQuAE,26646
|
63
63
|
utilities/reprlib.py,sha256=Re9bk3n-kC__9DxQmRlevqFA86pE6TtVfWjUgpbVOv0,1849
|
64
64
|
utilities/rich.py,sha256=t50MwwVBsoOLxzmeVFSVpjno4OW6Ufum32skXbV8-Bs,1911
|
65
65
|
utilities/scipy.py,sha256=X6ROnHwiUhAmPhM0jkfEh0-Fd9iRvwiqtCQMOLmOQF8,945
|
66
66
|
utilities/sentinel.py,sha256=3jIwgpMekWgDAxPDA_hXMP2St43cPhciKN3LWiZ7kv0,1248
|
67
67
|
utilities/shelve.py,sha256=HZsMwK4tcIfg3sh0gApx4-yjQnrY4o3V3ZRimvRhoW0,738
|
68
|
-
utilities/slack_sdk.py,sha256=
|
68
|
+
utilities/slack_sdk.py,sha256=NLHmWYK6wc5bz4CGImugXceaToasNBLSqA5sd5ld2r4,3307
|
69
69
|
utilities/socket.py,sha256=K77vfREvzoVTrpYKo6MZakol0EYu2q1sWJnnZqL0So0,118
|
70
|
-
utilities/sqlalchemy.py,sha256=
|
70
|
+
utilities/sqlalchemy.py,sha256=09stMwvmI68zlk-DSy9GDk5_YxcMddLh87RPC8Bs4yY,35469
|
71
71
|
utilities/sqlalchemy_polars.py,sha256=wjJpoUo-yO9E2ujpG_06vV5r2OdvBiQ4yvV6wKCa2Tk,15605
|
72
72
|
utilities/statsmodels.py,sha256=koyiBHvpMcSiBfh99wFUfSggLNx7cuAw3rwyfAhoKpQ,3410
|
73
73
|
utilities/streamlit.py,sha256=U9PJBaKP1IdSykKhPZhIzSPTZsmLsnwbEPZWzNhJPKk,2955
|
@@ -85,10 +85,10 @@ utilities/tzlocal.py,sha256=3upDNFBvGh1l9njmLR2z2S6K6VxQSb7QizYGUbAH3JU,960
|
|
85
85
|
utilities/uuid.py,sha256=jJTFxz-CWgltqNuzmythB7iEQ-Q1mCwPevUfKthZT3c,611
|
86
86
|
utilities/version.py,sha256=QFuyEeQA6jI0ruBEcmhqG36f-etg1AEiD1drBBqhQrs,5358
|
87
87
|
utilities/warnings.py,sha256=un1LvHv70PU-LLv8RxPVmugTzDJkkGXRMZTE2-fTQHw,1771
|
88
|
-
utilities/whenever.py,sha256=
|
88
|
+
utilities/whenever.py,sha256=jS31ZAY5OMxFxLja_Yo5Fidi87Pd-GoVZ7Vi_teqVDA,16743
|
89
89
|
utilities/zipfile.py,sha256=24lQc9ATcJxHXBPc_tBDiJk48pWyRrlxO2fIsFxU0A8,699
|
90
|
-
utilities/zoneinfo.py,sha256=-
|
91
|
-
dycw_utilities-0.
|
92
|
-
dycw_utilities-0.
|
93
|
-
dycw_utilities-0.
|
94
|
-
dycw_utilities-0.
|
90
|
+
utilities/zoneinfo.py,sha256=-5j7IQ9nb7gR43rdgA7ms05im-XuqhAk9EJnQBXxCoQ,1874
|
91
|
+
dycw_utilities-0.119.0.dist-info/METADATA,sha256=XG8mqNyIqDEemm7CPwNSAdYJS_z_rsP8SqlYoT-DEAY,12943
|
92
|
+
dycw_utilities-0.119.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
93
|
+
dycw_utilities-0.119.0.dist-info/licenses/LICENSE,sha256=gppZp16M6nSVpBbUBrNL6JuYfvKwZiKgV7XoKKsHzqo,1066
|
94
|
+
dycw_utilities-0.119.0.dist-info/RECORD,,
|
utilities/__init__.py
CHANGED
utilities/asyncio.py
CHANGED
@@ -3,7 +3,6 @@ from __future__ import annotations
|
|
3
3
|
import datetime as dt
|
4
4
|
from abc import ABC, abstractmethod
|
5
5
|
from asyncio import (
|
6
|
-
CancelledError,
|
7
6
|
Event,
|
8
7
|
PriorityQueue,
|
9
8
|
Queue,
|
@@ -13,17 +12,11 @@ from asyncio import (
|
|
13
12
|
Task,
|
14
13
|
TaskGroup,
|
15
14
|
create_subprocess_shell,
|
16
|
-
create_task,
|
17
15
|
sleep,
|
18
16
|
timeout,
|
19
17
|
)
|
20
18
|
from collections.abc import Callable, Hashable, Iterable, Iterator, Mapping
|
21
|
-
from contextlib import
|
22
|
-
AsyncExitStack,
|
23
|
-
_AsyncGeneratorContextManager,
|
24
|
-
asynccontextmanager,
|
25
|
-
suppress,
|
26
|
-
)
|
19
|
+
from contextlib import _AsyncGeneratorContextManager, asynccontextmanager
|
27
20
|
from dataclasses import dataclass, field
|
28
21
|
from io import StringIO
|
29
22
|
from logging import getLogger
|
@@ -35,7 +28,6 @@ from typing import (
|
|
35
28
|
Generic,
|
36
29
|
Literal,
|
37
30
|
NoReturn,
|
38
|
-
Self,
|
39
31
|
TextIO,
|
40
32
|
TypeVar,
|
41
33
|
assert_never,
|
@@ -44,7 +36,6 @@ from typing import (
|
|
44
36
|
)
|
45
37
|
|
46
38
|
from utilities.datetime import (
|
47
|
-
MILLISECOND,
|
48
39
|
MINUTE,
|
49
40
|
SECOND,
|
50
41
|
datetime_duration_to_float,
|
@@ -52,7 +43,7 @@ from utilities.datetime import (
|
|
52
43
|
get_now,
|
53
44
|
round_datetime,
|
54
45
|
)
|
55
|
-
from utilities.errors import
|
46
|
+
from utilities.errors import repr_error
|
56
47
|
from utilities.functions import ensure_int, ensure_not_none, get_class_name
|
57
48
|
from utilities.reprlib import get_repr
|
58
49
|
from utilities.sentinel import Sentinel, sentinel
|
@@ -69,7 +60,6 @@ if TYPE_CHECKING:
|
|
69
60
|
from asyncio.subprocess import Process
|
70
61
|
from collections.abc import AsyncIterator, Sequence
|
71
62
|
from contextvars import Context
|
72
|
-
from types import TracebackType
|
73
63
|
|
74
64
|
from utilities.types import Duration
|
75
65
|
|
@@ -80,120 +70,6 @@ _T = TypeVar("_T")
|
|
80
70
|
##
|
81
71
|
|
82
72
|
|
83
|
-
@dataclass(kw_only=True)
|
84
|
-
class AsyncService(ABC):
|
85
|
-
"""A long-running, asynchronous service."""
|
86
|
-
|
87
|
-
duration: Duration | None = None
|
88
|
-
_await_upon_aenter: bool = field(default=True, init=False, repr=False)
|
89
|
-
_event: Event = field(default_factory=Event, init=False, repr=False)
|
90
|
-
_stack: AsyncExitStack = field(
|
91
|
-
default_factory=AsyncExitStack, init=False, repr=False
|
92
|
-
)
|
93
|
-
_state: bool = field(default=False, init=False, repr=False)
|
94
|
-
_task: Task[None] | None = field(default=None, init=False, repr=False)
|
95
|
-
_depth: int = field(default=0, init=False, repr=False)
|
96
|
-
|
97
|
-
async def __aenter__(self) -> Self:
|
98
|
-
"""Context manager entry."""
|
99
|
-
if (self._task is None) and (self._depth == 0):
|
100
|
-
_ = await self._stack.__aenter__()
|
101
|
-
self._task = create_task(self._start_runner())
|
102
|
-
if self._await_upon_aenter:
|
103
|
-
with suppress(CancelledError):
|
104
|
-
await self._task
|
105
|
-
elif (self._task is not None) and (self._depth >= 1):
|
106
|
-
...
|
107
|
-
else:
|
108
|
-
raise ImpossibleCaseError( # pragma: no cover
|
109
|
-
case=[f"{self._task=}", f"{self._depth=}"]
|
110
|
-
)
|
111
|
-
self._depth += 1
|
112
|
-
return self
|
113
|
-
|
114
|
-
async def __aexit__(
|
115
|
-
self,
|
116
|
-
exc_type: type[BaseException] | None = None,
|
117
|
-
exc_value: BaseException | None = None,
|
118
|
-
traceback: TracebackType | None = None,
|
119
|
-
) -> None:
|
120
|
-
"""Context manager exit."""
|
121
|
-
_ = (exc_type, exc_value, traceback)
|
122
|
-
if (self._task is None) or (self._depth == 0):
|
123
|
-
raise ImpossibleCaseError( # pragma: no cover
|
124
|
-
case=[f"{self._task=}", f"{self._depth=}"]
|
125
|
-
)
|
126
|
-
self._state = False
|
127
|
-
self._depth -= 1
|
128
|
-
if self._depth == 0:
|
129
|
-
_ = await self._stack.__aexit__(exc_type, exc_value, traceback)
|
130
|
-
await self.stop()
|
131
|
-
with suppress(CancelledError):
|
132
|
-
await self._task
|
133
|
-
self._task = None
|
134
|
-
|
135
|
-
@abstractmethod
|
136
|
-
async def _start(self) -> None:
|
137
|
-
"""Start the service."""
|
138
|
-
|
139
|
-
async def _start_runner(self) -> None:
|
140
|
-
"""Coroutine to start the service."""
|
141
|
-
if self.duration is None:
|
142
|
-
_ = await self._start()
|
143
|
-
_ = await self._event.wait()
|
144
|
-
else:
|
145
|
-
try:
|
146
|
-
async with timeout_dur(duration=self.duration):
|
147
|
-
_ = await self._start()
|
148
|
-
except TimeoutError:
|
149
|
-
await self.stop()
|
150
|
-
|
151
|
-
async def stop(self) -> None:
|
152
|
-
"""Stop the service."""
|
153
|
-
if self._task is None:
|
154
|
-
raise ImpossibleCaseError(case=[f"{self._task=}"]) # pragma: no cover
|
155
|
-
with suppress(CancelledError):
|
156
|
-
_ = self._task.cancel()
|
157
|
-
|
158
|
-
|
159
|
-
##
|
160
|
-
|
161
|
-
|
162
|
-
@dataclass(kw_only=True)
|
163
|
-
class AsyncLoopingService(AsyncService):
|
164
|
-
"""A long-running, asynchronous service which loops a core function."""
|
165
|
-
|
166
|
-
sleep: Duration = MILLISECOND
|
167
|
-
_await_upon_aenter: bool = field(default=True, init=False, repr=False)
|
168
|
-
|
169
|
-
@abstractmethod
|
170
|
-
async def _run(self) -> None:
|
171
|
-
"""Run the core function once."""
|
172
|
-
raise NotImplementedError # pragma: no cover
|
173
|
-
|
174
|
-
async def _run_failure(self, error: Exception, /) -> None:
|
175
|
-
"""Process the failure."""
|
176
|
-
raise error
|
177
|
-
|
178
|
-
@override
|
179
|
-
async def _start(self) -> None:
|
180
|
-
"""Start the service, assuming no task is present."""
|
181
|
-
while True:
|
182
|
-
try:
|
183
|
-
await self._run()
|
184
|
-
except CancelledError:
|
185
|
-
await self.stop()
|
186
|
-
break
|
187
|
-
except Exception as error: # noqa: BLE001
|
188
|
-
await self._run_failure(error)
|
189
|
-
await sleep_dur(duration=self.sleep)
|
190
|
-
else:
|
191
|
-
await sleep_dur(duration=self.sleep)
|
192
|
-
|
193
|
-
|
194
|
-
##
|
195
|
-
|
196
|
-
|
197
73
|
class EnhancedTaskGroup(TaskGroup):
|
198
74
|
"""Task group with enhanced features."""
|
199
75
|
|
@@ -245,100 +121,6 @@ class EnhancedTaskGroup(TaskGroup):
|
|
245
121
|
##
|
246
122
|
|
247
123
|
|
248
|
-
@dataclass(kw_only=True)
|
249
|
-
class QueueProcessor(AsyncService, Generic[_T]):
|
250
|
-
"""Process a set of items in a queue."""
|
251
|
-
|
252
|
-
queue_type: type[Queue[_T]] = field(default=Queue, repr=False)
|
253
|
-
queue_max_size: int | None = field(default=None, repr=False)
|
254
|
-
sleep: Duration = MILLISECOND
|
255
|
-
_await_upon_aenter: bool = field(default=False, init=False, repr=False)
|
256
|
-
_queue: Queue[_T] = field(init=False, repr=False)
|
257
|
-
|
258
|
-
def __post_init__(self) -> None:
|
259
|
-
self._queue = self.queue_type(
|
260
|
-
maxsize=0 if self.queue_max_size is None else self.queue_max_size
|
261
|
-
)
|
262
|
-
|
263
|
-
def __len__(self) -> int:
|
264
|
-
return self._queue.qsize()
|
265
|
-
|
266
|
-
def empty(self) -> bool:
|
267
|
-
"""Check if the queue is empty."""
|
268
|
-
return self._queue.empty()
|
269
|
-
|
270
|
-
def enqueue(self, *items: _T) -> None:
|
271
|
-
"""Enqueue a set items."""
|
272
|
-
for item in items:
|
273
|
-
self._queue.put_nowait(item)
|
274
|
-
|
275
|
-
async def run_until_empty(self) -> None:
|
276
|
-
"""Run the processor until the queue is empty."""
|
277
|
-
while not self.empty():
|
278
|
-
await self._run()
|
279
|
-
await sleep_dur(duration=self.sleep)
|
280
|
-
|
281
|
-
def _get_items_nowait(self, *, max_size: int | None = None) -> Sequence[_T]:
|
282
|
-
"""Get items from the queue; no waiting."""
|
283
|
-
return get_items_nowait(self._queue, max_size=max_size)
|
284
|
-
|
285
|
-
@abstractmethod
|
286
|
-
async def _process_item(self, item: _T, /) -> None:
|
287
|
-
"""Process the first item."""
|
288
|
-
raise NotImplementedError(item) # pragma: no cover
|
289
|
-
|
290
|
-
async def _process_item_failure(self, item: _T, error: Exception, /) -> None:
|
291
|
-
"""Process the failure."""
|
292
|
-
_ = item
|
293
|
-
raise error
|
294
|
-
|
295
|
-
async def _run(self) -> None:
|
296
|
-
"""Run the processer."""
|
297
|
-
try:
|
298
|
-
(item,) = self._get_items_nowait(max_size=1)
|
299
|
-
except ValueError:
|
300
|
-
raise QueueEmpty from None
|
301
|
-
try:
|
302
|
-
await self._process_item(item)
|
303
|
-
except Exception as error: # noqa: BLE001
|
304
|
-
await self._process_item_failure(item, error)
|
305
|
-
|
306
|
-
@override
|
307
|
-
async def _start(self) -> None:
|
308
|
-
"""Start the processor."""
|
309
|
-
while True:
|
310
|
-
try:
|
311
|
-
await self._run()
|
312
|
-
except QueueEmpty:
|
313
|
-
await sleep_dur(duration=self.sleep)
|
314
|
-
except CancelledError:
|
315
|
-
await self.stop()
|
316
|
-
break
|
317
|
-
else:
|
318
|
-
await sleep_dur(duration=self.sleep)
|
319
|
-
|
320
|
-
@override
|
321
|
-
async def stop(self) -> None:
|
322
|
-
"""Stop the processor."""
|
323
|
-
await self.run_until_empty()
|
324
|
-
await super().stop()
|
325
|
-
|
326
|
-
|
327
|
-
@dataclass(kw_only=True)
|
328
|
-
class ExceptionProcessor(QueueProcessor[Exception | type[Exception]]):
|
329
|
-
"""Raise an exception in a queue."""
|
330
|
-
|
331
|
-
queue_max_size: int | None = field(default=1, repr=False)
|
332
|
-
|
333
|
-
@override
|
334
|
-
async def _process_item(self, item: Exception | type[Exception], /) -> None:
|
335
|
-
"""Run the processor on the first item."""
|
336
|
-
raise item
|
337
|
-
|
338
|
-
|
339
|
-
##
|
340
|
-
|
341
|
-
|
342
124
|
type _DurationOrEvery = Duration | tuple[Literal["every"], Duration]
|
343
125
|
|
344
126
|
|
@@ -807,15 +589,11 @@ async def timeout_dur(
|
|
807
589
|
|
808
590
|
|
809
591
|
__all__ = [
|
810
|
-
"AsyncLoopingService",
|
811
|
-
"AsyncService",
|
812
592
|
"EnhancedTaskGroup",
|
813
|
-
"ExceptionProcessor",
|
814
593
|
"InfiniteLooper",
|
815
594
|
"InfiniteLooperError",
|
816
595
|
"InfiniteQueueLooper",
|
817
596
|
"InfiniteQueueLooperError",
|
818
|
-
"QueueProcessor",
|
819
597
|
"StreamCommandOutput",
|
820
598
|
"UniquePriorityQueue",
|
821
599
|
"UniqueQueue",
|
utilities/click.py
CHANGED
@@ -131,10 +131,10 @@ class Enum(ParamType, Generic[TEnum]):
|
|
131
131
|
return _make_metavar(param, desc)
|
132
132
|
|
133
133
|
|
134
|
-
class
|
135
|
-
"""A
|
134
|
+
class Month(ParamType):
|
135
|
+
"""A month-valued parameter."""
|
136
136
|
|
137
|
-
name = "
|
137
|
+
name = "month"
|
138
138
|
|
139
139
|
@override
|
140
140
|
def __repr__(self) -> str:
|
@@ -142,21 +142,19 @@ class LocalDateTime(ParamType):
|
|
142
142
|
|
143
143
|
@override
|
144
144
|
def convert(
|
145
|
-
self, value:
|
146
|
-
) ->
|
147
|
-
"""Convert a value into the `
|
148
|
-
from utilities.whenever import EnsureLocalDateTimeError, ensure_local_datetime
|
149
|
-
|
145
|
+
self, value: MonthLike, param: Parameter | None, ctx: Context | None
|
146
|
+
) -> utilities.datetime.Month:
|
147
|
+
"""Convert a value into the `Month` type."""
|
150
148
|
try:
|
151
|
-
return
|
152
|
-
except
|
149
|
+
return ensure_month(value)
|
150
|
+
except EnsureMonthError as error:
|
153
151
|
self.fail(str(error), param, ctx)
|
154
152
|
|
155
153
|
|
156
|
-
class
|
157
|
-
"""A
|
154
|
+
class PlainDateTime(ParamType):
|
155
|
+
"""A local-datetime-valued parameter."""
|
158
156
|
|
159
|
-
name = "
|
157
|
+
name = "plain datetime"
|
160
158
|
|
161
159
|
@override
|
162
160
|
def __repr__(self) -> str:
|
@@ -164,12 +162,14 @@ class Month(ParamType):
|
|
164
162
|
|
165
163
|
@override
|
166
164
|
def convert(
|
167
|
-
self, value:
|
168
|
-
) ->
|
169
|
-
"""Convert a value into the `
|
165
|
+
self, value: DateTimeLike, param: Parameter | None, ctx: Context | None
|
166
|
+
) -> dt.date:
|
167
|
+
"""Convert a value into the `LocalDateTime` type."""
|
168
|
+
from utilities.whenever import EnsurePlainDateTimeError, ensure_plain_datetime
|
169
|
+
|
170
170
|
try:
|
171
|
-
return
|
172
|
-
except
|
171
|
+
return ensure_plain_datetime(value)
|
172
|
+
except EnsurePlainDateTimeError as error:
|
173
173
|
self.fail(str(error), param, ctx)
|
174
174
|
|
175
175
|
|
@@ -506,8 +506,8 @@ __all__ = [
|
|
506
506
|
"ListParameter",
|
507
507
|
"ListStrs",
|
508
508
|
"ListUUIDs",
|
509
|
-
"LocalDateTime",
|
510
509
|
"Month",
|
510
|
+
"PlainDateTime",
|
511
511
|
"Time",
|
512
512
|
"Timedelta",
|
513
513
|
"ZonedDateTime",
|