ezKit 1.7.8__py3-none-any.whl → 1.8.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.
ezKit/bottle.py CHANGED
@@ -17,7 +17,7 @@ from __future__ import print_function
17
17
  import sys
18
18
 
19
19
  __author__ = 'Marcel Hellkamp'
20
- __version__ = '0.13.1'
20
+ __version__ = '0.13.2'
21
21
  __license__ = 'MIT'
22
22
 
23
23
  ###############################################################################
@@ -185,6 +185,7 @@ def depr(major, minor, cause, fix, stacklevel=3):
185
185
  if DEBUG == 'strict':
186
186
  raise DeprecationWarning(text)
187
187
  warnings.warn(text, DeprecationWarning, stacklevel=stacklevel)
188
+ return DeprecationWarning(text)
188
189
 
189
190
 
190
191
  def makelist(data): # This is just too handy
@@ -4671,5 +4672,9 @@ def _main(argv): # pragma: no coverage
4671
4672
  config=config)
4672
4673
 
4673
4674
 
4674
- if __name__ == '__main__': # pragma: no coverage
4675
+ def main():
4675
4676
  _main(sys.argv)
4677
+
4678
+
4679
+ if __name__ == '__main__': # pragma: no coverage
4680
+ main()
@@ -1,36 +1,32 @@
1
+ """Bottle Extensions"""
1
2
  from typing import Callable
2
3
 
3
4
  from . import bottle, utils
4
5
 
5
6
 
6
7
  def enable_cors(fn: Callable) -> Callable:
7
- """
8
- Bottle CORS
9
- """
10
- """
11
- 参考文档:
12
- - https://stackoverflow.com/a/17262900
13
- - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers
14
- - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Methods
15
- - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin
16
- """
8
+ """Bottle CORS"""
9
+ # 参考文档:
10
+ # - https://stackoverflow.com/a/17262900
11
+ # - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers
12
+ # - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Methods
13
+ # - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin
17
14
  def cors(*args, **kwargs):
18
15
  bottle.response.headers['Access-Control-Allow-Headers'] = '*'
19
16
  bottle.response.headers['Access-Control-Allow-Methods'] = '*'
20
17
  bottle.response.headers['Access-Control-Allow-Origin'] = '*'
21
18
  if bottle.request.method != 'OPTIONS':
22
19
  return fn(*args, **kwargs)
20
+ return None
23
21
  return cors
24
22
 
25
- def request_json() -> dict | None:
26
- """
27
- Bottle Request JSON
28
- """
23
+ def request_json() -> bottle.DictProperty | None:
24
+ """Bottle Request JSON"""
29
25
  try:
30
- data: dict = bottle.request.json
26
+ data = bottle.request.json
31
27
  if utils.v_true(data, dict):
32
28
  return data
33
- else:
34
- return None
35
- except:
29
+ return None
30
+ except Exception as e:
31
+ print(e)
36
32
  return None
ezKit/database.py CHANGED
@@ -1,15 +1,16 @@
1
- '''
1
+ """
2
2
  Column, Table, MetaData API
3
3
  https://docs.sqlalchemy.org/en/14/core/metadata.html#column-table-metadata-api
4
4
  CursorResult
5
5
  https://docs.sqlalchemy.org/en/20/core/connections.html#sqlalchemy.engine.CursorResult
6
6
  PostgreSQL 14 Data Types
7
7
  https://www.postgresql.org/docs/14/datatype.html
8
- '''
8
+ """
9
9
  import csv
10
+ from typing import Any
10
11
 
11
12
  from loguru import logger
12
- from sqlalchemy import Index, create_engine, text
13
+ from sqlalchemy import CursorResult, Index, create_engine, text
13
14
 
14
15
  from . import utils
15
16
 
@@ -20,152 +21,184 @@ class Database():
20
21
  engine = create_engine('sqlite://')
21
22
 
22
23
  def __init__(self, engine_url, **engine_options):
23
- '''Initiation'''
24
- if engine_url is not None:
24
+ """Initiation"""
25
+ if engine_url is not None and utils.v_true(engine_url, str):
25
26
  if utils.v_true(engine_options, dict):
26
27
  self.engine = create_engine(engine_url, **engine_options)
27
28
  else:
28
29
  self.engine = create_engine(engine_url)
30
+ else:
31
+ pass
29
32
 
30
33
  def initializer(self):
31
- '''ensure the parent proc's database connections are not touched in the new connection pool'''
34
+ """ensure the parent proc's database connections are not touched in the new connection pool"""
32
35
  self.engine.dispose(close=False)
