reykit 1.0.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.
- reykit/__init__.py +41 -0
- reykit/rall.py +33 -0
- reykit/rcomm.py +431 -0
- reykit/rdata.py +395 -0
- reykit/rdll/__init__.py +17 -0
- reykit/rdll/rdll_inject.py +41 -0
- reykit/rdll/rdll_inject_core.py +202 -0
- reykit/remail.py +276 -0
- reykit/rexception.py +339 -0
- reykit/rimage.py +261 -0
- reykit/rlog.py +1061 -0
- reykit/rmonkey.py +341 -0
- reykit/rmultitask.py +871 -0
- reykit/rnumber.py +161 -0
- reykit/ros.py +1917 -0
- reykit/rrandom.py +351 -0
- reykit/rregex.py +293 -0
- reykit/rschedule.py +272 -0
- reykit/rstdout.py +356 -0
- reykit/rsystem.py +1180 -0
- reykit/rtable.py +511 -0
- reykit/rtext.py +458 -0
- reykit/rtime.py +678 -0
- reykit/rtype.py +106 -0
- reykit/rwrap.py +613 -0
- reykit/rzip.py +137 -0
- reykit-1.0.0.dist-info/METADATA +29 -0
- reykit-1.0.0.dist-info/RECORD +30 -0
- reykit-1.0.0.dist-info/WHEEL +5 -0
- reykit-1.0.0.dist-info/top_level.txt +1 -0
reykit/rmonkey.py
ADDED
@@ -0,0 +1,341 @@
|
|
1
|
+
# !/usr/bin/env python
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
"""
|
5
|
+
@Time : 2023-03-19 19:36:47
|
6
|
+
@Author : Rey
|
7
|
+
@Contact : reyxbo@163.com
|
8
|
+
@Explain : Monkey patch methods.
|
9
|
+
"""
|
10
|
+
|
11
|
+
|
12
|
+
from __future__ import annotations
|
13
|
+
|
14
|
+
|
15
|
+
__all__ = (
|
16
|
+
'monkey_patch_sqlalchemy_result_more_fetch',
|
17
|
+
'monkey_patch_sqlalchemy_row_index_field',
|
18
|
+
'monkey_patch_pprint_modify_width_judgment'
|
19
|
+
)
|
20
|
+
|
21
|
+
|
22
|
+
def monkey_patch_sqlalchemy_result_more_fetch():
|
23
|
+
"""
|
24
|
+
Monkey patch of package `sqlalchemy`, add more fetch methods to `CursorResult` object.
|
25
|
+
|
26
|
+
Returns
|
27
|
+
-------
|
28
|
+
Modified type.
|
29
|
+
"""
|
30
|
+
|
31
|
+
|
32
|
+
from typing import Optional
|
33
|
+
from sqlalchemy.engine.cursor import CursorResult
|
34
|
+
from pandas import DataFrame, NA, concat
|
35
|
+
|
36
|
+
from .rstdout import echo
|
37
|
+
from .rtable import (
|
38
|
+
to_table,
|
39
|
+
to_dict,
|
40
|
+
to_list,
|
41
|
+
to_df,
|
42
|
+
to_json,
|
43
|
+
to_text,
|
44
|
+
to_sql,
|
45
|
+
to_html,
|
46
|
+
to_csv,
|
47
|
+
to_excel
|
48
|
+
)
|
49
|
+
from .rtime import time_to
|
50
|
+
|
51
|
+
|
52
|
+
# Fetch result as table in 'list[dict]' format.
|
53
|
+
CursorResult.fetch_table = to_table
|
54
|
+
|
55
|
+
# Fetch result as dictionary.
|
56
|
+
CursorResult.fetch_dict = to_dict
|
57
|
+
|
58
|
+
# Fetch result as list.
|
59
|
+
CursorResult.fetch_list = to_list
|
60
|
+
|
61
|
+
# Fetch result as DataFrame object.
|
62
|
+
CursorResult.fetch_df = to_df
|
63
|
+
|
64
|
+
# Fetch result as JSON string.
|
65
|
+
CursorResult.fetch_json = to_json
|
66
|
+
|
67
|
+
# Fetch result as text.
|
68
|
+
CursorResult.fetch_text = to_text
|
69
|
+
|
70
|
+
# Fetch result as SQL string.
|
71
|
+
CursorResult.fetch_sql = to_sql
|
72
|
+
|
73
|
+
# Fetch result as HTML string.
|
74
|
+
CursorResult.fetch_html = to_html
|
75
|
+
|
76
|
+
# Fetch result as save csv format file.
|
77
|
+
CursorResult.fetch_csv = to_csv
|
78
|
+
|
79
|
+
# Fetch result as save excel file.
|
80
|
+
CursorResult.fetch_excel = to_excel
|
81
|
+
|
82
|
+
|
83
|
+
# Print result.
|
84
|
+
def method_show(self: RResult, limit: Optional[int] = None) -> None:
|
85
|
+
"""
|
86
|
+
Print result.
|
87
|
+
|
88
|
+
Parameters
|
89
|
+
----------
|
90
|
+
limit : Limit row.
|
91
|
+
- `>0`: Limit first few row.
|
92
|
+
- `<0`: Limit last few row.
|
93
|
+
"""
|
94
|
+
|
95
|
+
# Handle parameter.
|
96
|
+
if limit is None:
|
97
|
+
limit = 0
|
98
|
+
|
99
|
+
# Convert.
|
100
|
+
df: DataFrame = self.fetch_df()
|
101
|
+
df = df.applymap(time_to, raising=False)
|
102
|
+
df = df.astype(str)
|
103
|
+
df.replace(['NaT', '<NA>'], 'None', inplace=True)
|
104
|
+
row_len, column_len = df.shape
|
105
|
+
|
106
|
+
# Create omit row.
|
107
|
+
omit_row = (('...',) * column_len,)
|
108
|
+
omit_row = DataFrame(
|
109
|
+
omit_row,
|
110
|
+
columns=df.columns
|
111
|
+
)
|
112
|
+
|
113
|
+
# Limit.
|
114
|
+
if (
|
115
|
+
limit > 0
|
116
|
+
and limit < row_len
|
117
|
+
):
|
118
|
+
df = df.head(limit)
|
119
|
+
omit_row.index = (row_len - 1,)
|
120
|
+
df = concat((df, omit_row))
|
121
|
+
elif (
|
122
|
+
limit < 0
|
123
|
+
and -limit < row_len
|
124
|
+
):
|
125
|
+
df = df.tail(-limit)
|
126
|
+
omit_row.index = (0,)
|
127
|
+
df = concat((omit_row, df))
|
128
|
+
|
129
|
+
# Print.
|
130
|
+
echo(df, title='Result')
|
131
|
+
|
132
|
+
|
133
|
+
CursorResult.show = method_show
|
134
|
+
|
135
|
+
|
136
|
+
# Whether is exist.
|
137
|
+
@property
|
138
|
+
def method_exist(self: RResult) -> bool:
|
139
|
+
"""
|
140
|
+
Judge whether is exist row.
|
141
|
+
|
142
|
+
Returns
|
143
|
+
-------
|
144
|
+
Judge result.
|
145
|
+
"""
|
146
|
+
|
147
|
+
# Judge.
|
148
|
+
judge = self.rowcount != 0
|
149
|
+
|
150
|
+
return judge
|
151
|
+
|
152
|
+
|
153
|
+
CursorResult.exist = method_exist
|
154
|
+
|
155
|
+
|
156
|
+
# Whether is empty.
|
157
|
+
@property
|
158
|
+
def method_empty(self: RResult) -> bool:
|
159
|
+
"""
|
160
|
+
Judge whether is empty row.
|
161
|
+
|
162
|
+
Returns
|
163
|
+
-------
|
164
|
+
Judge result.
|
165
|
+
"""
|
166
|
+
|
167
|
+
# Judge.
|
168
|
+
judge = self.rowcount == 0
|
169
|
+
|
170
|
+
return judge
|
171
|
+
|
172
|
+
|
173
|
+
CursorResult.empty = method_empty
|
174
|
+
|
175
|
+
|
176
|
+
# Update annotations.
|
177
|
+
class RResult(CursorResult):
|
178
|
+
"""
|
179
|
+
Update based on `CursorResult` object, for annotation return value.
|
180
|
+
"""
|
181
|
+
|
182
|
+
# Inherit document.
|
183
|
+
__doc__ = CursorResult.__doc__
|
184
|
+
|
185
|
+
# Add method.
|
186
|
+
fetch_table = to_table
|
187
|
+
fetch_dict = to_dict
|
188
|
+
fetch_list = to_list
|
189
|
+
fetch_df = to_df
|
190
|
+
fetch_json = to_json
|
191
|
+
fetch_text = to_text
|
192
|
+
fetch_sql = to_sql
|
193
|
+
fetch_html = to_html
|
194
|
+
fetch_csv = to_csv
|
195
|
+
fetch_excel = to_excel
|
196
|
+
show = method_show
|
197
|
+
exist = method_exist
|
198
|
+
empty = method_empty
|
199
|
+
|
200
|
+
|
201
|
+
return RResult
|
202
|
+
|
203
|
+
|
204
|
+
def monkey_patch_sqlalchemy_row_index_field():
|
205
|
+
"""
|
206
|
+
Monkey patch of package `sqlalchemy`, add index by field method to `Row` object.
|
207
|
+
"""
|
208
|
+
|
209
|
+
|
210
|
+
from typing import Any, Union, overload
|
211
|
+
from sqlalchemy.engine.row import Row
|
212
|
+
|
213
|
+
|
214
|
+
# Define.
|
215
|
+
@overload
|
216
|
+
def __getitem__(self, index: Union[str, int]) -> Any: ...
|
217
|
+
|
218
|
+
@overload
|
219
|
+
def __getitem__(self, index: slice) -> tuple: ...
|
220
|
+
|
221
|
+
def __getitem__(self, index: Union[str, int, slice]) -> Union[Any, tuple]:
|
222
|
+
"""
|
223
|
+
Index row value.
|
224
|
+
|
225
|
+
Parameters
|
226
|
+
----------
|
227
|
+
index : Field name or subscript or slice.
|
228
|
+
|
229
|
+
Returns
|
230
|
+
-------
|
231
|
+
Index result.
|
232
|
+
"""
|
233
|
+
|
234
|
+
# Index.
|
235
|
+
if index.__class__ == str:
|
236
|
+
value = self._mapping[index]
|
237
|
+
else:
|
238
|
+
value = self._data[index]
|
239
|
+
|
240
|
+
return value
|
241
|
+
|
242
|
+
|
243
|
+
# Add.
|
244
|
+
Row.__getitem__ = __getitem__
|
245
|
+
|
246
|
+
|
247
|
+
def monkey_patch_pprint_modify_width_judgment() -> None:
|
248
|
+
"""
|
249
|
+
Monkey patch of package `pprint`, modify the chinese width judgment.
|
250
|
+
"""
|
251
|
+
|
252
|
+
|
253
|
+
from pprint import PrettyPrinter, _recursion
|
254
|
+
|
255
|
+
|
256
|
+
# New method.
|
257
|
+
def _format(_self, obj, stream, indent, allowance, context, level):
|
258
|
+
|
259
|
+
|
260
|
+
from .rtext import get_width
|
261
|
+
|
262
|
+
|
263
|
+
objid = id(obj)
|
264
|
+
if objid in context:
|
265
|
+
stream.write(_recursion(obj))
|
266
|
+
_self._recursive = True
|
267
|
+
_self._readable = False
|
268
|
+
return
|
269
|
+
rep = _self._repr(obj, context, level)
|
270
|
+
max_width = _self._width - indent - allowance
|
271
|
+
width = get_width(rep)
|
272
|
+
if width > max_width:
|
273
|
+
p = _self._dispatch.get(type(obj).__repr__, None)
|
274
|
+
if p is not None:
|
275
|
+
context[objid] = 1
|
276
|
+
p(_self, obj, stream, indent, allowance, context, level + 1)
|
277
|
+
del context[objid]
|
278
|
+
return
|
279
|
+
elif isinstance(obj, dict):
|
280
|
+
context[objid] = 1
|
281
|
+
_self._pprint_dict(obj, stream, indent, allowance,
|
282
|
+
context, level + 1)
|
283
|
+
del context[objid]
|
284
|
+
return
|
285
|
+
stream.write(rep)
|
286
|
+
|
287
|
+
|
288
|
+
# Modify.
|
289
|
+
PrettyPrinter._format = _format
|
290
|
+
|
291
|
+
|
292
|
+
def monkey_path_pil_image_get_bytes():
|
293
|
+
"""
|
294
|
+
Monkey patch of package `PIL`, add get bytes method to `Image` object.
|
295
|
+
|
296
|
+
Returns
|
297
|
+
-------
|
298
|
+
Image object.
|
299
|
+
"""
|
300
|
+
|
301
|
+
|
302
|
+
from PIL.Image import Image
|
303
|
+
from io import BytesIO
|
304
|
+
|
305
|
+
|
306
|
+
# Define.
|
307
|
+
def method_get_bytes(self: Image) -> bytes:
|
308
|
+
"""
|
309
|
+
Get image bytes data.
|
310
|
+
|
311
|
+
Returns
|
312
|
+
-------
|
313
|
+
Image bytes data.
|
314
|
+
"""
|
315
|
+
|
316
|
+
# Extract.
|
317
|
+
bytes_io = BytesIO()
|
318
|
+
self.save(bytes_io, 'JPEG')
|
319
|
+
image_bytes = bytes_io.getvalue()
|
320
|
+
|
321
|
+
return image_bytes
|
322
|
+
|
323
|
+
|
324
|
+
# Add.
|
325
|
+
Image.get_bytes = method_get_bytes
|
326
|
+
|
327
|
+
|
328
|
+
# Update annotations.
|
329
|
+
class RImage(Image):
|
330
|
+
"""
|
331
|
+
Update based on `Image` object, for annotation return value.
|
332
|
+
"""
|
333
|
+
|
334
|
+
# Inherit document.
|
335
|
+
__doc__ = Image.__doc__
|
336
|
+
|
337
|
+
# Add method.
|
338
|
+
get_bytes = method_get_bytes
|
339
|
+
|
340
|
+
|
341
|
+
return RImage
|