reykit 1.2.1__py3-none-any.whl → 1.2.2__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 CHANGED
@@ -30,5 +30,4 @@ rtask : Multi task methods.
30
30
  rtext : Text methods.
31
31
  rtime : Time methods.
32
32
  rwrap : Decorators.
33
- rzip : File compress methods.
34
33
  """
reykit/rall.py CHANGED
@@ -29,4 +29,3 @@ from .rtask import *
29
29
  from .rtext import *
30
30
  from .rtime import *
31
31
  from .rwrap import *
32
- from .rzip import *
reykit/rdata.py CHANGED
@@ -15,6 +15,9 @@ from collections.abc import Callable, Iterable, Generator, AsyncGenerator
15
15
  from itertools import chain as IChain
16
16
  from decimal import Decimal
17
17
  from json import dumps as json_dumps
18
+ from jwt import encode as jwt_encode, decode as jwt_decode
19
+ from jwt.exceptions import InvalidSignatureError
20
+ from bcrypt import gensalt as bcrypt_gensalt, hashpw as bcrypt_hashpw, checkpw as bcrypt_checkpw
18
21
 
19
22
  from .rbase import T, KT, VT, Base, Null, check_least_one, check_most_one, is_iterable
20
23
 
@@ -29,7 +32,11 @@ __all__ = (
29
32
  'objs_in',
30
33
  'chain',
31
34
  'default_dict',
32
- 'FunctionGenerator'
35
+ 'FunctionGenerator',
36
+ 'encode_jwt',
37
+ 'decode_jwt',
38
+ 'hash_bcrypt',
39
+ 'is_hash_bcrypt'
33
40
  )
34
41
 
35
42
 
@@ -545,3 +552,104 @@ class FunctionGenerator(Base):
545
552
  agenerator = await self.agenerator()
546
553
 
547
554
  return agenerator
555
+
556
+
557
+ def encode_jwt(data: dict[str, Any], key: str | bytes) -> str:
558
+ """
559
+ Encode data to JWT value, based on `HS256`.
560
+
561
+ Parameters
562
+ ----------
563
+ data : Data.
564
+ key : Key.
565
+
566
+ Returns
567
+ -------
568
+ JWT value.
569
+ """
570
+
571
+ # Parameter.
572
+ if type(key) != str:
573
+ key = str(key)
574
+ algorithm = 'HS256'
575
+
576
+ # Encode.
577
+ value = jwt_encode(data, key, algorithm=algorithm)
578
+
579
+ return value
580
+
581
+
582
+ def decode_jwt(jwt: str | bytes, key: str| bytes) -> dict[str, Any] | None:
583
+ """
584
+ Decode JWT value to data, based on `HS256`. When decode error, then return `None`.
585
+
586
+ Parameters
587
+ ----------
588
+ jwt : JWT value.
589
+ key : Key.
590
+
591
+ Returns
592
+ -------
593
+ Data or null.
594
+ """
595
+
596
+ # Parameter.
597
+ algorithm = 'HS256'
598
+
599
+ # Decode.
600
+ try:
601
+ data = jwt_decode(jwt, key, algorithms=algorithm)
602
+ except InvalidSignatureError:
603
+ return
604
+
605
+ return data
606
+
607
+
608
+ def hash_bcrypt(password: str | bytes) -> bytes:
609
+ """
610
+ Get hash password, based on algorithm `bcrypt`.
611
+
612
+ Parameters
613
+ ----------
614
+ password: Password.
615
+
616
+ Returns
617
+ -------
618
+ Hashed password.
619
+ """
620
+
621
+ # Parameter.
622
+ if type(password) != bytes:
623
+ password = bytes(password)
624
+
625
+ # Hash.
626
+ salt = bcrypt_gensalt()
627
+ password_hash = bcrypt_hashpw(password, salt)
628
+
629
+ return password_hash
630
+
631
+
632
+ def is_hash_bcrypt(password: str | bytes, password_hash: str | bytes) -> bool:
633
+ """
634
+ Whether is match password and hashed password.
635
+
636
+ Parameters
637
+ ----------
638
+ password: Password.
639
+ password_hash : Hashed password.
640
+
641
+ Returns
642
+ -------
643
+ Judgment result.
644
+ """
645
+
646
+ # Parameter.
647
+ if type(password) != bytes:
648
+ password = bytes(password)
649
+ if type(password_hash) != bytes:
650
+ password_hash = bytes(password_hash)
651
+
652
+ # Judge.
653
+ result = bcrypt_checkpw(password, password_hash)
654
+
655
+ return result
reykit/rimage.py CHANGED
@@ -212,7 +212,7 @@ def to_pil_image(source: str | bytes) -> Image:
212
212
 
213
213
 
214
214
  def generate_captcha_image(
215
- text: int | str | None = None,
215
+ text: int | str = 5,
216
216
  path: str | None = None,
217
217
  **kwargs: Any
218
218
  ) -> bytes:
@@ -222,7 +222,6 @@ def generate_captcha_image(
222
222
  Parameters
223
223
  ----------
224
224
  text : Text, contains digits and Uppercase letters and lowercase letters.
225
- - `None`: Random five characters.
226
225
  - `int`: Given length Random characters.
227
226
  - `str`: Given characters.
228
227
  path : File save path.
@@ -235,7 +234,6 @@ def generate_captcha_image(
235
234
  """
