gomyck-tools 1.4.2__py3-none-any.whl → 1.4.4__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.
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: UTF-8 -*-
3
+ __author__ = 'haoyang'
4
+ __date__ = '2025/7/16 14:19'
5
+
6
+ """
7
+ config = load_config("application.ini")
8
+ print(config)
9
+ print(config.base.app_name)
10
+ print(config.base.version)
11
+ """
12
+ from configparser import ConfigParser
13
+
14
+ cache = {}
15
+
16
+ class AttrNoneNamespace:
17
+ def __init__(self):
18
+ pass
19
+ def __setattr__(self, key, value):
20
+ super().__setattr__(key, value)
21
+ def __getattr__(self, item):
22
+ return None
23
+
24
+ def _convert_value(value: str):
25
+ val = value.strip()
26
+ if val.lower() in ('true', 'yes', 'on'):
27
+ return True
28
+ if val.lower() in ('false', 'no', 'off'):
29
+ return False
30
+ if val.isdigit():
31
+ return int(val)
32
+ try:
33
+ return float(val)
34
+ except ValueError:
35
+ return val
36
+
37
+ def _config_to_object(config: ConfigParser):
38
+ result = AttrNoneNamespace()
39
+ for section in config.sections():
40
+ section_obj = AttrNoneNamespace()
41
+ for key, value in config.items(section):
42
+ setattr(section_obj, key, _convert_value(value))
43
+ setattr(result, section, section_obj)
44
+ return result
45
+
46
+ def load_config(file_path):
47
+ if file_path in cache: return cache[file_path]
48
+ config = ConfigParser()
49
+ config.read(file_path)
50
+ cf = _config_to_object(config)
51
+ cache[file_path] = cf
52
+ return cf
@@ -1,3 +1,4 @@
1
+ import base64
1
2
  from io import BytesIO
2
3
 
3
4
  from PIL import Image
@@ -25,3 +26,10 @@ def change_color(image_path, area=None, rgb_color=None):
25
26
  img.save(img_bytes, format='JPEG')
26
27
  img_binary = img_bytes.getvalue()
27
28
  return img_binary
29
+
30
+
31
+ def img2b64(img: Image, fmt="PNG"):
32
+ buf = BytesIO()
33
+ img.save(buf, format=fmt.upper())
34
+ return base64.b64encode(buf.getvalue()).decode("utf-8")
35
+
ctools/util/jb_cut.py ADDED
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: UTF-8 -*-
3
+ __author__ = 'haoyang'
4
+ __date__ = '2025/7/15 13:08'
5
+
6
+ import sys
7
+
8
+ import jieba
9
+ from jieba import posseg as pseg
10
+
11
+ jqfx_exclude = ('ul', 'uj', 'uz', 'a', 'c', 'm', 'f', 'ad', 'an', 'r', 'q', 'u', 't', 'd', 'p', 'x')
12
+
13
+ def add_dict(dic_word: str = None, dic_path: str = None):
14
+ """
15
+ 添加自定义词库(自定义词库添加之后, 如果不适用全模式切词, 有时也不好使, 因为权重没有默认的高)
16
+ :param dic_word: 一个单词
17
+ :param dic_path: 单词表文件地址
18
+ 单词表文件格式:
19
+ 单词 词频 标签
20
+ 单词1 3 i
21
+ 单词2 3 i
22
+ 单词3 3 i
23
+ """
24
+ if dic_word: jieba.add_word(dic_word)
25
+ if dic_path: jieba.load_userdict(dic_path)
26
+
27
+ def add_freq(word: ()):
28
+ """
29
+ 添加词频
30
+ :param word: 一个单词
31
+ """
32
+ jieba.suggest_freq(word, True)
33
+
34
+ def get_declare_type_word(word: str, word_flag=(), use_paddle=False, exclude_flag="x"):
35
+ #import paddle
36
+ #paddle.enable_static()
37
+ #sys.stdout = sys.__stdout__
38
+ #sys.stderr = sys.__stderr__
39
+ """
40
+ 获取声明类型的单词
41
+ :param word: 单词
42
+ :param word_flag: 标签
43
+ :param use_paddle: 是否使用 paddle
44
+ :param exclude_flag: 排除的标签
45
+ :return: 筛选之后的单词(数组)
46
+ """
47
+ # linux 可以开放下面的语句, 并发执行分词, windows 不支持
48
+ # if platform.system() == 'Linux': jieba.enable_parallel(4)
49
+ ret = []
50
+ for w, flag in pseg.cut(word, use_paddle=use_paddle):
51
+ if (flag in word_flag or len(word_flag) == 0) and flag not in exclude_flag:
52
+ ret.append((w, flag))
53
+ return ret
@@ -5,74 +5,99 @@ from functools import wraps
5
5
  import bottle
