reykit 1.1.3__tar.gz

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.
@@ -0,0 +1,2 @@
1
+ __pycache__/
2
+ /dist
reykit-1.1.3/LICENSE ADDED
@@ -0,0 +1,7 @@
1
+ Copyright 2025 ReyXBo
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
reykit-1.1.3/PKG-INFO ADDED
@@ -0,0 +1,44 @@
1
+ Metadata-Version: 2.4
2
+ Name: reykit
3
+ Version: 1.1.3
4
+ Summary: Rey's kit method set.
5
+ Project-URL: homepage, https://github.com/reyxbo/reykit/
6
+ Author-email: Rey <reyxbo@163.com>
7
+ License: Copyright 2025 ReyXBo
8
+
9
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
14
+ License-File: LICENSE
15
+ Keywords: kit,rey,reyxbo,tool,tools
16
+ Requires-Python: >=3.12
17
+ Requires-Dist: aiohttp
18
+ Requires-Dist: apscheduler
19
+ Requires-Dist: captcha
20
+ Requires-Dist: concurrent-log-handler
21
+ Requires-Dist: filetype
22
+ Requires-Dist: pandas
23
+ Requires-Dist: pdfplumber
24
+ Requires-Dist: pillow
25
+ Requires-Dist: psutil
26
+ Requires-Dist: pymem
27
+ Requires-Dist: python-docx
28
+ Requires-Dist: pyzbar
29
+ Requires-Dist: qrcode
30
+ Requires-Dist: requests
31
+ Requires-Dist: tqdm
32
+ Requires-Dist: urwid
33
+ Requires-Dist: varname
34
+ Description-Content-Type: text/markdown
35
+
36
+ # reykit
37
+
38
+ > Rey's kit method set.
39
+
40
+ ## Install
41
+
42
+ ```
43
+ pip install reykit
44
+ ```
reykit-1.1.3/README.md ADDED
@@ -0,0 +1,9 @@
1
+ # reykit
2
+
3
+ > Rey's kit method set.
4
+
5
+ ## Install
6
+
7
+ ```
8
+ pip install reykit
9
+ ```
@@ -0,0 +1,37 @@
1
+ [project]
2
+ name = "reykit"
3
+ version = "1.1.3"
4
+ description = "Rey's kit method set."
5
+ readme = "README.md"
6
+ requires-python = ">=3.12"
7
+ license = {file = "LICENSE"}
8
+ keywords = ["rey", "reyxbo", "kit", "tool", "tools"]
9
+ authors = [
10
+ {name = "Rey", email = "reyxbo@163.com"}
11
+ ]
12
+ dependencies = [
13
+ "aiohttp",
14
+ "apscheduler",
15
+ "captcha",
16
+ "concurrent-log-handler",
17
+ "filetype",
18
+ "pandas",
19
+ "pyzbar",
20
+ "pdfplumber",
21
+ "psutil",
22
+ "pymem",
23
+ "python-docx",
24
+ "qrcode",
25
+ "requests",
26
+ "tqdm",
27
+ "urwid",
28
+ "varname",
29
+ "Pillow"
30
+ ]
31
+
32
+ [project.urls]
33
+ homepage = "https://github.com/reyxbo/reykit/"
34
+
35
+ [build-system]
36
+ requires = ["hatchling"]
37
+ build-backend = "hatchling.build"
@@ -0,0 +1,35 @@
1
+ # !/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+
4
+ """
5
+ @Time : 2022-12-05 14:09:21
6
+ @Author : Rey
7
+ @Contact : reyxbo@163.com
8
+ @Explain : Rey's kit method set.
9
+
10
+ Modules
11
+ -------
12
+ rall : All methods.
13
+ rcomm : Network communication methods.
14
+ rdata : Data methods.
15
+ rdll : DLL file methods.
16
+ remail : E-mail methods.
17
+ rexception : Exception methods.
18
+ rimage : Image methods.
19
+ rlog : Log methods.
20
+ rmonkey : Monkey patch methods.
21
+ rmultitask : Multi task methods.
22
+ rnumber : Number methods.
23
+ ros: Operation system methods.
24
+ rrandom : Random methods.
25
+ rregex : Regular expression methods.
26
+ rschedule : Schedule methods.
27
+ rstdout : Standard output methods.
28
+ rsystem : Interpreter system methods.
29
+ rtable : Table methods.
30
+ rtext : Text methods.
31
+ rtime : Time methods.
32
+ rtype : Type methods.
33
+ rwrap : Decorators.
34
+ rzip : File compress methods.
35
+ """
@@ -0,0 +1,33 @@
1
+ # !/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+
4
+ """
5
+ @Time : 2022-12-08 13:11:09
6
+ @Author : Rey
7
+ @Contact : reyxbo@163.com
8
+ @Explain : All methods.
9
+ """
10
+
11
+
12
+ from .rcomm import *
13
+ from .rdata import *
14
+ from .rdll import *
15
+ from .remail import *
16
+ from .rexception import *
17
+ from .rimage import *
18
+ from .rlog import *
19
+ from .rmonkey import *
20
+ from .rmultitask import *
21
+ from .rnumber import *
22
+ from .ros import *
23
+ from .rrandom import *
24
+ from .rregex import *
25
+ from .rschedule import *
26
+ from .rstdout import *
27
+ from .rsystem import *
28
+ from .rtable import *
29
+ from .rtext import *
30
+ from .rtime import *
31
+ from .rtype import *
32
+ from .rwrap import *
33
+ from .rzip import *
@@ -0,0 +1,431 @@
1
+ # !/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+
4
+ """
5
+ @Time : 2022-12-08 11:07:25
6
+ @Author : Rey
7
+ @Contact : reyxbo@163.com
8
+ @Explain : Network communication methods.
9
+ """
10
+
11
+
12
+ from typing import Any, Literal
13
+ from collections.abc import Callable, Iterable
14
+ from warnings import filterwarnings
15
+ from os.path import abspath as os_abspath, isfile as os_isfile
16
+ from socket import socket as Socket
17
+ from urllib.parse import urlsplit as urllib_urlsplit, quote as urllib_quote, unquote as urllib_unquote
18
+ from requests.api import request as requests_request
19
+ from requests.models import Response
20
+ from mimetypes import guess_type
21
+ from filetype import guess as filetype_guess
22
+
23
+ from .rexception import throw, check_response_code
24
+ from .ros import RFile
25
+ from .rregex import search
26
+
27
+
28
+ __all__ = (
29
+ 'join_url',
30
+ 'split_url',
31
+ 'join_cookie',
32
+ 'split_cookie',
33
+ 'get_content_type',
34
+ 'request',
35
+ 'download',
36
+ 'get_file_stream_time',
37
+ 'listen_socket'
38
+ )
39
+
40
+
41
+ def join_url(url: str, params: dict) -> str:
42
+ """
43
+ Join URL and parameters.
44
+
45
+ Parameters
46
+ ----------
47
+ url : URL.
48
+ params : Parameters of URL.
49
+
50
+ Returns
51
+ -------
52
+ Joined URL.
53
+ """
54
+
55
+ # Join parameter.
56
+ params_str = '&'.join(
57
+ [
58
+ f'{key}={urllib_quote(value)}'
59
+ for key, value in params.items()
60
+ ]
61
+ )
62
+
63
+ # Join URL.
64
+ if '?' not in url:
65
+ url += '?'
66
+ elif url[-1] != '?':
67
+ url += '&'
68
+ url += params_str
69
+
70
+ return url
71
+
72
+
73
+ def split_url(url: str) -> tuple[str, dict[str, str]]:
74
+ """
75
+ Split URL and parameters.
76
+
77
+ Parameters
78
+ ----------
79
+ url : URL.
80
+
81
+ Returns
82
+ -------
83
+ Split URL and parameters.
84
+ """
85
+
86
+ # Split URL.
87
+ split_result = urllib_urlsplit(url)
88
+ params_str = split_result.query
89
+ url = split_result.scheme + '://' + split_result.netloc + split_result.path
90
+
91
+ # Split parameter.
92
+ params = {
93
+ key: urllib_unquote(value)
94
+ for key, value in map(
95
+ lambda item: item.split('=', 1),
96
+ params_str.split('&')
97
+ )
98
+ }
99
+
100
+ return url, params
101
+
102
+
103
+ def join_cookie(params: dict[str, str]) -> str:
104
+ """
105
+ Join parameters of Cookie.
106
+
107
+ Parameters
108
+ ----------
109
+ params : Parameters.
110
+
111
+ Returns
112
+ -------
113
+ Joined cookie.
114
+ """
115
+
116
+ # Join.
117
+ cookie = '; '.join(
118
+ [
119
+ f'{key}={value}'
120
+ for key, value in params.items()
121
+ ]
122
+ )
123
+
124
+ return cookie
125
+
126
+
127
+ def split_cookie(cookie: str) -> dict[str, str]:
128
+ """
129
+ Split parameters of Cookie.
130
+
131
+ Parameters
132
+ ----------
133
+ cookie : Cookie.
134
+
135
+ Returns
136
+ -------
137
+ Split parameters
138
+ """
139
+
140
+ # Split parameter.
141
+ params = {
142
+ key: value
143
+ for key, value in map(
144
+ lambda item: item.split('=', 1),
145
+ cookie.split('; ')
146
+ )
147
+ }
148
+
149
+ return params
150
+
151
+
152
+ def get_content_type(file: str | bytes) -> str | None:
153
+ """
154
+ Get HTTP content type of file.
155
+
156
+ Parameters
157
+ ----------
158
+ file : File path or bytes data.
159
+
160
+ Returns
161
+ -------
162
+ HTTP content type.
163
+ """
164
+
165
+ # Guess.
166
+ if (
167
+ (
168
+ file.__class__ == str
169
+ and os_isfile(file)
170
+ ) or file.__class__ == bytes
171
+ ):
172
+ file_type_obj = filetype_guess(file)
173
+ else:
174
+ file_type_obj = None
175
+ if file_type_obj is not None:
176
+ file_type = file_type_obj.MIME
177
+ elif file.__class__ == str:
178
+ file_type, _ = guess_type(file)
179
+ else:
180
+ file_type = None
181
+
182
+ return file_type
183
+
184
+
185
+ def request(
186
+ url: str,
187
+ params: dict | None = None,
188
+ data: dict | str | bytes | None = None,
189
+ json: dict | None = None,
190
+ files: dict[str, str | bytes | tuple[str | bytes, dict]] | None = None,
191
+ headers: dict[str, str] = {},
192
+ timeout: float | None = None,
193
+ proxies: dict[str, str] = {},
194
+ stream: bool = False,
195
+ verify: bool = False,
196
+ method: Literal['get', 'post', 'put', 'patch', 'delete', 'options', 'head'] | None = None,
197
+ check: bool | int | Iterable[int] = False
198
+ ) -> Response:
199
+ """
200
+ Send request.
201
+
202
+ Parameters
203
+ ----------
204
+ url : Request URL.
205
+ params : Request URL add parameters.
206
+ data : Request body data.
207
+ - `dict`, Convert to `key=value&...`: format bytes.
208
+ Automatic set `Content-Type` to `application/x-www-form-urlencoded`.
209
+ - `str`: File path to read file bytes data.
210
+ Automatic set `Content-Type` to file media type, and `filename` to file name.
211
+ - `bytes`: File bytes data.
212
+ Automatic set `Content-Type` to file media type.
213
+ json : Request body data, convert to `JSON` format.
214
+ Automatic set `Content-Type` to `application/json`.
215
+ files : Request body data, convert to `multi form` format.
216
+ Automatic set `Content-Type` to `multipart/form-data`.
217
+ - `dict[str, str]`: Parameter name and File path to read file bytes data.
218
+ Automatic set `Content-Type` to file media type, and `filename` to file name.
219
+ - `dict[str, bytes]`: Parameter name and file bytes data.
220
+ - `dict[str, tuple[str, dict]`: Parameter name and File path to read file bytes data and other parameters.
221
+ Automatic set `Content-Type` to file media type, and `filename` to file name.
222
+ - `dict[str, tuple[bytes, dict]`: Parameter name and file bytes data and other parameters.
223
+ headers : Request header data.
224
+ timeout : Request maximun waiting time.
225
+ proxies : Proxy IP setup.
226
+ - `None`: No setup.
227
+ - `dict[str, str]`: Name and use IP of each protocol.
228
+ stream : Whether use stream request.
229
+ verify : Whether verify certificate.
230
+ method : Request method.
231
+ - `None`: Automatic judge.
232
+ When parameter `data` or `json` or `files` not has value, then request method is `get`.
233
+ When parameter `data` or `json` or `files` has value, then request method is `post`.
234
+ - `Literal['get', 'post', 'put', 'patch', 'delete', 'options', 'head']`: Use this request method.
235
+ check : Check response code, and throw exception.
236
+ - `Literal[False]`: Not check.
237
+ - `Literal[True]`: Check if is between 200 and 299.
238
+ - `int`: Check if is this value.
239
+ - `Iterable`: Check if is in sequence.
240
+
241
+ Returns
242
+ -------
243
+ Response object of requests package.
244
+ """
245
+
246
+ # Handle parameter.
247
+ if method is None:
248
+ if data is None and json is None and files is None:
249
+ method = 'get'
250
+ else:
251
+ method = 'post'
252
+ if files is None:
253
+ if data.__class__ == str:
254
+ rfile = RFile(data)
255
+ data = rfile.bytes
256
+ if 'Content-Disposition' not in headers:
257
+ file_name = rfile.name_suffix
258
+ headers['Content-Disposition'] = f'attachment; filename={file_name}'
259
+ if data.__class__ == bytes:
260
+ if 'Content-Type' not in headers:
261
+ headers['Content-Type'] = get_content_type(data)
262
+ else:
263
+ for key, value in files.items():
264
+ if value.__class__ == tuple:
265
+ item_data, item_headers = value
266
+ else:
267
+ item_data, item_headers = value, {}
268
+ if item_data.__class__ == str:
269
+ rfile = RFile(item_data)
270
+ data = rfile.bytes
271
+ item_headers.setdefault('filename', rfile.name_suffix)
272
+ if item_data.__class__ == bytes:
273
+ if 'Content-Type' not in item_headers:
274
+ item_headers['Content-Type'] = get_content_type(item_data)
275
+ files[key] = (
276
+ item_headers.get('filename', key),
277
+ item_data,
278
+ item_headers.get('Content-Type'),
279
+ item_headers
280
+ )
281
+ if not verify:
282
+ filterwarnings(
283
+ 'ignore',
284
+ 'Unverified HTTPS request is being made to host'
285
+ )
286
+
287
+ # Request.
288
+ response = requests_request(
289
+ method,
290
+ url,
291
+ params=params,
292
+ data=data,
293
+ json=json,
294
+ files=files,
295
+ headers=headers,
296
+ timeout=timeout,
297
+ proxies=proxies,
298
+ verify=verify,
299
+ stream=stream
300
+ )
301
+
302
+ # Set encod type.
303
+ if response.encoding == 'ISO-8859-1':
304
+ pattern = r'<meta [^>]*charset=([\w-]+)[^>]*>'
305
+ charset = search(pattern, response.text)
306
+ if charset is None:
307
+ charset = 'utf-8'
308
+ response.encoding = charset
309
+
310
+ # Check code.
311
+ if check is not False:
312
+ if check is True:
313
+ range_ = None
314
+ else:
315
+ range_ = check
316
+ check_response_code(response.status_code, range_)
317
+
318
+ return response
319
+
320
+
321
+ def download(url: str, path: str | None = None) -> str:
322
+ """
323
+ Download file from URL.
324
+
325
+ Parameters
326
+ ----------
327
+ url : Download URL.
328
+ path : Save path.
329
+ - `None`, File name is `download`: and automatic judge file type.
330
+
331
+ Returns
332
+ -------
333
+ File absolute path.
334
+ """
335
+
336
+ # Download.
337
+ response = request(url)
338
+ content = response.content
339
+
340
+ # Judge file type and path.
341
+ if path is None:
342
+ Content_disposition = response.headers.get('Content-Disposition', '')
343
+ if 'filename' in Content_disposition:
344
+ file_name = search(
345
+ 'filename=[\'"]?([^\\s\'"]+)',
346
+ Content_disposition
347
+ )
348
+ else:
349
+ file_name = None
350
+ if file_name is None:
351
+ file_type_obj = get_content_type(content)
352
+ if file_type_obj is not None:
353
+ file_name = 'download.' + file_type_obj.EXTENSION
354
+ if file_name is None:
355
+ file_name = 'download'
356
+ path = os_abspath(file_name)
357
+
358
+ # Save.
359
+ rfile = RFile(path)
360
+ rfile(content)
361
+
362
+ return path
363
+
364
+
365
+ def get_file_stream_time(
366
+ file: str | bytes | int,
367
+ bandwidth: float
368
+ ) -> float:
369
+ """
370
+ Get file stream transfer time, unit second.
371
+
372
+ Parameters
373
+ ----------
374
+ file : File data.
375
+ - `str`: File path.
376
+ - `bytes`: File bytes data.
377
+ - `int`: File bytes size.
378
+ bandwidth : Bandwidth, unit Mpbs.
379
+
380
+ Returns
381
+ -------
382
+ File send seconds.
383
+ """
384
+
385
+ # Get parameter.
386
+ match file:
387
+ case str():
388
+ rfile = RFile(file)
389
+ file_size = rfile.size
390
+ case bytes() | bytearray():
391
+ file_size = len(file)
392
+ case int():
393
+ file_size = file
394
+ case _:
395
+ throw(TypeError, file)
396
+
397
+ # Calculate.
398
+ seconds = file_size / 125_000 / bandwidth
399
+
400
+ return seconds
401
+
402
+
403
+ def listen_socket(
404
+ host: str,
405
+ port: str | int,
406
+ handler: Callable[[bytes], Any]
407
+ ) -> None:
408
+ """
409
+ Listen socket and handle data.
410
+
411
+ Parameters
412
+ ----------
413
+ host : Socket host.
414
+ port : Socket port.
415
+ handler : Handler function.
416
+ """
417
+
418
+ # Handle parameter.
419
+ port = int(port)
420
+ rece_size = 1024 * 1024 * 1024
421
+
422
+ # Instance.
423
+ socket = Socket()
424
+ socket.bind((host, port))
425
+ socket.listen()
426
+
427
+ # Loop.
428
+ while True:
429
+ socket_conn, _ = socket.accept()
430
+ data = socket_conn.recv(rece_size)
431
+ handler(data)