33
36
 
34
- def connect_test(self):
35
- info = '数据库连接测试'
37
+ def connect_test(self) -> bool:
38
+ info = "Database connect test"
36
39
  try:
37
- logger.info(f'{info}......')
40
+ logger.info(f"{info} ......")
38
41
  self.engine.connect()
39
- logger.success(f'{info}[成功]')
42
+ logger.success(f"{info} [success]")
40
43
  return True
41
44
  except Exception as e:
42
- logger.error(f'{info}[失败]')
45
+ logger.error(f"{info} [failure]")
43
46
  logger.exception(e)
44
47
  return False
45
48
 
46
- def metadata_init(self, base, **kwargs):
49
+ def metadata_init(self, base, **kwargs) -> bool:
47
50
  # https://stackoverflow.com/questions/19175311/how-to-create-only-one-table-with-sqlalchemy
48
- info = '初始化表'
51
+ info = "Database init table"
49
52
  try:
50
- logger.info(f'{info}......')
53
+ logger.info(f"{info} ......")
51
54
  base.metadata.drop_all(self.engine, **kwargs)
52
55
  base.metadata.create_all(self.engine, **kwargs)
53
- logger.success(f'{info}[成功]')
56
+ logger.success(f"{info} [success]")
54
57
  return True
55
58
  except Exception as e:
56
- logger.error(f'{info}[失败]')
59
+ logger.error(f"{info} [failure]")
57
60
  logger.exception(e)
58
61
  return False
59
62
 
60
- def create_index(self, index_name, table_field):
63
+ def create_index(self, index_name, table_field) -> bool:
61
64
  # 创建索引
62
65
  # https://stackoverflow.com/a/41254430
63
66
  # 示例:
64
67
  # index_name: a_share_list_code_idx1
65
68
  # table_field: Table_a_share_list.code
66
- info = '创建索引'
69
+ info = "Database create index"
67
70
  try:
68
- logger.info(f'{info}')
71
+ logger.info(f"{info} ......")
69
72
  idx = Index(index_name, table_field)
70
73
  try:
71
74
  idx.drop(bind=self.engine)
72
75
  except Exception as e:
73
76
  logger.exception(e)
74
77
  idx.create(bind=self.engine)
75
- logger.success(f'{info}[成功]')
78
+ logger.success(f'{info} [success]')
76
79
  return True
77
80
  except Exception as e:
78
- logger.error(f'{info}[失败]')
81
+ logger.error(f'{info} [failure]')
79
82
  logger.error(e)
80
83
  return False
81
84
 
82
85
  # 私有函数, 保存 execute 的结果到 CSV 文件
83
- def _result_save(self, file, data, echo=True):
86
+ def _result_save(self, file, data) -> bool:
84
87
  try:
85
88
  outcsv = csv.writer(file)
86
89
  outcsv.writerow(data.keys())
87
90
  outcsv.writerows(data)
88
91
  return True
89
92
  except Exception as e:
90
- if echo is True:
91
- logger.exception(e)
93
+ logger.exception(e)
92
94
  return False
93
95
 