6
6
  from bottle import response, Bottle, request
7
7
 
8
+ from ctools import call
8
9
  from ctools.dict_wrapper import DictWrapper
9
10
  from ctools.sys_log import flog as log
11
+ from ctools.util.cklock import try_lock
10
12
  from ctools.web import ctoken
11
13
  from ctools.web.api_result import R
12
14
 
13
15
  bottle.BaseRequest.MEMFILE_MAX = 1024 * 1024 * 50
14
16
  func_has_params = {}
15
-
17
+ app_cache = {}
16
18
 
17
19
  class GlobalState:
18
20
  lock = threading.Lock()
19
- withOutLoginURI = [
21
+ withOutLoginURI = {
20
22
  '/',
21
23
  '/index',
22
24
  '/login',
23
25
  '/favicon.ico',
24
- ]
25
- allowRemoteCallURI = [
26
-
27
- ]
26
+ }
27
+ allowRemoteCallURI = set()
28
+ auth_ignore_func = set()
28
29
  token = {}
29
30
  interceptors = []
30
31
 
31
-
32
- def init_app(context_path=None):
33
- app = Bottle()
34
- app.context_path = context_path
35
-
36
- @app.hook('before_request')
37
- def before_request():
38
- for interceptor in GlobalState.interceptors:
39
- res: R = interceptor['func']()
40
- if res.code != 200: bottle.abort(res.code, res.message)
41
-
42
- @app.error(401)
43
- def unauthorized(error):
44
- response.status = 401
45
- log.error("系统未授权: {} {} {}".format(error.body, request.method, request.fullpath))
46
- return R.error(resp=R.Code.cus_code(401, "系统未授权! {}".format(error.body)))
47
-
48
- @app.error(403)
49
- def unauthorized(error):
50
- response.status = 403
51
- log.error("访问受限: {} {} {}".format(error.body, request.method, request.fullpath))
52
- return R.error(resp=R.Code.cus_code(403, "访问受限: {}".format(error.body)))
53
-
54
- @app.error(404)
55
- def not_found(error):
56
- response.status = 404
57
- log.error("404 not found : {} {} {}".format(error.body, request.method, request.fullpath))
58
- return R.error(resp=R.Code.cus_code(404, "资源未找到: {}".format(error.body)))
59
-
60
- @app.error(405)
61
- def method_not_allow(error):
62
- response.status = 405
63
- log.error("请求方法错误: {} {} {}".format(error.status_line, request.method, request.fullpath))
64
- return R.error(resp=R.Code.cus_code(405, '请求方法错误: {}'.format(error.status_line)))
65
-
66
- @app.error(500)
67
- def internal_error(error):
68
- response.status = 500
69
- log.error("系统发生错误: {} {} {}".format(error.body, request.method, request.fullpath))
70
- return R.error(msg='系统发生错误: {}'.format(error.exception))
71
-
72
- @app.hook('after_request')
73
- def after_request():
74
- enable_cors()
75
-
32
+ def join_path(*parts):
33
+ """拼接 url"""
34
+ cleaned_parts = [p.strip('/') for p in parts if p and p.strip('/')]
35
+ return '/' + '/'.join(cleaned_parts)
36
+
37
+ @call.once
38
+ def cache_white_list(app):
39
+ """缓存白名单"""
40
+ for route in app.routes:
41
+ real_func = route.config.get('mountpoint.target')
42
+ if not real_func: continue
43
+ for method, routes in real_func.router.static.items():
44
+ for path, tuples in routes.items():
45
+ req_func = inspect.getmodule(tuples[0].callback).__name__ + "." + tuples[0].callback.__name__
46
+ if req_func in GlobalState.auth_ignore_func:
47
+ print("add white list: {}".format(join_path(app.context_path, real_func.context_path, path)))
48
+ GlobalState.withOutLoginURI.add(join_path(app.context_path, real_func.context_path, path))
49
+
50
+ def init_app(context_path="/", main_app=False):
51
+ with try_lock(block=True):
52
+ cache_app = app_cache.get(context_path)
53
+ if cache_app: return cache_app
54
+ app = Bottle()
55
+ app_cache[context_path] = app
56
+ app.context_path = context_path if context_path else "/"
57
+
58
+ def init_main_app():
59
+ @app.hook('before_request')
60
+ def before_request():
61
+ if request.path.startswith('/static') or request.path in GlobalState.withOutLoginURI: return
62
+ for interceptor in GlobalState.interceptors:
63
+ res: R = interceptor['func']()
64
+ if res.code != 200: bottle.abort(res.code, res.message)
65
+
66
+ @app.error(401)
67
+ def unauthorized(error):
68
+ response.status = 401
69
+ log.error("系统未授权: {} {} {}".format(error.body, request.method, request.fullpath))
70
+ return R.error(resp=R.Code.cus_code(401, "系统未授权! {}".format(error.body)))
71
+
72
+ @app.error(403)
73
+ def unauthorized(error):
74
+ response.status = 403
75
+ log.error("访问受限: {} {} {}".format(error.body, request.method, request.fullpath))
76
+ return R.error(resp=R.Code.cus_code(403, "访问受限: {}".format(error.body)))
77
+
78
+ @app.error(404)
79
+ def not_found(error):
80
+ response.status = 404
81
+ log.error("404 not found : {} {} {}".format(error.body, request.method, request.fullpath))
82
+ return R.error(resp=R.Code.cus_code(404, "资源未找到: {}".format(error.body)))
83
+
84
+ @app.error(405)
85
+ def method_not_allow(error):
86
+ response.status = 405
87
+ log.error("请求方法错误: {} {} {}".format(error.status_line, request.method, request.fullpath))
88
+ return R.error(resp=R.Code.cus_code(405, '请求方法错误: {}'.format(error.status_line)))
89
+
90
+ @app.error(500)
91
+ def internal_error(error):
92
+ response.status = 500
93
+ log.error("系统发生错误: {} {} {}".format(error.body, request.method, request.fullpath))
94
+ return R.error(msg='系统发生错误: {}'.format(error.exception))
95
+
96
+ @app.hook('after_request')
97
+ def after_request():
98
+ enable_cors()
99
+
100
+ if main_app: init_main_app()
76
101
  app.install(params_resolve)