236
235
 
237
236
  # Parameter.
238
- text = text or 5
239
237
  if type(text) == int:
240
238
  text = randchar(text, False)
241
239
 
reykit/ros.py CHANGED
@@ -14,11 +14,12 @@ if TYPE_CHECKING:
14
14
  from _typeshed import OpenTextMode, OpenBinaryMode
15
15
  from io import TextIOBase, BufferedIOBase
16
16
  from os import (
17
+ getcwd as os_getcwd,
17
18
  walk as os_walk,
18
19
  listdir as os_listdir,
19
20
  makedirs as os_makedirs,
20
21
  renames as os_renames,
21
- remove as os_remove
22
+ remove as os_remove,
22
23
  )
23
24
  from os.path import (
24
25
  join as os_join,
@@ -40,7 +41,6 @@ from pathlib import Path
40
41
  from hashlib import md5 as hashlib_md5
41
42
  from tomllib import loads as tomllib_loads
42
43
  from json import JSONDecodeError
43
- from filetype import guess as filetype_guess
44
44
  from tempfile import TemporaryFile, TemporaryDirectory
45
45
 
46
46
  from .rbase import Base, throw
@@ -63,6 +63,8 @@ __all__ = (
63
63
  'TempFile',
64
64
  'TempFolder',
65
65
  'FileStore',
66
+ 'compress',
67
+ 'decompress',
66
68
  'doc_to_docx',
67
69
  'extract_docx_content',
68
70
  'extract_pdf_content',
@@ -2105,6 +2107,97 @@ class FileStore(Base):
2105
2107
  return path
2106
2108
 
2107
2109
 
2110
+ def compress(
2111
+ path: str,
2112
+ build_dir: str | None = None,
2113
+ overwrite: bool = True
2114
+ ) -> None:
2115
+ """
2116
+ Compress file or folder.
2117
+
2118
+ Parameters
2119
+ ----------
2120
+ path : File or folder path.
2121
+ build_dir : Build directory.
2122
+ - `None`: Work directory.
2123
+ - `str`: Use this value.
2124
+ overwrite : Whether to overwrite.
2125
+ """
2126
+
2127
+ from zipfile import ZipFile, ZIP_DEFLATED
2128
+
2129
+ # Parameter.
2130
+ build_dir = Folder(build_dir).path
2131
+ if overwrite:
2132
+ mode = 'w'
2133
+ else:
2134
+ mode = 'x'
2135
+ is_file = os_isfile(path)
2136
+ if is_file:
2137
+ file = File(path)
2138
+ obj_name = file.name_suffix
2139
+ else:
2140
+ folder = Folder(path)
2141
+ obj_name = folder.name
2142
+ build_name = obj_name + '.zip'
2143
+ build_path = join_path(build_dir, build_name)
2144
+
2145
+ # Compress.
2146
+ with ZipFile(build_path, mode, ZIP_DEFLATED) as zip_file:
2147
+
2148
+ ## File.
2149
+ if is_file:
2150
+ zip_file.write(file.path, file.name_suffix)
2151
+
2152
+ ## Folder.
2153
+ else:
2154
+ dir_path_len = len(folder.path)
2155
+ dirs = os_walk(folder.path)
2156
+ for folder_name, sub_folders_name, files_name in dirs:
2157
+ for sub_folder_name in sub_folders_name:
2158
+ sub_folder_path = join_path(folder_name, sub_folder_name)
2159
+ zip_path = sub_folder_path[dir_path_len:]
2160
+ zip_file.write(sub_folder_path, zip_path)
2161
+ for file_name in files_name:
2162
+ file_path = join_path(folder_name, file_name)
2163
+ zip_path = file_path[dir_path_len:]
2164
+ zip_file.write(file_path, zip_path)
2165
+
2166
+
2167
+ def decompress(
2168
+ obj_path: str,
2169
+ build_dir: str | None = None,
2170
+ password: str | None = None
2171
+ ) -> None:
2172
+ """
2173
+ Decompress compressed object.
2174
+
2175
+ Parameters
2176
+ ----------
2177
+ obj_path : Compressed object path.
2178
+ build_dir : Build directory.
2179
+ - `None`: Work directory.
2180
+ - `str`: Use this value.
2181
+ passwrod : Unzip Password.
2182
+ - `None`: No Unzip Password.
2183
+ - `str`: Use this value.
2184
+ """
2185
+
2186
+ from zipfile import ZipFile, is_zipfile
2187
+
2188
+ # Check object whether can be decompress.
2189
+ is_support = is_zipfile(obj_path)
2190
+ if not is_support:
2191
+ raise AssertionError('file format that cannot be decompressed')
2192
+
2193
+ # Parameter.
2194
+ build_dir = build_dir or os_getcwd()
2195
+
2196
+ # Decompress.
2197
+ with ZipFile(obj_path) as zip_file:
2198
+ zip_file.extractall(build_dir, pwd=password)
2199
+
2200
+
2108
2201
  def doc_to_docx(path: str, save_path: str | None = None) -> str:
2109
2202
  """
2110
2203
  Convert `DOC` file to `DOCX` file.
reykit/rrand.py CHANGED
@@ -313,7 +313,7 @@ def randi(
313
313
 
314
314
 
315
315
  def randchar(
316
- length: int,
316
+ length: int = 32,
317
317
  punctuation: bool = True
318
318
  ) -> str:
319
319
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: reykit
3
- Version: 1.2.1
3
+ Version: 1.2.2
4
4
  Summary: Kit method set.
5
5
  Project-URL: homepage, https://github.com/reyxbo/reykit/
6
6
  Author-email: Rey <reyxbo@163.com>
@@ -16,6 +16,7 @@ Keywords: kit,rey,reyxbo,tool
16
16
  Requires-Python: >=3.12
17
17
  Requires-Dist: aiohttp
18
18
  Requires-Dist: apscheduler
19
+ Requires-Dist: bcrypt
19
20
  Requires-Dist: captcha
20
21
  Requires-Dist: concurrent-log-handler
21
22
  Requires-Dist: filetype
@@ -23,6 +24,7 @@ Requires-Dist: pandas
23
24
  Requires-Dist: pdfplumber
24
25
  Requires-Dist: pillow
25
26
  Requires-Dist: psutil
27
+ Requires-Dist: pyjwt
26
28
  Requires-Dist: pymem
27
29
  Requires-Dist: python-docx
28
30
  Requires-Dist: pyzbar
@@ -1,15 +1,15 @@
1
- reykit/__init__.py,sha256=5oKzVHvTmotJB08LhrMFQO3tFVFy7JuqXMn9PqnJEH8,779
2
- reykit/rall.py,sha256=-gxGRcEcK7zTcA66DgGLw46QuDsJcdda6NQA_Xuyq8w,619
1
+ reykit/__init__.py,sha256=Garu_XWuCXSp2a8rXviXcndlDi03vtwx9IDgIYycTw0,748
2
+ reykit/rall.py,sha256=Oljb0rwJyCrC6LhGLxpPizdB6MhxoZ9DOOnWM1sQC4o,598
3
3
  reykit/rbase.py,sha256=snRdHOMTdsaWFYDQ5sTIcdJRybNcMarlz59EErbrepA,20897
4
- reykit/rdata.py,sha256=j3BBeWKMIwowjC-W_5wkJxIWvVlZsqt1mYMKuQbaPG0,11323
4
+ reykit/rdata.py,sha256=nOlVDWCimTAeuuzCM4vVTbbomULREJd4Z13ZcHGCOoc,13565
5
5
  reykit/remail.py,sha256=DE4sxfJEXNu6MiBJKUsWXqvBrIOJNmnm_1lnGL0tZec,6693
6
- reykit/rimage.py,sha256=z-cjI_MgEbUhuKgIbvDS_e2fy2CrnBhr_FS6D8XuAg0,6124
6
+ reykit/rimage.py,sha256=yzrvZdYm9A08DjXq9nBRFti6k48o1rVJHv5-V9cnb74,6049
7
7
  reykit/rlog.py,sha256=yBArs48wl509v4q7e1vHbE3E_Bqi3VHEV-Iuw2Y58f8,25649
8
8
  reykit/rmonkey.py,sha256=PBA19EqlJHI9FxT8C4-t59RlyAfwfhX7xV9ZJ3PegWo,7894
9
9
  reykit/rnet.py,sha256=UlzkOttGxZPld8WCzbjbx-NUziPEj-n82mHH48zKBsA,17953
10
10
  reykit/rnum.py,sha256=WNtvKSS-MkgmudIqDR8Xv4WIdNLyEPIO0jz5ukL3cXg,3603
11
- reykit/ros.py,sha256=quDCZfqpYtZRgyK2wtscm92oPm3PaKoBqDBAaM29HV8,47714
12
- reykit/rrand.py,sha256=nH0e4wRiLba7Tg6pRyn7qnPrzIXdlJxm7e4S1EqsBLQ,8549
11
+ reykit/ros.py,sha256=VEwR1Yv4mozzQRPra4t1da3e8H4b0uYX4wsbeSV__4E,50276
12
+ reykit/rrand.py,sha256=12HD-g4gyg1jI5qnd8vd7xFsprwOXITNsprhqt3VwZU,8554
13
13
  reykit/rre.py,sha256=fVSTKa31lmeZCKhvbgRmDLA4KTLkLBgAYox-HQXs2d8,6001
14
14
  reykit/rschedule.py,sha256=H7JQbX3kVFetmGS2EZ_216NnZj-ilGl6h1MusIx8ZWk,12288
15
15
  reykit/rstdout.py,sha256=YEKP8-OcCSk8TTtChgqTkO7NSnJ5LOb77d2qiE_3vLI,8081
@@ -19,10 +19,9 @@ reykit/rtask.py,sha256=yKhsAhoMfJ99LQbKB-xc8bmP7mehC60aroK49X5N-_4,29242
19
19
  reykit/rtext.py,sha256=cf3a0uGmdr2ucKjGzYkQFkUPdixKJW1c82FPDdmRzwM,13227
20
20
  reykit/rtime.py,sha256=3UPpUK027TY1Wgf5bzwCQo1N4ZceZ2YtcZzM9I8Q9Qg,17766
21
21
  reykit/rwrap.py,sha256=lOKBhSqx8V_PcsdipPP4SaiGXXcpfaEhO_qEGSySEkw,15065
22
- reykit/rzip.py,sha256=vYw17toqg-DbMjvycluohU9zVX73uYYqQGAp_b21pA8,3433
23
22
  reykit/rdll/__init__.py,sha256=mewj06HHIzzW6oreQAz-6in2zYwNJ4-d1eWWL7CPQgc,685
24
23
  reykit/rdll/rdll_core.py,sha256=zBmOyxD6LkbNIadXmFHLJinj-6UFko8D6w5d7hYA7vU,5077
25
- reykit-1.2.1.dist-info/METADATA,sha256=B4vGbMbYqdLF4jOsZuO8Y3PUzijGQAT0aPmqpeSw17A,1880
26
- reykit-1.2.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
27
- reykit-1.2.1.dist-info/licenses/LICENSE,sha256=UYLPqp7BvPiH8yEZduJqmmyEl6hlM3lKrFIefiD4rvk,1059
28
- reykit-1.2.1.dist-info/RECORD,,
24
+ reykit-1.2.2.dist-info/METADATA,sha256=rs1iRtkoPQ1Wh166y9Liw-9mgxFJLKSnAYm7gOZyO5w,1923
25
+ reykit-1.2.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
26
+ reykit-1.2.2.dist-info/licenses/LICENSE,sha256=UYLPqp7BvPiH8yEZduJqmmyEl6hlM3lKrFIefiD4rvk,1059
27
+ reykit-1.2.2.dist-info/RECORD,,
reykit/rzip.py DELETED
@@ -1,135 +0,0 @@
1
- # !/usr/bin/env python
2
- # -*- coding: utf-8 -*-
3
-
4
- """
5
- @Time : 2023-01-19
6
- @Author : Rey
7
- @Contact : reyxbo@163.com
8
- @Explain : File compress methods.
9
- """
10
-
11
-
12
- from zipfile import ZipFile, is_zipfile, ZIP_DEFLATED
13
- from os import getcwd as os_getcwd, walk as os_walk
14
- from os.path import isfile as os_isfile
15
-
16
- from .ros import File, Folder, join_path
17
-
18
-
19
- __all__ = (
20
- 'compress',
21
- 'decompress',
22
- 'zip'
23
- )
24
-
25
-
26
- def compress(
27
- path: str,
28
- build_dir: str | None = None,
29
- overwrite: bool = True
30
- ) -> None:
31
- """
32
- Compress file or folder.
33
-
34
- Parameters
35
- ----------
36
- path : File or folder path.
37
- build_dir : Build directory.
38
- - `None`: Work directory.
39
- - `str`: Use this value.
40
- overwrite : Whether to overwrite.
41
- """
42
-
43
- # Parameter.
44
- build_dir = Folder(build_dir).path
45
- if overwrite:
46
- mode = 'w'
47
- else:
48
- mode = 'x'
49
- is_file = os_isfile(path)
50
- if is_file:
51
- file = File(path)
52
- obj_name = file.name_suffix
53
- else:
54
- folder = Folder(path)
55
- obj_name = folder.name
56
- build_name = obj_name + '.zip'
57
- build_path = join_path(build_dir, build_name)
58
-
59
- # Compress.
60
- with ZipFile(build_path, mode, ZIP_DEFLATED) as zip_file:
61
-
62
- ## File.
63
- if is_file:
64
- zip_file.write(file.path, file.name_suffix)
65
-
66
- ## Folder.
67
- else:
68
- dir_path_len = len(folder.path)
69
- dirs = os_walk(folder.path)
70
- for folder_name, sub_folders_name, files_name in dirs:
71
- for sub_folder_name in sub_folders_name:
72
- sub_folder_path = join_path(folder_name, sub_folder_name)
73
- zip_path = sub_folder_path[dir_path_len:]
74
- zip_file.write(sub_folder_path, zip_path)
75
- for file_name in files_name:
76
- file_path = join_path(folder_name, file_name)
77
- zip_path = file_path[dir_path_len:]
78
- zip_file.write(file_path, zip_path)
79
-
80
-
81
- def decompress(
82
- obj_path: str,
83
- build_dir: str | None = None,
84
- password: str | None = None
85
- ) -> None:
86
- """
87
- Decompress compressed object.
88
-
89
- Parameters
90
- ----------
91
- obj_path : Compressed object path.
92
- build_dir : Build directory.
93
- - `None`: Work directory.
94
- - `str`: Use this value.
95
- passwrod : Unzip Password.
96
- - `None`: No Unzip Password.
97
- - `str`: Use this value.
98
- """
99
-
100
- # Check object whether can be decompress.
101
- is_support = is_zipfile(obj_path)
102
- if not is_support:
103
- raise AssertionError('file format that cannot be decompressed')
104
-
105
- # Parameter.
106
- build_dir = build_dir or os_getcwd()
107
-
108
- # Decompress.
109
- with ZipFile(obj_path) as zip_file:
110
- zip_file.extractall(build_dir, pwd=password)
111
-
112
-
113
- def zip(
114
- obj_path: str,
115
- build_dir: str | None = None
116
- ) -> None:
117
- """
118
- Automatic judge and compress or decompress object.
119
-
120
- Parameters
121
- ----------
122
- obj_path : File or folder or compressed object path.
123
- output_path : Build directory.
124
- - `None`: Work directory.
125
- - `str`: Use this value.
126
- """
127
-
128
- # Judge compress or decompress.
129
- is_support = is_zipfile(obj_path)
130
-
131
- # Execute.
132
- if is_support:
133
- decompress(obj_path, build_dir)
134
- else:
135
- compress(obj_path, build_dir)
File without changes