✨ 为get_help
添加更多特性
@ -1,18 +1,50 @@
|
|||||||
|
from pathlib import Path
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
from typing import Dict, List, Tuple, Callable, Optional
|
from typing import Dict, List, Tuple, Callable, Optional
|
||||||
|
|
||||||
from PIL import Image, ImageDraw, ImageFont
|
from PIL import Image, ImageDraw, ImageFont, ImageFilter
|
||||||
|
|
||||||
from gsuid_core.data_store import get_res_path
|
from gsuid_core.data_store import get_res_path
|
||||||
from gsuid_core.utils.image.convert import convert_img
|
from gsuid_core.utils.image.convert import convert_img
|
||||||
from gsuid_core.utils.image.image_tools import (
|
from gsuid_core.utils.image.image_tools import crop_center_img
|
||||||
crop_center_img,
|
|
||||||
easy_alpha_composite,
|
|
||||||
)
|
|
||||||
|
|
||||||
from .model import PluginHelp
|
from .model import PluginHelp
|
||||||
|
|
||||||
cache: Dict[str, int] = {}
|
cache: Dict[str, int] = {}
|
||||||
|
MICON_PATH = Path(__file__).parent / 'icon'
|
||||||
|
DEFAULT_ICON = MICON_PATH / '拼图.png'
|
||||||
|
|
||||||
|
|
||||||
|
def cx(w: int, x: int) -> int:
|
||||||
|
return int((w - x) / 2)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_icon(name: str, ICON_PATH: Path) -> Optional[Image.Image]:
|
||||||
|
path = ICON_PATH / f'{name}.png'
|
||||||
|
icon = None
|
||||||
|
if path.exists():
|
||||||
|
icon = Image.open(path)
|
||||||
|
else:
|
||||||
|
for i in ICON_PATH.glob('*.png'):
|
||||||
|
if i.stem in name:
|
||||||
|
icon = Image.open(i)
|
||||||
|
break
|
||||||
|
|
||||||
|
return icon
|
||||||
|
|
||||||
|
|
||||||
|
def get_icon(name: str, ICON_PATH: Optional[Path]) -> Image.Image:
|
||||||
|
if ICON_PATH is not None:
|
||||||
|
icon = _get_icon(name, ICON_PATH)
|
||||||
|
if icon is None:
|
||||||
|
icon = _get_icon(name, MICON_PATH)
|
||||||
|
else:
|
||||||
|
icon = _get_icon(name, MICON_PATH)
|
||||||
|
|
||||||
|
if icon is None:
|
||||||
|
icon = Image.open(DEFAULT_ICON)
|
||||||
|
|
||||||
|
return icon.resize((36, 36))
|
||||||
|
|
||||||
|
|
||||||
async def get_help(
|
async def get_help(
|
||||||
@ -28,6 +60,12 @@ async def get_help(
|
|||||||
is_dark: bool = True,
|
is_dark: bool = True,
|
||||||
text_color: Tuple[int, int, int] = (250, 250, 250),
|
text_color: Tuple[int, int, int] = (250, 250, 250),
|
||||||
sub_color: Optional[Tuple[int, int, int]] = None,
|
sub_color: Optional[Tuple[int, int, int]] = None,
|
||||||
|
op_color: Optional[Tuple[int, int, int]] = None,
|
||||||
|
column: int = 5,
|
||||||
|
is_gaussian: bool = False,
|
||||||
|
gaussian_blur: int = 20,
|
||||||
|
is_icon: bool = True,
|
||||||
|
ICON_PATH: Optional[Path] = None,
|
||||||
) -> bytes:
|
) -> bytes:
|
||||||
help_path = get_res_path('help') / f'{name}.jpg'
|
help_path = get_res_path('help') / f'{name}.jpg'
|
||||||
|
|
||||||
@ -39,73 +77,112 @@ async def get_help(
|
|||||||
elif sub_color is None and not is_dark:
|
elif sub_color is None and not is_dark:
|
||||||
sub_color = tuple(x + 50 for x in text_color if x < 205)
|
sub_color = tuple(x + 50 for x in text_color if x < 205)
|
||||||
|
|
||||||
title = Image.new('RGBA', (900, 600))
|
if op_color is None and is_dark:
|
||||||
|
op_color = tuple(x - 90 for x in text_color if x > 90)
|
||||||
|
elif op_color is None and not is_dark:
|
||||||
|
op_color = tuple(x + 90 for x in text_color if x < 160)
|
||||||
|
|
||||||
|
w, h = 50 + 260 * column, 630
|
||||||
|
button_x = 260
|
||||||
|
button_y = 103 # 80
|
||||||
|
|
||||||
|
title = Image.new('RGBA', (w, 600))
|
||||||
icon = icon.resize((300, 300))
|
icon = icon.resize((300, 300))
|
||||||
title.paste(icon, (300, 89), icon)
|
|
||||||
title.paste(badge, (0, 390), badge)
|
title.paste(icon, (cx(w, 300), 89), icon)
|
||||||
|
title.paste(badge, (cx(w, 900), 390), badge)
|
||||||
badge_s = badge.resize((720, 80))
|
badge_s = badge.resize((720, 80))
|
||||||
title.paste(badge_s, (90, 480), badge_s)
|
title.paste(badge_s, (cx(w, 720), 480), badge_s)
|
||||||
title_draw = ImageDraw.Draw(title)
|
title_draw = ImageDraw.Draw(title)
|
||||||
|
|
||||||
title_draw.text((450, 440), f'{name} 帮助', text_color, font(36), 'mm')
|
title_draw.text((cx(w, 0), 440), f'{name} 帮助', text_color, font(36), 'mm')
|
||||||
title_draw.text((450, 520), sub_text, sub_color, font(26), 'mm')
|
title_draw.text((cx(w, 0), 520), sub_text, sub_color, font(26), 'mm')
|
||||||
|
|
||||||
w, h = 900, 630
|
if is_dark:
|
||||||
|
icon_mask = Image.new('RGBA', (36, 36), (255, 255, 255))
|
||||||
|
else:
|
||||||
|
icon_mask = Image.new('RGBA', (36, 36), (10, 10, 10))
|
||||||
|
|
||||||
sv_img_list: List[Image.Image] = []
|
sv_img_list: List[Image.Image] = []
|
||||||
for sv_name in help_data:
|
for sv_name in help_data:
|
||||||
tr_size = len(help_data[sv_name]['data'])
|
tr_size = len(help_data[sv_name]['data'])
|
||||||
y = 100 + ((tr_size + 3) // 4) * 80
|
y = 100 + ((tr_size + column - 1) // column) * button_y
|
||||||
h += y
|
h += y
|
||||||
sv_img = Image.new('RGBA', (900, y))
|
|
||||||
|
# 生成单个服务的背景, 依据默认column
|
||||||
|
sv_img = Image.new('RGBA', (w, y))
|
||||||
sv_data = help_data[sv_name]['data']
|
sv_data = help_data[sv_name]['data']
|
||||||
sv_desc = help_data[sv_name]['desc']
|
sv_desc = help_data[sv_name]['desc']
|
||||||
|
|
||||||
bc = deepcopy(banner)
|
bc = deepcopy(banner)
|
||||||
bc_draw = ImageDraw.Draw(bc)
|
bc_draw = ImageDraw.Draw(bc)
|
||||||
bc_draw.text((30, 25), sv_name, text_color, font(35), 'lm')
|
bc_draw.text((30, 25), sv_name, text_color, font(35), 'lm')
|
||||||
|
|
||||||
if hasattr(font, 'getsize'):
|
if hasattr(font, 'getsize'):
|
||||||
size, _ = font(35).getsize(sv_name)
|
size, _ = font(35).getsize(sv_name) # type: ignore
|
||||||
else:
|
else:
|
||||||
bbox = font(35).getbbox(sv_name)
|
bbox = font(35).getbbox(sv_name)
|
||||||
size, _ = bbox[2] - bbox[0], bbox[3] - bbox[1]
|
size, _ = bbox[2] - bbox[0], bbox[3] - bbox[1]
|
||||||
bc_draw.text((42 + size, 30), sv_desc, sub_color, font(20), 'lm')
|
|
||||||
sv_img = easy_alpha_composite(sv_img, bc, (0, 10))
|
|
||||||
# sv_img.paste(bc, (0, 10), bc)
|
|
||||||
|
|
||||||
|
bc_draw.text((42 + size, 30), sv_desc, sub_color, font(20), 'lm')
|
||||||
|
sv_img.paste(bc, (0, 10), bc)
|
||||||
|
# sv_img = easy_alpha_composite(sv_img, bc, (0, 10))
|
||||||
|
|
||||||
|
# 开始绘制各个按钮
|
||||||
for index, tr in enumerate(sv_data):
|
for index, tr in enumerate(sv_data):
|
||||||
bt = deepcopy(button)
|
bt = deepcopy(button)
|
||||||
bt_draw = ImageDraw.Draw(bt)
|
bt_draw = ImageDraw.Draw(bt)
|
||||||
if len(tr['name']) > 8:
|
|
||||||
|
# 限制长度
|
||||||
|
if is_icon and len(tr['name']) > 7:
|
||||||
tr_name = tr['name'][:5] + '..'
|
tr_name = tr['name'][:5] + '..'
|
||||||
|
elif len(tr['name']) > 10:
|
||||||
|
tr_name = tr['name'][:8] + '..'
|
||||||
else:
|
else:
|
||||||
tr_name = tr['name']
|
tr_name = tr['name']
|
||||||
|
|
||||||
bt_draw.text((105, 28), tr_name, text_color, font(26), 'mm')
|
if is_icon:
|
||||||
bt_draw.text((105, 51), tr['eg'], sub_color, font(17), 'mm')
|
f = 38
|
||||||
offset_x = 210 * (index % 4)
|
icon = get_icon(tr['name'], ICON_PATH)
|
||||||
offset_y = 80 * (index // 4)
|
bt.paste(icon_mask, (13, 17), icon)
|
||||||
sv_img = easy_alpha_composite(
|
else:
|
||||||
sv_img, bt, (26 + offset_x, 83 + offset_y)
|
f = 0
|
||||||
)
|
|
||||||
# sv_img.paste(bt, (26 + offset_x, 83 + offset_y), bt)
|
# 标题
|
||||||
|
bt_draw.text((20 + f, 28), tr_name, text_color, font(26), 'lm')
|
||||||
|
# 使用范例
|
||||||
|
bt_draw.text((20 + f, 50), tr['eg'], sub_color, font(17), 'lm')
|
||||||
|
# 简单介绍
|
||||||
|
bt_draw.text((20, 78), tr['desc'], op_color, font(16), 'lm')
|
||||||
|
|
||||||
|
offset_x = button_x * (index % column)
|
||||||
|
offset_y = button_y * (index // column)
|
||||||
|
sv_img.paste(bt, (25 + offset_x, 83 + offset_y), bt)
|
||||||
|
|
||||||
sv_img_list.append(sv_img)
|
sv_img_list.append(sv_img)
|
||||||
|
|
||||||
img = crop_center_img(bg, w, h)
|
img = crop_center_img(bg, w, h)
|
||||||
|
if is_gaussian:
|
||||||
|
img = img.filter(ImageFilter.GaussianBlur(gaussian_blur))
|
||||||
|
|
||||||
img.paste(title, (0, 0), title)
|
img.paste(title, (0, 0), title)
|
||||||
temp = 0
|
temp = 0
|
||||||
for _sm in sv_img_list:
|
for _sm in sv_img_list:
|
||||||
img.paste(_sm, (0, 600 + temp), _sm)
|
img.paste(_sm, (0, 600 + temp), _sm)
|
||||||
temp += _sm.size[1]
|
temp += _sm.size[1]
|
||||||
|
|
||||||
|
img = img.convert('RGBA')
|
||||||
|
all_white = Image.new('RGBA', img.size, (255, 255, 255))
|
||||||
|
img = Image.alpha_composite(all_white, img)
|
||||||
|
|
||||||
img = img.convert('RGB')
|
img = img.convert('RGB')
|
||||||
help_path = get_res_path('help') / f'{name}.jpg'
|
help_path = get_res_path('help') / f'{name}.jpg'
|
||||||
img.save(
|
img.save(
|
||||||
help_path,
|
help_path,
|
||||||
'JPEG',
|
'JPEG',
|
||||||
quality=85,
|
quality=89,
|
||||||
subsampling=0,
|
subsampling=0,
|
||||||
)
|
)
|
||||||
cache[name] = 1
|
cache[name] = 1
|
||||||
|
|
||||||
return await convert_img(img)
|
return await convert_img(img)
|
||||||
|
BIN
gsuid_core/help/icon/介绍.png
Normal file
After Width: | Height: | Size: 776 B |
BIN
gsuid_core/help/icon/任务.png
Normal file
After Width: | Height: | Size: 753 B |
BIN
gsuid_core/help/icon/信息.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
gsuid_core/help/icon/公告.png
Normal file
After Width: | Height: | Size: 698 B |
BIN
gsuid_core/help/icon/刀剑.png
Normal file
After Width: | Height: | Size: 977 B |
BIN
gsuid_core/help/icon/切换.png
Normal file
After Width: | Height: | Size: 890 B |
BIN
gsuid_core/help/icon/删除.png
Normal file
After Width: | Height: | Size: 743 B |
BIN
gsuid_core/help/icon/刷新.png
Normal file
After Width: | Height: | Size: 875 B |
BIN
gsuid_core/help/icon/卡组.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
gsuid_core/help/icon/哪里.png
Normal file
After Width: | Height: | Size: 896 B |
BIN
gsuid_core/help/icon/地图.png
Normal file
After Width: | Height: | Size: 896 B |
BIN
gsuid_core/help/icon/导入.png
Normal file
After Width: | Height: | Size: 563 B |
BIN
gsuid_core/help/icon/导出.png
Normal file
After Width: | Height: | Size: 644 B |
BIN
gsuid_core/help/icon/影.png
Normal file
After Width: | Height: | Size: 622 B |
BIN
gsuid_core/help/icon/拼图.png
Normal file
After Width: | Height: | Size: 917 B |
BIN
gsuid_core/help/icon/探索.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
gsuid_core/help/icon/推送.png
Normal file
After Width: | Height: | Size: 770 B |
BIN
gsuid_core/help/icon/收集.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
gsuid_core/help/icon/攻略.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
gsuid_core/help/icon/更新.png
Normal file
After Width: | Height: | Size: 883 B |
BIN
gsuid_core/help/icon/材料.png
Normal file
After Width: | Height: | Size: 949 B |
BIN
gsuid_core/help/icon/查询.png
Normal file
After Width: | Height: | Size: 839 B |
BIN
gsuid_core/help/icon/校验.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
gsuid_core/help/icon/每月.png
Normal file
After Width: | Height: | Size: 768 B |
BIN
gsuid_core/help/icon/深渊.png
Normal file
After Width: | Height: | Size: 1004 B |
BIN
gsuid_core/help/icon/添加.png
Normal file
After Width: | Height: | Size: 830 B |
BIN
gsuid_core/help/icon/清除.png
Normal file
After Width: | Height: | Size: 643 B |
BIN
gsuid_core/help/icon/状态.png
Normal file
After Width: | Height: | Size: 761 B |
BIN
gsuid_core/help/icon/签到.png
Normal file
After Width: | Height: | Size: 772 B |
BIN
gsuid_core/help/icon/绑定.png
Normal file
After Width: | Height: | Size: 837 B |
BIN
gsuid_core/help/icon/表.png
Normal file
After Width: | Height: | Size: 537 B |
BIN
gsuid_core/help/icon/表情.png
Normal file
After Width: | Height: | Size: 864 B |
BIN
gsuid_core/help/icon/角色.png
Normal file
After Width: | Height: | Size: 627 B |
BIN
gsuid_core/help/icon/记录.png
Normal file
After Width: | Height: | Size: 428 B |
BIN
gsuid_core/help/icon/配置.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
gsuid_core/help/icon/重启.png
Normal file
After Width: | Height: | Size: 990 B |
@ -100,7 +100,7 @@ def get_str_size(
|
|||||||
line += i
|
line += i
|
||||||
|
|
||||||
if hasattr(font, 'getsize'):
|
if hasattr(font, 'getsize'):
|
||||||
size, _ = font.getsize(line)
|
size, _ = font.getsize(line) # type: ignore
|
||||||
else:
|
else:
|
||||||
bbox = font.getbbox(line)
|
bbox = font.getbbox(line)
|
||||||
size, _ = bbox[2] - bbox[0], bbox[3] - bbox[1]
|
size, _ = bbox[2] - bbox[0], bbox[3] - bbox[1]
|
||||||
|
@ -44,7 +44,7 @@ def draw_center_text_by_line(
|
|||||||
x, y = pos
|
x, y = pos
|
||||||
|
|
||||||
if hasattr(font, 'getsize'):
|
if hasattr(font, 'getsize'):
|
||||||
_, h = font.getsize('X')
|
_, h = font.getsize('X') # type: ignore
|
||||||
else:
|
else:
|
||||||
bbox = font.getbbox('X')
|
bbox = font.getbbox('X')
|
||||||
_, h = 0, bbox[3] - bbox[1]
|
_, h = 0, bbox[3] - bbox[1]
|
||||||
@ -54,7 +54,8 @@ def draw_center_text_by_line(
|
|||||||
anchor = 'la' if not_center else 'mm'
|
anchor = 'la' if not_center else 'mm'
|
||||||
for char in text:
|
for char in text:
|
||||||
if hasattr(font, 'getsize'):
|
if hasattr(font, 'getsize'):
|
||||||
size, _ = font.getsize(char) # 获取当前字符的宽度
|
# 获取当前字符的宽度
|
||||||
|
size, _ = font.getsize(char) # type: ignore
|
||||||
else:
|
else:
|
||||||
bbox = font.getbbox(char)
|
bbox = font.getbbox(char)
|
||||||
size, _ = bbox[2] - bbox[0], bbox[3] - bbox[1]
|
size, _ = bbox[2] - bbox[0], bbox[3] - bbox[1]
|
||||||
@ -89,7 +90,7 @@ def draw_text_by_line(
|
|||||||
x, y = pos
|
x, y = pos
|
||||||
|
|
||||||
if hasattr(font, 'getsize'):
|
if hasattr(font, 'getsize'):
|
||||||
_, h = font.getsize('X')
|
_, h = font.getsize('X') # type: ignore
|
||||||
else:
|
else:
|
||||||
bbox = font.getbbox('X')
|
bbox = font.getbbox('X')
|
||||||
_, h = 0, bbox[3] - bbox[1]
|
_, h = 0, bbox[3] - bbox[1]
|
||||||
@ -102,8 +103,9 @@ def draw_text_by_line(
|
|||||||
row = "" # 存储本行文字
|
row = "" # 存储本行文字
|
||||||
length = 0 # 记录本行长度
|
length = 0 # 记录本行长度
|
||||||
for character in text:
|
for character in text:
|
||||||
|
# 获取当前字符的宽度
|
||||||
if hasattr(font, 'getsize'):
|
if hasattr(font, 'getsize'):
|
||||||
w, h = font.getsize(character) # 获取当前字符的宽度
|
w, h = font.getsize(character) # type: ignore
|
||||||
else:
|
else:
|
||||||
bbox = font.getbbox('X')
|
bbox = font.getbbox('X')
|
||||||
w, h = bbox[2] - bbox[0], bbox[3] - bbox[1]
|
w, h = bbox[2] - bbox[0], bbox[3] - bbox[1]
|
||||||
@ -115,7 +117,7 @@ def draw_text_by_line(
|
|||||||
row += character
|
row += character
|
||||||
if center:
|
if center:
|
||||||
if hasattr(font, 'getsize'):
|
if hasattr(font, 'getsize'):
|
||||||
font_size = font.getsize(row)
|
font_size = font.getsize(row) # type: ignore
|
||||||
else:
|
else:
|
||||||
bbox = font.getbbox(character)
|
bbox = font.getbbox(character)
|
||||||
font_size = bbox[2] - bbox[0], bbox[3] - bbox[1]
|
font_size = bbox[2] - bbox[0], bbox[3] - bbox[1]
|
||||||
@ -127,7 +129,7 @@ def draw_text_by_line(
|
|||||||
if row != "":
|
if row != "":
|
||||||
if center:
|
if center:
|
||||||
if hasattr(font, 'getsize'):
|
if hasattr(font, 'getsize'):
|
||||||
font_size = font.getsize(row)
|
font_size = font.getsize(row) # type: ignore
|
||||||
else:
|
else:
|
||||||
bbox = font.getbbox(row)
|
bbox = font.getbbox(row)
|
||||||
font_size = bbox[2] - bbox[0], bbox[3] - bbox[1]
|
font_size = bbox[2] - bbox[0], bbox[3] - bbox[1]
|
||||||
|
22
poetry.lock
generated
@ -196,13 +196,13 @@ reference = "mirrors"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "apscheduler"
|
name = "apscheduler"
|
||||||
version = "3.10.3"
|
version = "3.10.4"
|
||||||
description = "In-process task scheduler with Cron-like capabilities"
|
description = "In-process task scheduler with Cron-like capabilities"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.6"
|
python-versions = ">=3.6"
|
||||||
files = [
|
files = [
|
||||||
{file = "APScheduler-3.10.3-py3-none-any.whl", hash = "sha256:1611d207b095ff52d97884e90736c192bdd94dbd44ce27eb92c3f1da24a400d3"},
|
{file = "APScheduler-3.10.4-py3-none-any.whl", hash = "sha256:fb91e8a768632a4756a585f79ec834e0e27aad5860bac7eaa523d9ccefd87661"},
|
||||||
{file = "APScheduler-3.10.3.tar.gz", hash = "sha256:3f17fd3915f14f4bfa597f552130a14a9d1cc74a002fa1d95dd671cb48dba70e"},
|
{file = "APScheduler-3.10.4.tar.gz", hash = "sha256:e6df071b27d9be898e486bc7940a7be50b4af2e9da7c08f0744a96d4bd4cef4a"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
@ -605,13 +605,13 @@ reference = "mirrors"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "click"
|
name = "click"
|
||||||
version = "8.1.6"
|
version = "8.1.7"
|
||||||
description = "Composable command line interface toolkit"
|
description = "Composable command line interface toolkit"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
{file = "click-8.1.6-py3-none-any.whl", hash = "sha256:fa244bb30b3b5ee2cae3da8f55c9e5e0c0e86093306301fb418eb9dc40fbded5"},
|
{file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"},
|
||||||
{file = "click-8.1.6.tar.gz", hash = "sha256:48ee849951919527a045bfe3bf7baa8a959c423134e1a5b98c05c20ba75a1cbd"},
|
{file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
@ -1996,17 +1996,17 @@ reference = "mirrors"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "setuptools"
|
name = "setuptools"
|
||||||
version = "68.1.0"
|
version = "68.1.2"
|
||||||
description = "Easily download, build, install, upgrade, and uninstall Python packages"
|
description = "Easily download, build, install, upgrade, and uninstall Python packages"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
{file = "setuptools-68.1.0-py3-none-any.whl", hash = "sha256:e13e1b0bc760e9b0127eda042845999b2f913e12437046e663b833aa96d89715"},
|
{file = "setuptools-68.1.2-py3-none-any.whl", hash = "sha256:3d8083eed2d13afc9426f227b24fd1659489ec107c0e86cec2ffdde5c92e790b"},
|
||||||
{file = "setuptools-68.1.0.tar.gz", hash = "sha256:d59c97e7b774979a5ccb96388efc9eb65518004537e85d52e81eaee89ab6dd91"},
|
{file = "setuptools-68.1.2.tar.gz", hash = "sha256:3d4dfa6d95f1b101d695a6160a7626e15583af71a5f52176efa5d39a054d475d"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
|
docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5,<=7.1.2)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
|
||||||
testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
|
testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
|
||||||
testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"]
|
testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"]
|
||||||
|
|
||||||
@ -2708,4 +2708,4 @@ reference = "mirrors"
|
|||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "2.0"
|
lock-version = "2.0"
|
||||||
python-versions = "^3.8.1"
|
python-versions = "^3.8.1"
|
||||||
content-hash = "cf1907f9dba50e810dcf9bc81a81c79309a080aac345358c68a34b1dbd82d44e"
|
content-hash = "a57a5ae92fffd7da50ee98c76df4945223b2bf5636f1f6a84b2e38f0de05975f"
|
||||||
|
@ -24,8 +24,8 @@ aiosqlite = ">=0.17.0"
|
|||||||
aiofiles = ">=0.8.0"
|
aiofiles = ">=0.8.0"
|
||||||
sqlmodel = ">=0.0.8"
|
sqlmodel = ">=0.0.8"
|
||||||
gitpython = ">=3.1.27"
|
gitpython = ">=3.1.27"
|
||||||
fastapi-amis-admin = ">=0.5.0"
|
fastapi-amis-admin = "^0.5.8"
|
||||||
fastapi-user-auth = ">=0.5.0"
|
fastapi-user-auth = "^0.5.0"
|
||||||
qrcode = {extras = ["pil"], version = "^7.3.1"}
|
qrcode = {extras = ["pil"], version = "^7.3.1"}
|
||||||
msgspec = ">= 0.13.1"
|
msgspec = ">= 0.13.1"
|
||||||
uvicorn = ">=0.20.0"
|
uvicorn = ">=0.20.0"
|
||||||
|
@ -5,7 +5,7 @@ aiohttp==3.8.5 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0
|
|||||||
aiosignal==1.3.1 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
|
aiosignal==1.3.1 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
|
||||||
aiosqlite==0.19.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
|
aiosqlite==0.19.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
|
||||||
anyio==3.7.1 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
|
anyio==3.7.1 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
|
||||||
apscheduler==3.10.3 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
|
apscheduler==3.10.4 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
|
||||||
async-timeout==4.0.3 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
|
async-timeout==4.0.3 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
|
||||||
attrs==23.1.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
|
attrs==23.1.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
|
||||||
backports-zoneinfo==0.2.1 ; python_full_version >= "3.8.1" and python_version < "3.9"
|
backports-zoneinfo==0.2.1 ; python_full_version >= "3.8.1" and python_version < "3.9"
|
||||||
@ -14,7 +14,7 @@ beautifulsoup4==4.12.2 ; python_full_version >= "3.8.1" and python_full_version
|
|||||||
certifi==2023.7.22 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
|
certifi==2023.7.22 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
|
||||||
cffi==1.15.1 ; os_name == "nt" and implementation_name != "pypy" and python_full_version >= "3.8.1" and python_full_version < "4.0.0"
|
cffi==1.15.1 ; os_name == "nt" and implementation_name != "pypy" and python_full_version >= "3.8.1" and python_full_version < "4.0.0"
|
||||||
charset-normalizer==3.2.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
|
charset-normalizer==3.2.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
|
||||||
click==8.1.6 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
|
click==8.1.7 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
|
||||||
colorama==0.4.6 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0" and (platform_system == "Windows" or sys_platform == "win32")
|
colorama==0.4.6 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0" and (platform_system == "Windows" or sys_platform == "win32")
|
||||||
dnspython==2.4.2 ; python_full_version >= "3.8.1" and python_version < "4.0"
|
dnspython==2.4.2 ; python_full_version >= "3.8.1" and python_version < "4.0"
|
||||||
email-validator==2.0.0.post2 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
|
email-validator==2.0.0.post2 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
|
||||||
|