77
102
  return app
78
103
 
@@ -88,27 +113,45 @@ def enable_cors():
88
113
  # annotation
89
114
  def before_intercept(order=0):
90
115
  def decorator(func):
116
+ for interceptor in GlobalState.interceptors:
117
+ if interceptor['func'].__name__ == func.__name__:
118
+ log.info("duplicate interceptor: {}".format(func.__name__))
119
+ return
91
120
  log.info("add before interceptor: {}".format(func.__name__))
92
121
  GlobalState.interceptors.append({'order': order, 'func': func})
93
122
  GlobalState.interceptors = sorted(GlobalState.interceptors, key=lambda x: x['order'])
94
123
 
95
124
  return decorator
96
125
 
126
+ # annotation
127
+ def auth_ignore(func):
128
+ """忽略登录验证的接口"""
129
+ ignore_req_func = inspect.getmodule(func).__name__ + "." + func.__name__
130
+ if ignore_req_func in GlobalState.auth_ignore_func: raise Exception("duplicate ignore func: {}".format(ignore_req_func))
131
+ GlobalState.auth_ignore_func.add(ignore_req_func)
132
+ @wraps(func)
133
+ def decorated(*args, **kwargs):
134
+ return func(*args, **kwargs)
135
+ return decorated
97
136
 
98
137
  # annotation
99
138
  def rule(key):