94
- def execute(self, sql=None, sql_file=None, sql_file_kwargs=None, csv_file=None, csv_file_kwargs=None, echo=True):
95
- '''
96
+ def execute(
97
+ self,
98
+ sql: str | None = None,
99
+ sql_file: str | None = None,
100
+ sql_file_kwargs: dict | None = None,
101
+ csv_file: str | None = None,
102
+ csv_file_kwargs: dict | None = None
103
+ ) -> CursorResult[Any] | bool:
104
+ """
96
105
  echo 是否打印日志
97
106
  某些情况下只需要结果, 不需要日志, 将 echo 设置为 False 即可
98
- '''
107
+ """
99
108
 
100
- info_prefix = '[执行SQL]'
109
+ # info_prefix = '[Execute SQL]'
101
110
 
102
111
  # ------------------------------------------------------------
103
112
 
104
113
  # 提取 SQL
105
114
  # 如果 sql 和 sql_file 同时存在, 优先执行 sql
106
115
  sql_object = None
107
- info = f'{info_prefix}提取SQL'
116
+ info: str = "Extract SQL"
108
117
  try:
109
- if echo is True:
110
- logger.info(f'{info}......')
118
+
119
+ logger.info(f"{info} ......")
120
+
111
121
  if utils.v_true(sql, str):
122
+
112
123
  sql_object = sql
113
- elif utils.v_true(sql_file, str):
124
+
125
+ elif sql_file is not None and utils.v_true(sql_file, str):
126
+
114
127
  # 判断文件是否存在
115
- if utils.check_file_type(sql_file, 'file') is False:
116
- logger.error(f'文件不存在: {sql_file}') if echo == True else next
128
+ if isinstance(sql_file, str) and utils.check_file_type(sql_file, "file") is False:
129
+
130
+ logger.error(f"No such file: {sql_file}")
117
131
  return False
118
- # 读取文件内容
119
- if utils.v_true(sql_file_kwargs, dict):
120
- with open(sql_file, 'r', **sql_file_kwargs) as _file:
121
- sql_object = _file.read()
122
- else:
123
- with open(sql_file, 'r') as _file:
124
- sql_object = _file.read()
132
+
133
+ if isinstance(sql_file, str) and utils.v_true(sql_file, str):
134
+
135
+ # 读取文件内容
136
+ if sql_file_kwargs is not None and utils.v_true(sql_file_kwargs, dict):
137
+ with open(sql_file, "r", encoding="utf-8", **sql_file_kwargs) as _file:
138
+ sql_object = _file.read()
139
+ else:
140
+ with open(sql_file, "r", encoding="utf-8") as _file:
141
+ sql_object = _file.read()
142
+
125
143
  else:
126
- logger.error(f'{info}[失败]') if echo == True else next
127
- logger.error(f'{info_prefix}SQL SQL文件 错误') if echo == True else next
144
+
145
+ logger.error("SQL or SQL file error")
146
+ logger.error(f"{info} [failure]")
128
147
  return False
129
- logger.success(f'{info}[成功]') if echo == True else next
148
+
149
+ logger.success(f'{info} [success]')
150
+
130
151
  except Exception as e:
131
- logger.error(f'{info}[失败]') if echo == True else next
132
- logger.exception(e) if echo == True else next
152
+
153
+ logger.error(f"{info} [failure]")
154
+ logger.exception(e)
133
155
  return False
134
156
 
135
157
  # ------------------------------------------------------------
136
158
 
137
159
  # 执行 SQL
138
- info = f'{info_prefix}执行SQL'
160
+ info: str = "Execute SQL"
139
161
  try:
140
- logger.info(f'{info}......') if echo == True else next
162
+
163
+ logger.info(f"{info} ......")
164
+
141
165
  with self.engine.connect() as connect:
166
+
142
167
  # 执行SQL
168
+ if sql_object is None:
169
+ return False
170
+
143
171
  result = connect.execute(text(sql_object))
144
- if csv_file == None:
172
+
173
+ if csv_file is None:
145
174
  # 如果 csv_file 没有定义, 则直接返回结果
146
- logger.success(f'{info}[成功]') if echo == True else next
175
+ logger.success(f'{info} [success]')
147
176
  return result
177
+
178
+ # 如果 csv_file 有定义, 则保存结果到 csv_file
179
+ info_of_save = f"Save result to file: {csv_file}"
180
+ logger.info(f"{info_of_save} .......")
181
+
182
+ # 保存结果
183
+ if isinstance(csv_file_kwargs, dict) and utils.v_true(csv_file_kwargs, dict):
184
+ with open(csv_file, "w", encoding="utf-8", **csv_file_kwargs) as _file:
185
+ result_of_save = self._result_save(_file, result)
148
186
  else:
149
- # 如果 csv_file 有定义, 则保存结果到 csv_file
150
- info_of_save = f'{info_prefix}保存结果到文件: {csv_file}'
151
- logger.info(f'{info_of_save} .......') if echo == True else next
152
- # 保存结果
153
- if utils.v_true(csv_file_kwargs, dict):
154
- with open(csv_file, 'w', **csv_file_kwargs) as _file:
155
- result_of_save = self._result_save(_file, result, echo=echo)
156
- else:
157
- with open(csv_file, 'w') as _file:
158
- result_of_save = self._result_save(_file, result, echo=echo)
159
- # 检查保存结果
160
- if result_of_save == True:
161
- logger.success(f'{info_of_save} [成功]') if echo == True else next
162
- logger.success(f'{info}[成功]') if echo == True else next
163
- return True
164
- else:
165
- logger.error(f'{info_of_save} [失败]') if echo == True else next
166
- logger.error(f'{info}[失败]') if echo == True else next
167
- return False
187
+ with open(csv_file, "w", encoding="utf-8") as _file:
188
+ result_of_save = self._result_save(_file, result)
189
+
190
+ # 检查保存结果
191
+ if result_of_save is True:
192
+ logger.success(f'{info_of_save} [success]')
193
+ logger.success(f'{info} [success]')
194
+ return True
195
+
196
+ logger.error(f"{info_of_save} [failure]")
197
+ logger.error(f"{info} [failure]")
198
+ return False
199
+
168
200
  except Exception as e:
169
- logger.error(f'{info}[失败]') if echo == True else next
170
- logger.exception(e) if echo == True else next
201
+
202
+ logger.error(f'{info} [failure]')
203
+ logger.exception(e)
171
204
  return False
ezKit/http.py CHANGED
@@ -1,4 +1,5 @@
1
1
  import json
2
+ from typing import Any
2
3
 
3
4
  import requests
4
5
  from loguru import logger
@@ -11,61 +12,59 @@ def download(
11
12
  file: dict,
12
13
  chunks: bool = False,
13
14
  iter_content: dict | None = None,
14
- echo: bool = False,
15
- info: str = None,
16
- debug: bool = False
15
+ info: str | None = None
17
16
  ) -> bool:
18
- "下载文件"
17
+ """下载文件"""
19
18
 
20
19
  if utils.v_true(request, dict):
21
- request_arguments = {'method': 'GET', 'stream': True, **request}
20
+ request_arguments = {"method": "GET", "stream": True, **request}
22
21
  else:
23
22
  return False
24
23
 
25
24
  if utils.v_true(file, dict):
26
- file_arguments = {'mode': 'wb', **file}
25
+ file_arguments = {"mode": "wb", **file}
27
26
  else:
28
27
  return False
29
28
 
30
- if utils.v_true(iter_content, dict):
31
- iter_content_arguments = {'chunk_size': 1024, **iter_content}
29
+ if iter_content is not None and utils.v_true(iter_content, dict):
30
+ iter_content_arguments = {"chunk_size": 1024, **iter_content}
32
31
  else:
33
- iter_content_arguments = {'chunk_size': 1024}
32
+ iter_content_arguments = {"chunk_size": 1024}
34
33
 
35
- info = f'下载 {info}' if utils.v_true(info, str) else f'下载'
34
+ info_prefix: str = "Download"
35
+ if utils.v_true(info, str):
36
+ info_prefix = f"Download {info}"
36
37
 
37
38
  try:
38
39
 
39
- logger.info(f'{info} ......') if utils.v_true(echo, bool) else next
40
+ logger.info(f'{info_prefix} ......')
40
41
 
41
42
  response = requests.request(**request_arguments)
42
43
 
43
- with open(**file_arguments) as _file:
44
+ # # pylint: disable=W1514
45
+ with open(**file_arguments) as _file: # type: ignore
44
46
 
45
47
  if utils.v_true(chunks, bool):
46
- for _chunk in response.iter_content(**iter_content_arguments):
48
+ for _chunk in response.iter_content(**iter_content_arguments): # type: ignore
47
49
  _file.write(_chunk)
48
50
  else:
49
51
  _file.write(response.content)
50
52
 
51
- logger.success(f'{info} [成功]') if utils.v_true(echo, bool) else next
53
+ logger.success(f'{info_prefix} [success]')
52
54
 
53
55
  return True
54
56
 
55
57
  except Exception as e:
56
- logger.exception(e) if debug is True else next
57
- logger.error(f'{info} [失败]') if utils.v_true(echo, bool) else next
58
+
59
+ logger.error(f'{info_prefix} [failure]')
60
+ logger.exception(e)
58
61
  return False
59
62
 
60
63
 
61
- def response_json(
62
- data: any = None,
63
- debug: bool = False,
64
- **kwargs
65
- ) -> str:
64
+ def response_json(data: Any = None, **kwargs) -> str | None:
66
65
  """解决字符编码问题: ensure_ascii=False"""
67
66
  try:
68
67
  return json.dumps(data, default=str, ensure_ascii=False, sort_keys=True, **kwargs)
69
68
  except Exception as e:
70
- logger.exception(e) if debug is True else next
69
+ logger.exception(e)
71
70
  return None
ezKit/mongo.py CHANGED
@@ -28,7 +28,7 @@ class Mongo():
28
28
  logger.success(f"{info} [success]")
29
29
  return True
30
30
  except Exception as e:
31
- logger.error(f"{info} [failed]")
31
+ logger.error(f"{info} [failure]")
32
32
  logger.exception(e)
33
33
  return False
34
34
 
@@ -56,12 +56,12 @@ class Mongo():
56
56
  # 插入多条数据
57
57
  result = db_collection.insert_many(data)
58
58
  else:
59
- logger.error(f"{info} [failed]")
59
+ logger.error(f"{info} [failure]")
60
60
  logger.error("Data type error")
61
61
  return False
62
62
  logger.success(f"{info} [success]")
63
63
  return result
64
64
  except Exception as e:
65
- logger.error(f"{info} [failed]")
65
+ logger.error(f"{info} [failure]")
66
66
  logger.exception(e)
67
67
  return False
ezKit/redis.py CHANGED
@@ -20,9 +20,10 @@ class Redis:
20
20
  """Initiation"""
21
21
  if isinstance(arguments, str) and utils.v_true(arguments, str):
22
22
  self.redis = RedisClient.from_url(arguments)
23
-
24
- if isinstance(arguments, dict) and utils.v_true(arguments, dict):
23
+ elif isinstance(arguments, dict) and utils.v_true(arguments, dict):
25
24
  self.redis = RedisClient.Redis(**arguments)
25
+ else:
26
+ pass
26
27
 
27
28
  def connect_test(self) -> bool:
28
29
  info = "Redis connect test"
@@ -32,7 +33,7 @@ class Redis:
32
33
  logger.success(f"{info} [success]")
33
34
  return True
34
35
  except Exception as e:
35
- logger.error(f"{info} [failed]")
36
+ logger.error(f"{info} [failure]")
36
37
  logger.exception(e)
37
38
  return False
38
39
 
@@ -48,6 +49,6 @@ class Redis:
48
49
  logger.success(f"{info} [success]")
49
50
  return True
50
51
  except Exception as e:
51
- logger.error(f"{info} [failed]")
52
+ logger.error(f"{info} [failure]")
52
53
  logger.exception(e)
53
54
  return False
ezKit/sendemail.py CHANGED
@@ -1,12 +1,5 @@
1
1
  """发送邮件"""
2
2
  # https://stackoverflow.com/questions/882712/sending-html-email-using-python
3
- # pylint: disable=E0611
4
- # pylint: disable=R0911
5
- # pylint: disable=R0912
6
- # pylint: disable=R0913
7
- # pylint: disable=R0914
8
- # pylint: disable=R0915
9
- # pylint: disable=R1710
10
3
  import smtplib
11
4
  from email.header import Header
12
5
  from email.mime.image import MIMEImage
ezKit/utils.py CHANGED
@@ -1468,8 +1468,8 @@ def create_empty_file(
1468
1468
  # 创建一个空文件
1469
1469
  if v_true(debug, bool):
1470
1470
  logger.info(f"file: {file}")
1471
- # pylint: disable=R1732,disable=W1514
1472
- open(file, 'w').close()
1471
+ # pylint: disable=R1732
1472
+ open(file, "w", encoding="utf-8").close()
1473
1473
  # 返回文件路径
1474
1474
  return file
1475
1475
  except Exception as e:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ezKit
3
- Version: 1.7.8
3
+ Version: 1.8.0
4
4
  Summary: Easy Kit
5
5
  Author: septvean
6
6
  Author-email: septvean@gmail.com
@@ -0,0 +1,17 @@
1
+ ezKit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ ezKit/bottle.py,sha256=usKK1wVaZw4_D-4VwMYmOIc8jtz4TrpM30nck59HMFw,180178
3
+ ezKit/bottle_extensions.py,sha256=LQikCbbYZBAa4AcihvrTvixWHHMY7OjCBsT02PqWMMM,1129
4
+ ezKit/cipher.py,sha256=uVUzeoYg5ZPJLpqg2wLst-7vfdDGmqWKka9Oyi0WrCA,2883
5
+ ezKit/database.py,sha256=awTEdD4aqevyJg5LPBHmUPrOKweqzJ2Ezqqx0_xgUDA,6859
6
+ ezKit/http.py,sha256=cyS18-TW9f7p1OaiJ4nnVsKZT8Ghy-8OewkfYm8yesw,1790
7
+ ezKit/mongo.py,sha256=P6WTwFRxaaHixJK_PyKlOfPHkeJRxxrNLV77xy5LVBQ,2048
8
+ ezKit/redis.py,sha256=HVofsLdSBbBHAR-veumsrjTwZQspRDy2FXNR6MDCCXs,1972
9
+ ezKit/sendemail.py,sha256=Qxu4XQkHRPeX6FSJdzj-MXND9NyKcgHljbafNmy34H0,8243
10
+ ezKit/token.py,sha256=9CAZhPdXiRiWoOIeWmP0q6L3j1zQAv4YcVWH95Tjefs,1755
11
+ ezKit/utils.py,sha256=an7joZy_EEpYfN8zBtEWAnhP0YXYfPieabsK_HAxXl4,48921
12
+ ezKit/xftp.py,sha256=7BABr-gjxZxK2UXoW9XxN76i1HdubeaomYlYMqRurHE,7770
13
+ ezKit-1.8.0.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
14
+ ezKit-1.8.0.dist-info/METADATA,sha256=CNkyQ01iJgdaiUFUFq2n8aL9MBXtxduFVK6ZBpJrW68,192
15
+ ezKit-1.8.0.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
16
+ ezKit-1.8.0.dist-info/top_level.txt,sha256=aYLB_1WODsqNTsTFWcKP-BN0KCTKcV-HZJ4zlHkCFw8,6
17
+ ezKit-1.8.0.dist-info/RECORD,,