🐛 修复绑定uid
遇到的问题
@ -11,8 +11,12 @@ from .mono.Character import Character
|
|||||||
from ..genshinuid_config.gs_config import gsconfig
|
from ..genshinuid_config.gs_config import gsconfig
|
||||||
from .etc.MAP_PATH import COLOR_MAP, avatarName2SkillAdd
|
from .etc.MAP_PATH import COLOR_MAP, avatarName2SkillAdd
|
||||||
from ..utils.fonts.genshin_fonts import genshin_font_origin
|
from ..utils.fonts.genshin_fonts import genshin_font_origin
|
||||||
from ..utils.image.image_tools import CustomizeImage, get_weapon_affix_pic
|
from .etc.etc import TEXT_PATH, strLenth, get_artifacts_value
|
||||||
from .etc.etc import TEXT_PATH, strLenth, get_star_png, get_artifacts_value
|
from ..utils.image.image_tools import (
|
||||||
|
CustomizeImage,
|
||||||
|
get_star_png,
|
||||||
|
get_weapon_affix_pic,
|
||||||
|
)
|
||||||
from ..utils.resource.RESOURCE_PATH import (
|
from ..utils.resource.RESOURCE_PATH import (
|
||||||
REL_PATH,
|
REL_PATH,
|
||||||
ICON_PATH,
|
ICON_PATH,
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from PIL import Image
|
|
||||||
|
|
||||||
from .MAP_PATH import ATTR_MAP, dmgMap
|
from .MAP_PATH import ATTR_MAP, dmgMap
|
||||||
|
|
||||||
R_PATH = Path(__file__).parents[1]
|
R_PATH = Path(__file__).parents[1]
|
||||||
@ -31,11 +29,6 @@ VALUE_MAP = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def get_star_png(star: int) -> Image.Image:
|
|
||||||
png = Image.open(TEXT_PATH / 's-{}.png'.format(str(star)))
|
|
||||||
return png
|
|
||||||
|
|
||||||
|
|
||||||
def strLenth(r: str, size: int, limit: int = 540) -> str:
|
def strLenth(r: str, size: int, limit: int = 540) -> str:
|
||||||
result = ''
|
result = ''
|
||||||
temp = 0
|
temp = 0
|
||||||
|
@ -65,7 +65,9 @@ async def send_link_uid_msg(bot: Bot, ev: Event):
|
|||||||
await bot.logger.info('[绑定/解绑]UserID: {}'.format(qid))
|
await bot.logger.info('[绑定/解绑]UserID: {}'.format(qid))
|
||||||
|
|
||||||
sqla = get_sqla(ev.bot_id)
|
sqla = get_sqla(ev.bot_id)
|
||||||
uid = ev.text
|
uid = ev.text.strip()
|
||||||
|
if not uid.isdigit():
|
||||||
|
return '你输入了错误的格式!'
|
||||||
|
|
||||||
if ev.command.startswith('绑定'):
|
if ev.command.startswith('绑定'):
|
||||||
data = await sqla.insert_bind_data(qid, uid=uid)
|
data = await sqla.insert_bind_data(qid, uid=uid)
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
from pathlib import Path
|
|
||||||
from textwrap import fill
|
from textwrap import fill
|
||||||
from typing import Tuple, Union
|
from typing import Tuple, Union
|
||||||
|
|
||||||
import aiofiles
|
import aiofiles
|
||||||
from PIL import Image, ImageDraw
|
from PIL import Image, ImageDraw
|
||||||
|
|
||||||
|
from .path import TEXT_PATH
|
||||||
from ..utils.error_reply import get_error
|
from ..utils.error_reply import get_error
|
||||||
from ..utils.image.image_tools import get_pic
|
from ..utils.image.image_tools import get_pic
|
||||||
from ..gsuid_utils.api.minigg.models import Artifact
|
from ..gsuid_utils.api.minigg.models import Artifact
|
||||||
@ -18,9 +18,6 @@ from ..utils.fonts.genshin_fonts import (
|
|||||||
gs_font_40,
|
gs_font_40,
|
||||||
)
|
)
|
||||||
|
|
||||||
R_PATH = Path(__file__).parents[0]
|
|
||||||
TEXT_PATH = R_PATH / 'texture2D'
|
|
||||||
|
|
||||||
img1 = Image.open(TEXT_PATH / 'wiki_artifacts_bg1.png')
|
img1 = Image.open(TEXT_PATH / 'wiki_artifacts_bg1.png')
|
||||||
img2 = Image.open(TEXT_PATH / 'wiki_artifacts_bg2.png')
|
img2 = Image.open(TEXT_PATH / 'wiki_artifacts_bg2.png')
|
||||||
img3 = Image.open(TEXT_PATH / 'wiki_artifacts_bg3.png')
|
img3 = Image.open(TEXT_PATH / 'wiki_artifacts_bg3.png')
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
from pathlib import Path
|
|
||||||
from typing import Dict, Tuple, Union
|
from typing import Dict, Tuple, Union
|
||||||
|
|
||||||
from PIL import Image, ImageDraw
|
from PIL import Image, ImageDraw
|
||||||
|
|
||||||
|
from .path import TEXT_PATH
|
||||||
from ..utils.colors import first_color
|
from ..utils.colors import first_color
|
||||||
from ..utils.error_reply import get_error
|
from ..utils.error_reply import get_error
|
||||||
from ..utils.resource.download_url import download
|
from ..utils.resource.download_url import download
|
||||||
@ -22,8 +22,6 @@ from ..gsuid_utils.api.minigg.models import (
|
|||||||
CharacterConstellations,
|
CharacterConstellations,
|
||||||
)
|
)
|
||||||
|
|
||||||
R_PATH = Path(__file__).parents[0]
|
|
||||||
TEXT_PATH = R_PATH / 'texture2D'
|
|
||||||
COLOR_MAP = {
|
COLOR_MAP = {
|
||||||
'Anemo': (0, 145, 137),
|
'Anemo': (0, 145, 137),
|
||||||
'Cryo': (4, 126, 152),
|
'Cryo': (4, 126, 152),
|
||||||
|
152
GenshinUID/genshinuid_wikitext/get_weapons_pic.py
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
import math
|
||||||
|
from typing import List, Union
|
||||||
|
|
||||||
|
import aiofiles
|
||||||
|
from PIL import Image, ImageDraw
|
||||||
|
|
||||||
|
from .path import TEXT_PATH
|
||||||
|
from ..utils.colors import white_color
|
||||||
|
from ..utils.error_reply import get_error
|
||||||
|
from ..utils.get_assets import get_assets_from_ambr
|
||||||
|
from ..utils.image.convert import str_lenth, convert_img
|
||||||
|
from ..utils.resource.RESOURCE_PATH import WIKI_WEAPON_PATH
|
||||||
|
from ..gsuid_utils.api.minigg.models import Weapon, WeaponStats
|
||||||
|
from ..utils.image.image_tools import (
|
||||||
|
get_color_bg,
|
||||||
|
get_star_png,
|
||||||
|
get_unknown_png,
|
||||||
|
)
|
||||||
|
from ..gsuid_utils.api.minigg.request import (
|
||||||
|
get_others_info,
|
||||||
|
get_weapon_info,
|
||||||
|
get_weapon_stats,
|
||||||
|
)
|
||||||
|
from ..utils.fonts.genshin_fonts import (
|
||||||
|
gs_font_18,
|
||||||
|
gs_font_22,
|
||||||
|
gs_font_28,
|
||||||
|
gs_font_36,
|
||||||
|
gs_font_44,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def get_artifacts_wiki_img(name: str) -> Union[str, bytes]:
|
||||||
|
data = await get_weapon_info(name)
|
||||||
|
stats = await get_weapon_stats(name, 90)
|
||||||
|
if isinstance(data, int):
|
||||||
|
return get_error(data)
|
||||||
|
elif isinstance(stats, int):
|
||||||
|
return get_error(stats)
|
||||||
|
elif isinstance(data, List) or isinstance(stats, List):
|
||||||
|
return get_error(-400)
|
||||||
|
else:
|
||||||
|
art_name = data['name']
|
||||||
|
path = WIKI_WEAPON_PATH / f'{art_name}.jpg'
|
||||||
|
if path.exists():
|
||||||
|
async with aiofiles.open(path, 'rb') as f:
|
||||||
|
return await f.read()
|
||||||
|
img = await draw_weapons_wiki_img(data, stats)
|
||||||
|
return img
|
||||||
|
|
||||||
|
|
||||||
|
async def draw_weapons_wiki_img(data: Weapon, stats: WeaponStats):
|
||||||
|
gray_color = (175, 173, 176)
|
||||||
|
img_test = Image.new('RGBA', (1, 1))
|
||||||
|
img_test_draw = ImageDraw.Draw(img_test)
|
||||||
|
effect = data['effect']
|
||||||
|
effect = await str_lenth(effect, 22, 540)
|
||||||
|
_, _, _, y1 = img_test_draw.textbbox((0, 0), effect, gs_font_22)
|
||||||
|
w, h = 600, 1040 + y1
|
||||||
|
|
||||||
|
star_pic = get_star_png(data['rarity'])
|
||||||
|
type_pic = Image.open(TEXT_PATH / f'{data["weapontype"]}.png')
|
||||||
|
gacha_pic = await get_assets_from_ambr(data['images']['namegacha'])
|
||||||
|
if gacha_pic is None:
|
||||||
|
gacha_pic = Image.new('RGBA', (333, 666))
|
||||||
|
else:
|
||||||
|
gacha_pic = gacha_pic.resize((333, 666))
|
||||||
|
|
||||||
|
img = await get_color_bg(w, h, 'wiki_weapon_bg')
|
||||||
|
img_draw = ImageDraw.Draw(img)
|
||||||
|
|
||||||
|
img_draw.text((44, 59), data['name'], white_color, gs_font_44, 'lm')
|
||||||
|
img.paste(star_pic, (45, 83), star_pic)
|
||||||
|
img.paste(type_pic, (44, 158), type_pic)
|
||||||
|
img.paste(gacha_pic, (134, 81), gacha_pic)
|
||||||
|
img_draw.text((45, 744), '基础攻击力', gray_color, gs_font_18, 'lm')
|
||||||
|
img_draw.text((545, 744), data['substat'], gray_color, gs_font_18, 'rm')
|
||||||
|
|
||||||
|
if data['subvalue'] != '':
|
||||||
|
sub_val = (
|
||||||
|
(data['subvalue'] + '%')
|
||||||
|
if data['substat'] != '元素精通'
|
||||||
|
else data['subvalue']
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
sub_val = ''
|
||||||
|
|
||||||
|
if data['substat'] != '':
|
||||||
|
sp = (
|
||||||
|
'%.1f%%' % (stats['specialized'] * 100)
|
||||||
|
if data['substat'] != '元素精通'
|
||||||
|
else str(math.floor(stats['specialized']))
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
sp = ''
|
||||||
|
|
||||||
|
atk = f'{data["baseatk"]} · {stats["attack"]}'
|
||||||
|
subval = f'{sub_val} · {sp}'
|
||||||
|
|
||||||
|
img_draw.text((45, 779), atk, white_color, gs_font_36, 'lm')
|
||||||
|
img_draw.text((545, 779), subval, white_color, gs_font_36, 'rm')
|
||||||
|
|
||||||
|
effect_name = f'{data["effectname"]}・精炼5' if data['effectname'] else '无特效'
|
||||||
|
img_draw.text((46, 837), effect_name, white_color, gs_font_28, 'lm')
|
||||||
|
img_draw.text((46, 866), effect, gray_color, gs_font_28)
|
||||||
|
|
||||||
|
# 计算材料
|
||||||
|
temp = {}
|
||||||
|
cost = data['costs']
|
||||||
|
for i in reversed(cost.values()):
|
||||||
|
for j in i: # type:ignore
|
||||||
|
for name in temp.keys():
|
||||||
|
similarity = len(set(j['name']) & set(name))
|
||||||
|
if similarity >= len(j['name']) / 2:
|
||||||
|
continue
|
||||||
|
elif j['name'] == name:
|
||||||
|
temp[name] += j['count']
|
||||||
|
else:
|
||||||
|
temp[j['name']] = j['count']
|
||||||
|
|
||||||
|
if data['rarity'] == '5':
|
||||||
|
temp['精锻用魔矿'] = 907
|
||||||
|
elif data['rarity'] == '4':
|
||||||
|
temp['精锻用魔矿'] = 605
|
||||||
|
elif data['rarity'] == '3':
|
||||||
|
temp['精锻用魔矿'] = 399
|
||||||
|
elif data['rarity'] == '2':
|
||||||
|
temp['精锻用魔矿'] = 108
|
||||||
|
elif data['rarity'] == '1':
|
||||||
|
temp['精锻用魔矿'] = 72
|
||||||
|
|
||||||
|
wiki_cost_bg = Image.open(TEXT_PATH / 'wiki_weapon_cost.png')
|
||||||
|
wiki_cost_draw = ImageDraw.Draw(wiki_cost_bg)
|
||||||
|
for index, cost_name in enumerate(temp):
|
||||||
|
material = await get_others_info('materials', cost_name)
|
||||||
|
if isinstance(material, int):
|
||||||
|
cost_pic = get_unknown_png()
|
||||||
|
else:
|
||||||
|
name_icon = material['images']['nameicon']
|
||||||
|
_cost_pic = await get_assets_from_ambr(name_icon)
|
||||||
|
if _cost_pic is None:
|
||||||
|
cost_pic = get_unknown_png()
|
||||||
|
else:
|
||||||
|
cost_pic = _cost_pic.resize((64, 64))
|
||||||
|
t = 100 * index
|
||||||
|
wiki_cost_bg.paste(cost_pic, (67 + t, 46), cost_pic)
|
||||||
|
val = str(temp[cost_name])
|
||||||
|
wiki_cost_draw.text((99 + t, 123), val, white_color, gs_font_18, 'mm')
|
||||||
|
|
||||||
|
img.paste(wiki_cost_bg, (0, 850 + y1), wiki_cost_bg)
|
||||||
|
|
||||||
|
return await convert_img(img)
|
3
GenshinUID/genshinuid_wikitext/path.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
TEXT_PATH = Path(__file__).parent / 'texture2D'
|
BIN
GenshinUID/genshinuid_wikitext/texture2D/wiki_weapon_cost.png
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
GenshinUID/genshinuid_wikitext/texture2D/单手剑.png
Normal file
After Width: | Height: | Size: 128 KiB |
BIN
GenshinUID/genshinuid_wikitext/texture2D/双手剑.png
Normal file
After Width: | Height: | Size: 155 KiB |
BIN
GenshinUID/genshinuid_wikitext/texture2D/弓.png
Normal file
After Width: | Height: | Size: 156 KiB |
BIN
GenshinUID/genshinuid_wikitext/texture2D/法器.png
Normal file
After Width: | Height: | Size: 115 KiB |
BIN
GenshinUID/genshinuid_wikitext/texture2D/长柄武器.png
Normal file
After Width: | Height: | Size: 132 KiB |
@ -42,5 +42,7 @@ def get_error(retcode: Union[int, str]) -> str:
|
|||||||
return '当前角色冒险等阶未达到10级, 暂时无法参加此活动...'
|
return '当前角色冒险等阶未达到10级, 暂时无法参加此活动...'
|
||||||
elif retcode == 400:
|
elif retcode == 400:
|
||||||
return '[MINIGG]暂未找到此内容...'
|
return '[MINIGG]暂未找到此内容...'
|
||||||
|
elif retcode == -400:
|
||||||
|
return '请输入更详细的名称...'
|
||||||
else:
|
else:
|
||||||
return f'API报错, 错误码为{retcode}!'
|
return f'API报错, 错误码为{retcode}!'
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
from typing import Literal, Optional
|
from typing import Literal, Optional
|
||||||
|
|
||||||
|
import aiofiles
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
from aiohttp.client import ClientSession
|
from aiohttp.client import ClientSession
|
||||||
|
|
||||||
|
from .resource.RESOURCE_PATH import ICON_PATH
|
||||||
|
|
||||||
AMBR_UI = 'https://api.ambr.top/assets/UI/{}.png'
|
AMBR_UI = 'https://api.ambr.top/assets/UI/{}.png'
|
||||||
ENKA_UI = 'https://enka.network/ui/{}.png'
|
ENKA_UI = 'https://enka.network/ui/{}.png'
|
||||||
|
|
||||||
@ -10,6 +13,9 @@ ENKA_UI = 'https://enka.network/ui/{}.png'
|
|||||||
async def _get_assets(
|
async def _get_assets(
|
||||||
name: str, type: Literal['ENKA', 'AMBR'] = 'AMBR'
|
name: str, type: Literal['ENKA', 'AMBR'] = 'AMBR'
|
||||||
) -> Optional[Image.Image]:
|
) -> Optional[Image.Image]:
|
||||||
|
path = ICON_PATH / f'{name}.png'
|
||||||
|
if path.exists():
|
||||||
|
return Image.open(path)
|
||||||
if type == 'AMBR':
|
if type == 'AMBR':
|
||||||
URL = AMBR_UI
|
URL = AMBR_UI
|
||||||
else:
|
else:
|
||||||
@ -18,6 +24,8 @@ async def _get_assets(
|
|||||||
async with sess.get(URL.format(name)) as res:
|
async with sess.get(URL.format(name)) as res:
|
||||||
if res.status == 200:
|
if res.status == 200:
|
||||||
content = await res.read()
|
content = await res.read()
|
||||||
|
async with aiofiles.open(path, 'wb') as f:
|
||||||
|
await f.write(content)
|
||||||
return Image.open(content)
|
return Image.open(content)
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
BIN
GenshinUID/utils/image/bg/sp_bg/wiki_weapon_bg.jpg
Normal file
After Width: | Height: | Size: 29 KiB |
@ -182,6 +182,19 @@ async def get_level_pic(level: int) -> Image.Image:
|
|||||||
return Image.open(LEVEL_PATH / f'level_{level}.png')
|
return Image.open(LEVEL_PATH / f'level_{level}.png')
|
||||||
|
|
||||||
|
|
||||||
|
def get_star_png(star: Union[int, str]) -> Image.Image:
|
||||||
|
path = TEXT_PATH / 'weapon_star' / f's-{star}.png'
|
||||||
|
if path.exists():
|
||||||
|
png = Image.open(path)
|
||||||
|
else:
|
||||||
|
png = Image.open(TEXT_PATH / 'weapon_star' / 's-1.png')
|
||||||
|
return png
|
||||||
|
|
||||||
|
|
||||||
|
def get_unknown_png() -> Image.Image:
|
||||||
|
return Image.open(TEXT_PATH / 'unknown.png')
|
||||||
|
|
||||||
|
|
||||||
async def get_qq_avatar(
|
async def get_qq_avatar(
|
||||||
qid: Optional[Union[int, str]] = None, avatar_url: Optional[str] = None
|
qid: Optional[Union[int, str]] = None, avatar_url: Optional[str] = None
|
||||||
) -> Image.Image:
|
) -> Image.Image:
|
||||||
@ -250,7 +263,10 @@ def crop_center_img(
|
|||||||
|
|
||||||
|
|
||||||
async def get_color_bg(
|
async def get_color_bg(
|
||||||
based_w: int, based_h: int, bg: Optional[str] = None
|
based_w: int,
|
||||||
|
based_h: int,
|
||||||
|
bg: Optional[str] = None,
|
||||||
|
without_mask: bool = False,
|
||||||
) -> Image.Image:
|
) -> Image.Image:
|
||||||
image = ''
|
image = ''
|
||||||
if bg and gsconfig.get_config('DefaultBaseBG').data:
|
if bg and gsconfig.get_config('DefaultBaseBG').data:
|
||||||
@ -263,9 +279,12 @@ async def get_color_bg(
|
|||||||
CI_img = CustomizeImage(image, based_w, based_h)
|
CI_img = CustomizeImage(image, based_w, based_h)
|
||||||
img = CI_img.bg_img
|
img = CI_img.bg_img
|
||||||
color = CI_img.bg_color
|
color = CI_img.bg_color
|
||||||
color_mask = Image.new('RGBA', (based_w, based_h), color)
|
if not without_mask:
|
||||||
enka_mask = Image.open(TEXT2D_PATH / 'mask.png').resize((based_w, based_h))
|
color_mask = Image.new('RGBA', (based_w, based_h), color)
|
||||||
img.paste(color_mask, (0, 0), enka_mask)
|
enka_mask = Image.open(TEXT2D_PATH / 'mask.png').resize(
|
||||||
|
(based_w, based_h)
|
||||||
|
)
|
||||||
|
img.paste(color_mask, (0, 0), enka_mask)
|
||||||
return img
|
return img
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ GUIDE_PATH = WIKI_PATH / 'guide'
|
|||||||
REF_PATH = WIKI_PATH / 'ref'
|
REF_PATH = WIKI_PATH / 'ref'
|
||||||
WIKI_REL_PATH = WIKI_PATH / 'artifacts'
|
WIKI_REL_PATH = WIKI_PATH / 'artifacts'
|
||||||
CONSTELLATION_PATH = WIKI_PATH / 'constellation'
|
CONSTELLATION_PATH = WIKI_PATH / 'constellation'
|
||||||
|
WIKI_WEAPON_PATH = WIKI_PATH / 'weapon'
|
||||||
TEXT2D_PATH = Path(__file__).parent / 'texture2d'
|
TEXT2D_PATH = Path(__file__).parent / 'texture2d'
|
||||||
|
|
||||||
PLAYER_PATH = MAIN_PATH / 'players'
|
PLAYER_PATH = MAIN_PATH / 'players'
|
||||||
@ -54,6 +55,7 @@ def init_dir():
|
|||||||
CHAR_CARD_PATH,
|
CHAR_CARD_PATH,
|
||||||
WIKI_REL_PATH,
|
WIKI_REL_PATH,
|
||||||
CONSTELLATION_PATH,
|
CONSTELLATION_PATH,
|
||||||
|
WIKI_WEAPON_PATH,
|
||||||
]:
|
]:
|
||||||
i.mkdir(parents=True, exist_ok=True)
|
i.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
BIN
GenshinUID/utils/resource/texture2d/unknown.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
GenshinUID/utils/resource/texture2d/weapon_star/s-1.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
GenshinUID/utils/resource/texture2d/weapon_star/s-2.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
GenshinUID/utils/resource/texture2d/weapon_star/s-3.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
GenshinUID/utils/resource/texture2d/weapon_star/s-4.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
GenshinUID/utils/resource/texture2d/weapon_star/s-5.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
6
poetry.lock
generated
@ -1705,14 +1705,14 @@ files = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pytest"
|
name = "pytest"
|
||||||
version = "7.3.0"
|
version = "7.3.1"
|
||||||
description = "pytest: simple powerful testing with Python"
|
description = "pytest: simple powerful testing with Python"
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
{file = "pytest-7.3.0-py3-none-any.whl", hash = "sha256:933051fa1bfbd38a21e73c3960cebdad4cf59483ddba7696c48509727e17f201"},
|
{file = "pytest-7.3.1-py3-none-any.whl", hash = "sha256:3799fa815351fea3a5e96ac7e503a96fa51cc9942c3753cda7651b93c1cfa362"},
|
||||||
{file = "pytest-7.3.0.tar.gz", hash = "sha256:58ecc27ebf0ea643ebfdf7fb1249335da761a00c9f955bcd922349bcb68ee57d"},
|
{file = "pytest-7.3.1.tar.gz", hash = "sha256:434afafd78b1d78ed0addf160ad2b77a30d35d4bdf8af234fe621919d9ed15e3"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
|