100
139
  def return_func(func):
101
140
  @wraps(func)
102
141
  def decorated(*args, **kwargs):
103
- # if GlobalState.licenseInfo is not None and key not in GlobalState.licenseInfo.access_module:
104
- # log.error("系统未授权! {} {}".format(request.fullpath, '当前请求的模块未授权!请联系管理员!'))
105
- # return R.error(resp=R.Code.cus_code(9999, "系统未授权! {}".format('当前请求的模块未授权!请联系管理员!')))
106
- return func(*args, **kwargs)
107
-
142
+ rules = ctoken.get_token_attr("rules") or []
143
+ if _match_rule_by_prefix(key, rules):
144
+ return func(*args, **kwargs)
145
+ else:
146
+ return R.error("权限不足, 请联系管理员: {}".format(key))
108
147
  return decorated
109
-
110
148
  return return_func
111
149
 
150
+ def _match_rule_by_prefix(key, rules):
151
+ for r in rules:
152
+ if key.startswith(r):
153
+ return True
154
+ return False
112
155
 
113
156
  # annotation or plugins, has auto install, don't need to call
114
157
  def params_resolve(func):
@@ -124,45 +167,59 @@ def params_resolve(func):
124
167
  return func(*args, **kwargs)
125
168
  else:
126
169
  func_has_params[request.fullpath] = True
127
- if request.method == 'GET':
170
+ if request.method == 'GET' or request.method == 'DELETE':
128
171
  queryStr = request.query.decode('utf-8')
129
172
  page_info = PageInfo(
130
173
  page_size=10 if request.headers.get('page_size') is None else int(request.headers.get('page_size')),
131
174
  page_index=1 if request.headers.get('page_index') is None else int(request.headers.get('page_index'))
132
175
  )
176
+ queryStr = auto_exchange(func, queryStr)
133
177
  queryStr.page_info = page_info
134
178
  return func(params=queryStr, *args, **kwargs)
135
- elif request.method == 'POST':
179
+ elif request.method == 'POST' or request.method == 'PUT':
136
180
  query_params = request.query.decode('utf-8')
137
181
  content_type = request.get_header('content-type')
138
182
  if content_type == 'application/json':
139
183
  params = request.json or {}
140
184
  dict_wrapper = DictWrapper(params)
141
185
  dict_wrapper.update(query_params.dict)
142
- return func(params=dict_wrapper, *args, **kwargs)
186
+ return func(params=auto_exchange(func, dict_wrapper), *args, **kwargs)
143
187
  elif 'multipart/form-data' in content_type:
144
188
  form_data = request.forms.decode()
145
189
  form_files = request.files.decode()
146
190
  dict_wrapper = DictWrapper(form_data)
147
191
  dict_wrapper.update(query_params.dict)
148
192
  dict_wrapper.files = form_files
149
- return func(params=dict_wrapper, *args, **kwargs)
193
+ return func(params=auto_exchange(func, dict_wrapper), *args, **kwargs)
150
194
  elif 'application/x-www-form-urlencoded' in content_type:
151
195
  params = request.forms.decode()
152
196
  dict_wrapper = DictWrapper(params.dict)
153
197
  dict_wrapper.update(query_params.dict)
154
- return func(params=dict_wrapper, *args, **kwargs)
198
+ return func(params=auto_exchange(func, dict_wrapper), *args, **kwargs)
155
199
  elif 'text/plain' in content_type:
156
200
  params = request.body.read().decode('utf-8')
157
201
  dict_wrapper = DictWrapper({'body': params})
158
202
  dict_wrapper.update(query_params.dict)
159
- return func(params=dict_wrapper, *args, **kwargs)
203
+ return func(params=auto_exchange(func, dict_wrapper), *args, **kwargs)
160
204
  else:
161
205
  return func(*args, **kwargs)
162
206
 
163
207
  return decorated
164
208
 
165
-
209
+ # 自动转换参数类型
210
+ def auto_exchange(func, dict_wrapper):
211
+ model_class = func.__annotations__.get('params')
212
+ if model_class:
213
+ try:
214
+ model_instance = model_class(**dict_wrapper)
215
+ return model_instance
216
+ except Exception as e:
217
+ log.exception(e)
218
+ return dict_wrapper
219
+ else:
220
+ return dict_wrapper
221
+
222
+ # 分页信息对象
166
223
  class PageInfo:
