lesscode-flask 0.0.79__tar.gz → 0.0.81__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.
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/PKG-INFO +1 -1
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/__init__.py +16 -8
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/app.py +4 -1
- lesscode_flask-0.0.81/lesscode_flask/export_data/data_download_handler.py +94 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/setting/__init__.py +1 -1
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/setup/__init__.py +38 -1
- lesscode_flask-0.0.81/lesscode_flask/utils/oss/__init__.py +0 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask.egg-info/PKG-INFO +1 -1
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask.egg-info/SOURCES.txt +2 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/README.md +0 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/db/__init__.py +0 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/db/datasource.py +0 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/db/executor.py +0 -0
- {lesscode_flask-0.0.79/lesscode_flask/utils/decorator → lesscode_flask-0.0.81/lesscode_flask/export_data}/__init__.py +0 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/log/access_log_handler.py +0 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/model/access_log.py +0 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/model/auth_client.py +0 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/model/auth_permission.py +0 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/model/base_model.py +0 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/model/parameterized_query.py +0 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/model/response_result.py +0 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/model/user.py +0 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/service/access_log_service.py +0 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/service/auth_client_service.py +0 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/service/auth_permission_service.py +0 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/service/authentication_service.py +0 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/service/base_service.py +0 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/utils/__init__.py +0 -0
- {lesscode_flask-0.0.79/lesscode_flask/utils/oss → lesscode_flask-0.0.81/lesscode_flask/utils/decorator}/__init__.py +0 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/utils/decorator/cache.py +0 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/utils/decorator/swagger.py +0 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/utils/file/file_exporter.py +0 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/utils/helpers.py +0 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/utils/json/NotSortJSONProvider.py +0 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/utils/oss/ks3_oss.py +0 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/utils/redis/redis_helper.py +0 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/utils/request/request.py +0 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/utils/swagger/swagger_template.py +0 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/utils/swagger/swagger_util.py +0 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/utils/thread/thread_utils.py +0 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/wsgi.py +0 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask.egg-info/dependency_links.txt +0 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask.egg-info/requires.txt +0 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask.egg-info/top_level.txt +0 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/redash/query_runner/__init__.py +0 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/redash/query_runner/clickhouse.py +0 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/redash/query_runner/elasticsearch.py +0 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/redash/query_runner/kingbase.py +0 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/redash/query_runner/mysql.py +0 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/redash/query_runner/pg.py +0 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/redash/settings/__init__.py +0 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/redash/settings/helpers.py +0 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/redash/utils/__init__.py +0 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/redash/utils/requests_session.py +0 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/setup.cfg +0 -0
- {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/setup.py +0 -0
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
__version__ = '0.0.
|
|
1
|
+
__version__ = '0.0.81'
|
|
2
2
|
|
|
3
3
|
import functools
|
|
4
4
|
import logging
|
|
5
5
|
import traceback
|
|
6
6
|
|
|
7
7
|
from flask import Blueprint
|
|
8
|
+
|
|
9
|
+
from lesscode_flask.export_data.data_download_handler import download_func_dict
|
|
8
10
|
from lesscode_flask.utils.decorator.cache import deal_cache
|
|
9
11
|
|
|
10
12
|
|
|
@@ -15,11 +17,13 @@ class SQ_Blueprint(Blueprint):
|
|
|
15
17
|
super().__init__(name=name, url_prefix=url_prefix, **kwargs)
|
|
16
18
|
|
|
17
19
|
def decorator_handler(self, title: str, url: str = None, cache_enalbe: bool = False, cache_ex: int = 3600 * 10,
|
|
18
|
-
content_type: str = "json", methods=['POST']):
|
|
20
|
+
content_type: str = "json", methods=['POST'], export_enable: bool = False):
|
|
19
21
|
options = {"methods": methods}
|
|
20
22
|
|
|
21
23
|
def decorator(func):
|
|
22
24
|
path = url if url else "/{}".format(func.__name__)
|
|
25
|
+
download_key = func.__module__ + "." + func.__name__
|
|
26
|
+
download_func_dict[download_key] = func
|
|
23
27
|
|
|
24
28
|
@functools.wraps(func)
|
|
25
29
|
def wrapper(*args, **kwargs):
|
|
@@ -31,9 +35,13 @@ class SQ_Blueprint(Blueprint):
|
|
|
31
35
|
except Exception as e:
|
|
32
36
|
logging.error(traceback.format_exc())
|
|
33
37
|
data = func(*args, **kwargs)
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
38
|
+
else:
|
|
39
|
+
# 如果没有开启缓存,或者缓存未命中,则执行原始函数
|
|
40
|
+
data = func(*args, **kwargs)
|
|
41
|
+
if isinstance(data, dict) and export_enable:
|
|
42
|
+
data.update({
|
|
43
|
+
"download_key": download_key
|
|
44
|
+
})
|
|
37
45
|
return data
|
|
38
46
|
|
|
39
47
|
wrapper._title = title
|
|
@@ -45,11 +53,11 @@ class SQ_Blueprint(Blueprint):
|
|
|
45
53
|
return decorator
|
|
46
54
|
|
|
47
55
|
def post_route(self, title: str, url: str = None, cache_enalbe: bool = False, cache_ex: int = 3600 * 10,
|
|
48
|
-
content_type: str = "json", methods=['POST']):
|
|
49
|
-
decorator = self.decorator_handler(title, url, cache_enalbe, cache_ex, content_type, methods)
|
|
56
|
+
content_type: str = "json", methods=['POST'], export_enable: bool = False):
|
|
57
|
+
decorator = self.decorator_handler(title, url, cache_enalbe, cache_ex, content_type, methods, export_enable)
|
|
50
58
|
return decorator
|
|
51
59
|
|
|
52
60
|
def get_route(self, title: str, url: str = None, cache_enalbe: bool = False, cache_ex: int = 3600 * 10,
|
|
53
61
|
content_type: str = "json", methods=['GET']):
|
|
54
62
|
decorator = self.decorator_handler(title, url, cache_enalbe, cache_ex, content_type, methods)
|
|
55
|
-
return decorator
|
|
63
|
+
return decorator
|
|
@@ -16,7 +16,7 @@ from werkzeug.middleware.proxy_fix import ProxyFix
|
|
|
16
16
|
|
|
17
17
|
from lesscode_flask.model.response_result import ResponseResult
|
|
18
18
|
from lesscode_flask.setup import setup_blueprint, setup_logging, setup_query_runner, setup_swagger, setup_sql_alchemy, \
|
|
19
|
-
setup_redis, setup_login_manager, setup_resource_register
|
|
19
|
+
setup_redis, setup_login_manager, setup_resource_register, setup_data_download
|
|
20
20
|
from lesscode_flask.utils.helpers import inject_args, generate_uuid, app_config
|
|
21
21
|
from lesscode_flask.utils.json.NotSortJSONProvider import NotSortJSONProvider
|
|
22
22
|
from lesscode_flask.utils.redis.redis_helper import RedisHelper
|
|
@@ -147,6 +147,9 @@ class Lesscoder(Flask):
|
|
|
147
147
|
for blueprint_name, blueprint in blueprint_map.items():
|
|
148
148
|
self.register_blueprint(blueprint)
|
|
149
149
|
setup_resource_register(self)
|
|
150
|
+
setup_data_download(self)
|
|
151
|
+
# setup_static(self)
|
|
152
|
+
|
|
150
153
|
|
|
151
154
|
@staticmethod
|
|
152
155
|
def handle_exception(e):
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import inspect
|
|
2
|
+
import logging
|
|
3
|
+
import os
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
|
|
6
|
+
from flask import current_app
|
|
7
|
+
from openpyxl import Workbook
|
|
8
|
+
from openpyxl.styles import Alignment, Font
|
|
9
|
+
|
|
10
|
+
download_func_dict = {}
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def upload_result_url(data_list: list, file_name: str = None, describe_text: str = None):
|
|
14
|
+
# 创建一个工作簿和一个工作表
|
|
15
|
+
wb = Workbook()
|
|
16
|
+
ws = wb.active
|
|
17
|
+
# 将数据写入工作表
|
|
18
|
+
for row in data_list:
|
|
19
|
+
row = [",".join(list(set(x))) if type(x) == list else str(x) for x in row]
|
|
20
|
+
ws.append(row)
|
|
21
|
+
# 自适应列宽
|
|
22
|
+
for index, col in enumerate(ws.columns):
|
|
23
|
+
max_length = max([len(str(data[index])) for data in data_list])
|
|
24
|
+
column = col[0].column_letter # 获取列字母
|
|
25
|
+
adjusted_width = min(60, (max_length * 2 + 2)) # 添加一些额外的空白以防止截断
|
|
26
|
+
ws.column_dimensions[column].width = adjusted_width
|
|
27
|
+
if describe_text:
|
|
28
|
+
ws.insert_rows(1, amount=1)
|
|
29
|
+
ws.merge_cells(f"A1:{column}1") # 合并第1行单元格
|
|
30
|
+
ws["A1"] = describe_text
|
|
31
|
+
# img = Image("./static/img/img.png")
|
|
32
|
+
# ws.add_image(img, "A1")
|
|
33
|
+
# 保存工作簿
|
|
34
|
+
file_key = f'{file_name}-{datetime.now().strftime("%Y%m%d%H%M%S")}.xlsx'
|
|
35
|
+
path = f'{current_app.config.get("STATIC_PATH", "")}/data_download/{file_key}'
|
|
36
|
+
wb.save(path)
|
|
37
|
+
clear_excel_task()
|
|
38
|
+
return f'{current_app.config.get("OUTSIDE_SCREEN_IP")}/static/data_download/{file_key}', file_key
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def clear_excel_task():
|
|
42
|
+
delay = 3600 * 24
|
|
43
|
+
excel_path = os.path.join(current_app.config.get("STATIC_PATH", ""), "data_download")
|
|
44
|
+
files = get_files(excel_path)
|
|
45
|
+
for f in files:
|
|
46
|
+
now = datetime.now().timestamp()
|
|
47
|
+
if os.path.exists(f):
|
|
48
|
+
file_time = os.path.getctime(f)
|
|
49
|
+
if now - file_time > delay:
|
|
50
|
+
os.remove(f)
|
|
51
|
+
logging.info(f'delete file({f}) success')
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def get_files(path):
|
|
55
|
+
files = []
|
|
56
|
+
fs = os.listdir(path)
|
|
57
|
+
for f in fs:
|
|
58
|
+
file_path = f'{path}/{f}'
|
|
59
|
+
if os.path.isfile(file_path):
|
|
60
|
+
if ".gitkeep" not in file_path:
|
|
61
|
+
files.append(file_path)
|
|
62
|
+
else:
|
|
63
|
+
ft = get_files(file_path)
|
|
64
|
+
files.extend(ft)
|
|
65
|
+
return files
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def format_to_table_download(table_head_list=None, table_body_list=None):
|
|
69
|
+
if not table_head_list:
|
|
70
|
+
table_head_list = table_body_list["columns"]
|
|
71
|
+
table_body_list = table_body_list["dataSource"]
|
|
72
|
+
data_index_list = [one['dataIndex'] for one in table_head_list]
|
|
73
|
+
title_list = [one['title'] for one in table_head_list]
|
|
74
|
+
all_data_list = [title_list]
|
|
75
|
+
for one in table_body_list:
|
|
76
|
+
all_data_list.append([one.get(dataIndex, "") for dataIndex in data_index_list])
|
|
77
|
+
# table_head_map_dict = {one['dataIndex']: one['title'] for one in table_head_list}
|
|
78
|
+
#
|
|
79
|
+
# sta_map_dict = {}
|
|
80
|
+
# for one in table_body_list:
|
|
81
|
+
# for tag in data_index_list:
|
|
82
|
+
# if tag not in sta_map_dict:
|
|
83
|
+
# sta_map_dict[tag] = [one.get(tag, "")]
|
|
84
|
+
# else:
|
|
85
|
+
# sta_map_dict[tag].append(one.get(tag, ""))
|
|
86
|
+
# sta_map_dict = {table_head_map_dict[k]: v for k, v in sta_map_dict.items()}
|
|
87
|
+
return all_data_list
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def convert_page(offset: int = None, size: int = None, page_num: int = None, page_size: int = None):
|
|
91
|
+
if not offset and not size:
|
|
92
|
+
offset = (page_num - 1) * page_size
|
|
93
|
+
size = page_size
|
|
94
|
+
return offset, size
|
|
@@ -61,7 +61,7 @@ class BaseConfig:
|
|
|
61
61
|
# 应用运行根路径
|
|
62
62
|
# APPLICATION_PATH: str = f"{os.path.abspath(os.path.dirname(sys.argv[0]))}"
|
|
63
63
|
# # 静态资源目录
|
|
64
|
-
STATIC_PATH: str = f"{os.path.abspath(os.path.dirname(sys.argv[0]))}"
|
|
64
|
+
STATIC_PATH: str = os.path.join(f"{os.path.abspath(os.path.dirname(sys.argv[0]))}", "static")
|
|
65
65
|
|
|
66
66
|
SECRET_KEY = "423ad5ef841bbd073b415e4ba4136d7c94cac3f5e9bfeec1a21da35cd9ea6b46"
|
|
67
67
|
|
|
@@ -4,9 +4,11 @@ from datetime import datetime
|
|
|
4
4
|
from importlib import import_module
|
|
5
5
|
from logging.handlers import TimedRotatingFileHandler
|
|
6
6
|
|
|
7
|
-
from flask import current_app
|
|
7
|
+
from flask import current_app, send_from_directory
|
|
8
8
|
|
|
9
|
+
from lesscode_flask import download_func_dict
|
|
9
10
|
from lesscode_flask.db import db
|
|
11
|
+
from lesscode_flask.export_data.data_download_handler import convert_page, format_to_table_download, upload_result_url
|
|
10
12
|
from lesscode_flask.log.access_log_handler import AccessLogHandler
|
|
11
13
|
from lesscode_flask.model.user import AnonymousUser
|
|
12
14
|
from lesscode_flask.service.authentication_service import get_token_user, get_api_user, get_gateway_user
|
|
@@ -400,3 +402,38 @@ def setup_resource_register(app):
|
|
|
400
402
|
return res
|
|
401
403
|
except Exception as e:
|
|
402
404
|
raise e
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
# def setup_static(app):
|
|
408
|
+
# @app.route("/static/<filename>")
|
|
409
|
+
# def static_resource(filename, **kwargs):
|
|
410
|
+
# """
|
|
411
|
+
# 方法说明
|
|
412
|
+
# :param download_key:
|
|
413
|
+
# :return:
|
|
414
|
+
# """
|
|
415
|
+
# return send_from_directory('static', filename)
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
def setup_data_download(app):
|
|
419
|
+
@app.route(f"{current_app.config.get('ROUTE_PREFIX')}/download/data_download", methods=['POST'])
|
|
420
|
+
def data_download(download_key, params, column_list=None, page_size=10, file_name="", page_number=1, offset=0,
|
|
421
|
+
size=10):
|
|
422
|
+
"""
|
|
423
|
+
方法说明
|
|
424
|
+
:param download_key:
|
|
425
|
+
:return:
|
|
426
|
+
"""
|
|
427
|
+
if not file_name:
|
|
428
|
+
file_name = "data_export"
|
|
429
|
+
func = download_func_dict.get(download_key, {})
|
|
430
|
+
offset, size = convert_page(offset, size, page_number, page_size)
|
|
431
|
+
request_param = {"offset": offset, "size": size}
|
|
432
|
+
signature = inspect.signature(func)
|
|
433
|
+
for parameter_name, parameter in signature.parameters.items():
|
|
434
|
+
if params.get(parameter_name):
|
|
435
|
+
request_param[parameter_name] = params[parameter_name]
|
|
436
|
+
table_body_list = func(**request_param)
|
|
437
|
+
sta_map_dict = format_to_table_download(table_head_list=column_list, table_body_list=table_body_list)
|
|
438
|
+
url, file_key = upload_result_url(sta_map_dict, file_name=file_name)
|
|
439
|
+
return url
|
|
File without changes
|
|
@@ -11,6 +11,8 @@ lesscode_flask.egg-info/top_level.txt
|
|
|
11
11
|
lesscode_flask/db/__init__.py
|
|
12
12
|
lesscode_flask/db/datasource.py
|
|
13
13
|
lesscode_flask/db/executor.py
|
|
14
|
+
lesscode_flask/export_data/__init__.py
|
|
15
|
+
lesscode_flask/export_data/data_download_handler.py
|
|
14
16
|
lesscode_flask/log/access_log_handler.py
|
|
15
17
|
lesscode_flask/model/access_log.py
|
|
16
18
|
lesscode_flask/model/auth_client.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/service/access_log_service.py
RENAMED
|
File without changes
|
{lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/service/auth_client_service.py
RENAMED
|
File without changes
|
{lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/service/auth_permission_service.py
RENAMED
|
File without changes
|
{lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/service/authentication_service.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/utils/json/NotSortJSONProvider.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/utils/swagger/swagger_template.py
RENAMED
|
File without changes
|
{lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/utils/swagger/swagger_util.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|