167
224
  def __init__(self, page_size, page_index):
168
225
  self.page_size = page_size
@@ -170,13 +227,7 @@ class PageInfo:
170
227
 
171
228
 
172
229
  # 通用的鉴权方法
173
- def common_auth_verify(aes_key):
174
- if request.path.startswith('/static') or request.path in GlobalState.withOutLoginURI:
175
- return R.ok(to_json_str=False)
176
- auth_token = request.get_header('Authorization')
177
- if auth_token is None:
178
- auth_token = request.get_cookie('Authorization')
179
- payload = ctoken.get_payload(auth_token, aes_key)
180
- if payload:
181
- return R.ok(to_json_str=False)
230
+ def common_auth_verify() -> R:
231
+ valid = ctoken.is_valid()
232
+ if valid: return R.ok(to_json_str=False)
182
233
  return R.error(resp=R.Code.cus_code(401, "请登录!"), to_json_str=False)
@@ -5,48 +5,36 @@ from wsgiref.simple_server import WSGIServer, WSGIRequestHandler, make_server
5
5
  from bottle import ServerAdapter, Bottle, template, static_file, abort, redirect, response
6
6
 
7
7
  from ctools import sys_info
8
+ from ctools.pkg.dynamic_imp import load_modules_from_package
9
+ from ctools.web.bottle_web_base import cache_white_list
8
10
 
9
- """
10
- module_names = list(globals().keys())
11
- def get_modules():
12
- mods = []
13
- for modname in module_names:
14
- if modname == 'base' or modname == 'online' or modname.startswith('__') or modname == 'importlib': continue
15
- module = globals()[modname]
16
- mods.append(module)
17
- return mods
18
-
19
- def get_ws_modules():
20
- from . import websocket
21
- return [websocket]
22
- """
23
11
 
24
12
  """
25
- from ctools.web import bottle_web_base, ctoken, bottle_webserver
26
- from ctools.web.api_result import R
13
+ import controllers
14
+ from ctools import patch
15
+ from ctools.database import database
16
+ from ctools.util.config_util import load_config
17
+ from ctools.web import bottle_web_base, bottle_webserver
18
+ from key_word_cloud.db_core.db_init import init_partitions
19
+ from patch_manager import patch_funcs
27
20
 
28
- secret_key = "xxx"
29
- app = bottle_web_base.init_app('子模块写 context_path, 主模块就不用写任何东西')
21
+ database.init_db('postgresql://postgres:123123@192.168.xx.xx:5432/xxx', default_schema='xxx', auto_gen_table=False, echo=False)
30
22
 
31
- # 通用的鉴权方法
32
- @bottle_web_base.before_intercept(0)
33
- def token_check():
34
- return bottle_web_base.common_auth_verify(secret_key)
23
+ config = load_config('application.ini')
35
24
 
36
- @app.post('/login')
37
- def login(params):
38
- return R.ok(ctoken.gen_token({'username': 'xxx'}, secret_key, 3600))
25
+ patch.sync_version(config.base.app_name, config.base.version, patch_funcs)
26
+ init_partitions()
39
27
 
40
- @app.get('/demo')
41
- @bottle_web_base.rule('DOC:DOWNLOAD')
42
- def demo(params):
43
- print(params)
28
+ app = bottle_web_base.init_app("/api", True)
29
+
30
+ @bottle_web_base.before_intercept(0)
31
+ def token_check():
32
+ return bottle_web_base.common_auth_verify(config.base.secret_key)
44
33
 
45
34
  if __name__ == '__main__':
46
- main_app = bottle_webserver.init_bottle() # 这里可以传 APP 当做主模块, 但是 context_path 就不好使了, 上下文必须是 /
47
- main_app.mount(app.context_path, app)
48
- main_app.set_index(r'index.html')
49
- main_app.run()
35
+ main_server = bottle_webserver.init_bottle(app)
36
+ main_server.auto_mount(controllers)
37
+ main_server.run()
50
38
  """
51
39
 
52
40
  _default_port = 8888
@@ -101,6 +89,7 @@ class CBottle:
101
89
  def run(self):
102
90
  http_server = WSGIRefServer(port=self.port)
103
91
  print('Click the link below to open the service homepage %s' % '\n \t\t http://localhost:%s \n \t\t http://%s:%s' % (self.port, sys_info.get_local_ipv4(), self.port), file=sys.stderr)
92
+ cache_white_list(self.bottle)
104
93
  self.bottle.run(server=http_server, quiet=self.quiet)
105
94
 
106
95
  def set_index(self, filename='index.html', root='./', is_tpl=False, redirect_url=None, **kwargs):
@@ -120,6 +109,17 @@ class CBottle:
120
109
  if not context_path: return
121
110
  self.bottle.mount(context_path, app, **kwargs)
122
111
 
112
+ def auto_mount(self, package, exclude=None, recursive=True):
113
+ for module in load_modules_from_package(package, exclude, recursive):
114
+ if self.bottle.context_path != '/':
115
+ if module.app.context_path == '/':
116
+ ctx_path = self.bottle.context_path
117
+ else:
118
+ ctx_path = self.bottle.context_path + module.app.context_path
119
+ else:
120
+ ctx_path = module.app.context_path
121
+ print("mount: %s on %s" % (ctx_path, module.__name__))
122
+ self.bottle.mount(ctx_path, module.app)
123
123
 
124
124
  def init_bottle(app: Bottle = None, port=_default_port, quiet=False) -> CBottle:
125
125
  bottle = app or Bottle()
ctools/web/ctoken.py CHANGED
@@ -8,32 +8,96 @@ import time
8
8
  import jwt
9
9
  from bottle import request
10
10
 
11
+ from ctools import cid
11
12
  from ctools.dict_wrapper import DictWrapper
12
13
 
13
- token_header = 'Authorization'
14
14
 
15
+ class CToken:
16
+ token_audience = ["gomyck"]
17
+ token_secret_key = 'gomyck123'
18
+ token_header = 'Authorization'
15
19
 
16
- def gen_token(payload: {}, secret_key, expired: int = 3600) -> str:
17
- payload.update({'exp': time.time() + expired})
18
- return jwt.encode(payload, secret_key, algorithm='HS256')
20
+ def gen_token(userid, username, payload={}, expired: int = 3600, rules= []) -> str:
21
+ if expired and expired > 0: payload.update({'exp': time.time() + expired})
22
+ payload.update({'iss': "gomyck", 'jti': cid.get_snowflake_id_str(), 'nbf': time.time(), 'iat': time.time()})
23
+ payload.update({'rules': rules})
24
+ payload.update({'uid': userid})
25
+ payload.update({'sub': username})
26
+ payload.update({'aud': CToken.token_audience})
27
+ payload.update({'rules': rules})
28
+ return jwt.encode(payload, CToken.token_secret_key, algorithm='HS256')
19
29
 
20
-
21
- def get_payload(token, secret_key):
30
+ def get_payload(token=None):
22
31
  try:
23
- payload = jwt.decode(token, secret_key, algorithms=['HS256'])
32
+ if token is None: token = get_token()
33
+ payload = jwt.decode(token, options={"verify_signature": False}, algorithms=['HS256'])
24
34
  return DictWrapper(payload)
25
35
  except Exception as e:
26
36
  return None
27
37
 
38
+ def get_token_payload(token=None):
39
+ if token is None: token = get_token()
40
+ return get_payload(token)
41
+
42
+ def is_valid(token=None):
43
+ """
44
+ 判断token是否有效
45
+ :param token: token 信息
46
+ :return: 是否有效
47
+ """
48
+ if token is None: token = get_token()
49
+ if token is None: return False
50
+ try:
51
+ jwt.decode(token, CToken.token_secret_key, algorithms=['HS256'], audience=CToken.token_audience)
52
+ except Exception as e:
53
+ print(e)
54
+ return False
55
+ return True
56
+
57
+ def get_user_name():
58
+ """
59
+ 获取用户名称
60
+ :return: 用户ID
61
+ """
62
+ token_obj = get_token_attr("sub")
63
+ return token_obj
64
+
65
+ def get_user_id():
66
+ """
67
+ 获取用户ID
68
+ :return: 用户ID
69
+ """
70
+ token_obj = get_token_attr("uid")
71
+ return token_obj
72
+
73
+ def get_token_id():
74
+ """
75
+ 获取token id
76
+ :return: token id
77
+ """
78
+ token_obj = get_token_attr("jti")
79
+ return token_obj
28
80
 
29
- def get_token(key):
30
- return get_payload(request.get_header(token_header), key)
81
+ def get_app_flag() -> []:
82
+ """
83
+ 获取服务标识
84
+ :return: 服务标识 []
85
+ """
86
+ token_obj = get_token_attr("aud")
87
+ return token_obj
31
88
 
89
+ def get_token_attr(attr):
90
+ token_obj = get_token_payload()
91
+ return getattr(token_obj, attr, None)
32
92
 
33
- def is_valid(key):
34
- return get_payload(request.get_header(token_header), key) is not None
93
+ def get_token():
94
+ auth_token = request.get_header(CToken.token_header)
95
+ if auth_token is None:
96
+ auth_token = request.get_cookie(CToken.token_header)
97
+ return auth_token
35
98
 
36
99
  # if __name__ == '__main__':
37
- # token = gen_token({"xx": 123}, '123')
38
- # xx = get_payload(token, '123')
39
- # print(xx.xx)
100
+ # token = gen_token(123, username='xxx', expired=0)
101
+ # print(token)
102
+ # print(get_payload(token))
103
+ # print(is_valid(token))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gomyck-tools
3
- Version: 1.4.2
3
+ Version: 1.4.4
4
4
  Summary: A tools collection for python development by hao474798383
5
5
  Author-email: gomyck <hao474798383@163.com>
6
6
  License-Expression: Apache-2.0
@@ -15,7 +15,7 @@ Requires-Dist: croniter~=5.0.1
15
15
  Requires-Dist: gmssl~=3.2.2
16
16
  Requires-Dist: psutil~=6.1.0
17
17
  Requires-Dist: jsonpath_ng~=1.7.0
18
- Requires-Dist: bottle~=0.13.2
18
+ Requires-Dist: bottle~=0.13.4
19
19
  Requires-Dist: requests~=2.32.3
20
20
  Requires-Dist: urllib3~=1.26.20
21
21
  Requires-Dist: kafka-python~=2.0.2
@@ -30,15 +30,16 @@ Requires-Dist: pyjwt==2.10.1
30
30
  Requires-Dist: cryptography==44.0.2
31
31
  Requires-Dist: redis==5.2.1
32
32
  Requires-Dist: uvloop>=0.21.0
33
- Provides-Extra: db
34
- Requires-Dist: sqlalchemy>=2.0; extra == "db"
35
- Requires-Dist: asyncpg>=0.28; extra == "db"
36
- Provides-Extra: office
37
- Requires-Dist: pandas>=2.2.3; extra == "office"
38
- Requires-Dist: xlrd>=2.0.1; extra == "office"
39
- Requires-Dist: python-docx>=1.1.2; extra == "office"
40
- Provides-Extra: auto-ui
41
- Requires-Dist: pynput==1.7.7; extra == "auto-ui"
33
+ Provides-Extra: kwc
34
+ Requires-Dist: imageio>=2.37.0; extra == "kwc"
35
+ Requires-Dist: wordcloud>=1.9.4; extra == "kwc"
36
+ Requires-Dist: jieba==0.42.1; extra == "kwc"
37
+ Requires-Dist: paddlepaddle==2.6.1; extra == "kwc"
38
+ Provides-Extra: cut
39
+ Requires-Dist: jieba==0.42.1; extra == "cut"
40
+ Requires-Dist: paddlepaddle==2.6.1; extra == "cut"
41
+ Provides-Extra: ml
42
+ Requires-Dist: scikit-learn>=1.7.1; extra == "ml"
42
43
  Dynamic: license-file
43
44
 
44
45
  # Gomyck-Tools