添加 Python 工具与折行调试

This commit is contained in:
chengzongjie 2026-05-10 16:05:47 +08:00
parent 49e351c871
commit cfd31d0ff3
5 changed files with 506 additions and 0 deletions

1
.python-version Normal file
View File

@ -0,0 +1 @@
3.11

258
main.py Normal file
View File

@ -0,0 +1,258 @@
from openpyxl import load_workbook
from openpyxl.cell.cell import Cell
from openpyxl.utils import get_column_letter
BASE_WIDTH = 5.83
# openpyxl 未设置时的默认列宽/行高
DEFAULT_COLUMN_WIDTH = 8.43
DEFAULT_ROW_HEIGHT_PT = 15.0
# 宋体字符宽度规则
def char_width_pt(c: str, base_pt: float = 8.0) -> float:
if "\u4e00" <= c <= "\u9fff":
return base_pt
return 0.5 * base_pt
def is_chinese_char(c: str) -> bool:
return "\u4e00" <= c <= "\u9fff"
def is_ascii_alnum(c: str) -> bool:
return c.isascii() and (c.isalnum() or c == ".")
# 这些符号通常不应出现在折行后的行首,倾向于“粘在前一个词后面”
NON_LEADING_PUNCT = {
")",
"]",
"}",
")",
"】",
"》",
"〉",
"”",
"’",
",",
"。",
"、",
",",
".",
";",
":",
"!",
"?",
}
def iter_words(line_txt: str) -> list[str]:
"""把一行文本切成“单词”数组。
规则:
- 一个汉字算一个单词
- 连续的数字或字母(ASCII alnum)算一个单词
- 其他字符(空格/标点等)按单字符单词处理
"""
words: list[str] = []
i = 0
n = len(line_txt)
while i < n:
c = line_txt[i]
# 右括号/收尾标点尽量不单独成词,避免被折到新行行首
if c in NON_LEADING_PUNCT and words:
words[-1] += c
i += 1
continue
if is_chinese_char(c):
words.append(c)
i += 1
continue
if is_ascii_alnum(c):
j = i + 1
while j < n and is_ascii_alnum(line_txt[j]):
j += 1
words.append(line_txt[i:j])
i = j
continue
words.append(c)
i += 1
# print(" | ".join(words))
return words
def wrap_line_words(line_txt: str, max_width_pt: float) -> list[str]:
"""把一行文本按最大宽度折行,返回折行后的每一行内容。"""
if not line_txt.strip():
return [line_txt]
words = iter_words(line_txt)
wrapped_lines: list[str] = []
curr_line = ""
curr_width = 0.0
def flush_line() -> None:
nonlocal curr_line, curr_width
if curr_line != "":
wrapped_lines.append(curr_line)
curr_line = ""
curr_width = 0.0
def append_char(ch: str) -> None:
nonlocal curr_line, curr_width
ch_w = char_width_pt(ch)
if curr_line and (curr_width + ch_w > max_width_pt):
flush_line()
curr_line += ch
curr_width += ch_w
for word in words:
word_w = sum(char_width_pt(c) for c in word)
# 单词本身就超过最大宽度:退化到逐字符切分
if word_w > max_width_pt:
for ch in word:
append_char(ch)
continue
if curr_line and (curr_width + word_w > max_width_pt):
flush_line()
curr_line += word
curr_width += word_w
flush_line()
return wrapped_lines or [""]
# ------------- 获取合并/普通单元格 真实可用列宽(原生列宽单位) -------------
def cell_available_col_width(cell: Cell) -> float:
sheet = cell.parent
col_idx = cell.column
# 遍历合并区域
for merged_range in sheet.merged_cells.ranges: # pyright: ignore[reportAttributeAccessIssue]
min_col, _, max_col, _ = merged_range.bounds
if min_col <= col_idx <= max_col:
merged_width = 0.0
for c in range(min_col, max_col + 1):
col_letter = get_column_letter(c)
col_width = (
sheet.column_dimensions[col_letter].width or DEFAULT_COLUMN_WIDTH # pyright: ignore[reportAttributeAccessIssue]
)
merged_width += col_width
return merged_width
# 普通单元格
col_letter = get_column_letter(col_idx)
return sheet.column_dimensions[col_letter].width or DEFAULT_COLUMN_WIDTH # pyright: ignore[reportAttributeAccessIssue]
# ------------- 获取合并/普通单元格 真实总高度(pt) -------------
def cell_total_height_pt(cell: Cell) -> float:
sheet = cell.parent
row_idx = cell.row
for merged_range in sheet.merged_cells.ranges: # pyright: ignore[reportAttributeAccessIssue]
_, min_row, _, max_row = merged_range.bounds
if min_row <= row_idx <= max_row:
total_h = 0.0
for r in range(min_row, max_row + 1):
row_height = sheet.row_dimensions[r].height or DEFAULT_ROW_HEIGHT_PT # pyright: ignore[reportAttributeAccessIssue]
total_h += row_height
return total_h
return sheet.row_dimensions[row_idx].height or DEFAULT_ROW_HEIGHT_PT # pyright: ignore[reportAttributeAccessIssue]
# ------------- 计算单行文本在指定宽度下折成几行 -------------
def wrap_line_count(line_txt: str, max_width_pt: float) -> int:
return len(wrap_line_words(line_txt, max_width_pt))
def can_fit_chinese_chars(col_width_chars: float, zh_font_pt: float) -> int:
"""
根据Excel列宽值(字符单位),计算在宋体8号下能容纳多少个汉字
像素 = 点 × (DPI / 72)
px = pt * dpi / 72
pt = px * 72 / dpi
基准字符宽度:Calibri 11pt '0' = 5.83
"""
return int(col_width_chars * BASE_WIDTH / zh_font_pt)
def default_row_height_pt(sheet) -> float:
"""获取 sheet 默认行高(pt)。"""
return float(
getattr(getattr(sheet, "sheet_format", None), "defaultRowHeight", None)
or DEFAULT_ROW_HEIGHT_PT
)
# ------------- 主函数:判断单元格内容展示/打印是否溢出 -------------
def is_cell_content_overflow(cell: Cell) -> bool:
if not cell.value:
return False
text = str(cell.value).replace("\r", "")
align = cell.alignment
# 缩小字体填充 直接不溢出
if align.shrink_to_fit:
return False
# 1. 拿到真实可用列宽、单元格总高度(pt)
avail_col_width = cell_available_col_width(cell)
chinese_capacity = can_fit_chinese_chars(avail_col_width, 8.0)
print("列宽为", avail_col_width, "可容纳汉字", chinese_capacity, "个")
cell_height_pt = cell_total_height_pt(cell)
print("高度:", cell_height_pt)
# 2. 不开自动换行:只判宽度溢出
if not align.wrap_text:
total_w = sum(char_width_pt(c) for c in text)
return total_w > avail_col_width
# 3. 开自动换行:先按 \n 拆分,再逐行自动折行
lines = text.split("\n")
total_wrap_lines = 0
for line in lines:
wrapped = wrap_line_words(line, avail_col_width * BASE_WIDTH)
print(line, "->", len(wrapped), "行")
for i, wrapped_line in enumerate(wrapped, start=1):
print(f" {i:02d}: {wrapped_line}")
total_wrap_lines += len(wrapped)
# 文本总所需高度 pt
# 注意:font_size 不是“行高”。这里改为用 sheet 默认行高来估算每一行换行文本的占用高度。
required_height_pt = total_wrap_lines * default_row_height_pt(cell.parent)
# 超出单元格高度即溢出
return required_height_pt > cell_height_pt
# ===================== 使用示例 =====================
if __name__ == "__main__":
# 加载你的Excel文件
wb = load_workbook("测试.xlsx")
ws = wb.active
if ws is None:
raise ValueError("无法获取工作表")
# 测试:普通单元格 / 合并单元格 都可以
test_cells = ws["AA4":"AB4"]
for row in test_cells:
for cell in row:
overflow = is_cell_content_overflow(cell)
print(f"单元格 {cell.coordinate}:")
print(f" 内容:{cell.value}")
print(f" 是否溢出:{overflow}")

73
ok.py Normal file
View File

@ -0,0 +1,73 @@
from openpyxl import load_workbook
from PIL import ImageFont
def get_font_width_ratio(font_path, point_size, char="0"):
"""
测量给定字体下指定字符的宽度比例(宽度 / 字体大小)
通过放大到 200pt 测量消除取整误差。
"""
measure_pt = 200 # 足够大,减少 hinting 影响
# Pillow 的 size 参数需要像素值,我们任选一个 DPI 但最终取比例,所以 DPI 可任意
dpi = 96
measure_px = int(measure_pt * dpi / 72)
font = ImageFont.truetype(font_path, measure_px)
bbox = font.getbbox(char)
width_px = bbox[2] - bbox[0]
ratio = width_px / measure_px # 无量纲比例
return ratio
def calc_chars_per_column(workbook_path, sheet_name, column_letter, target_char="中"):
"""
计算指定列能容纳多少个 target_char(默认汉字)
"""
wb = load_workbook(workbook_path)
ws = wb[sheet_name]
# 1. 获取默认字体(Normal 样式)
# default_font = wb._named_styles["Normal"].font
# default_font_name = default_font.name or "Calibri"
# default_font_size = default_font.size or 11 # 磅值
# 2. 获取默认字体下数字 '0' 的宽度比例
# 需要找到默认字体文件路径(简单方案:使用系统字体名,PIL 能自动查找)
zero_ratio = get_font_width_ratio(
"Calibri.ttf", 11, "0"
)
standard_char_width_pt = 11 * zero_ratio # 标准字符宽度(点)
# 3. 获取目标字体(宋体 8 号 = 5pt)下汉字的宽度比例
target_font_name = "simsun.ttc" # 宋体
target_font_size_pt = 8
han_ratio = get_font_width_ratio(target_font_name, target_font_size_pt, target_char)
han_width_pt = target_font_size_pt * han_ratio
# 4. 列宽(字符数)
col_width_chars = ws.column_dimensions[column_letter].width
print("列宽:", col_width_chars, "字符")
# 5. 左右内边距 + 右边框线的经验值(点)
# 根据实测,对于小列宽,固定边距约为 3pt(相当于 4~5 像素在 96DPI 下)
padding_pt = 0
total_width_pt = (
col_width_chars * standard_char_width_pt + padding_pt * 2 + 0.5
) # 右边框约 0.5pt
# 6. 计算可容纳汉字数
max_count = int(total_width_pt // han_width_pt)
# print(f"默认字体: {default_font_name} {default_font_size}pt")
print(f"标准字符宽度: {standard_char_width_pt:.3f} pt")
print(f"目标汉字宽度: {han_width_pt:.3f} pt")
print(f"列总宽度: {total_width_pt:.3f} pt")
print(f"可容纳汉字数: {max_count}")
return max_count
# 使用示例
if __name__ == "__main__":
# 替换为你的文件路径和工作表名
count = calc_chars_per_column("测试.xlsx", "Sheet1", "AA")

15
pyproject.toml Normal file
View File

@ -0,0 +1,15 @@
[project]
name = "excel2pdf"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.11"
dependencies = [
"openpyxl>=3.1.5",
"pillow>=12.2.0",
]
[dependency-groups]
dev = [
"ruff>=0.15.12",
]

159
uv.lock generated Normal file
View File

@ -0,0 +1,159 @@
version = 1
revision = 3
requires-python = ">=3.11"
[[package]]
name = "et-xmlfile"
version = "2.0.0"
source = { registry = "https://bytedpypi.byted.org/simple" }
sdist = { url = "https://bytedpypi.byted.org/packages/et-xmlfile/et_xmlfile-2.0.0.tar.gz", hash = "sha256:dab3f4764309081ce75662649be815c4c9081e88f0837825f90fd28317d4da54" }
wheels = [
{ url = "https://bytedpypi.byted.org/packages/et-xmlfile/et_xmlfile-2.0.0-py3-none-any.whl", hash = "sha256:7a91720bc756843502c3b7504c77b8fe44217c85c537d85037f0f536151b2caa" },
]
[[package]]
name = "excel2pdf"
version = "0.1.0"
source = { virtual = "." }
dependencies = [
{ name = "openpyxl" },
{ name = "pillow" },
]
[package.dev-dependencies]
dev = [
{ name = "ruff" },
]
[package.metadata]
requires-dist = [
{ name = "openpyxl", specifier = ">=3.1.5" },
{ name = "pillow", specifier = ">=12.2.0" },
]
[package.metadata.requires-dev]
dev = [{ name = "ruff", specifier = ">=0.15.12" }]
[[package]]
name = "openpyxl"
version = "3.1.5"
source = { registry = "https://bytedpypi.byted.org/simple" }
dependencies = [
{ name = "et-xmlfile" },
]
sdist = { url = "https://bytedpypi.byted.org/packages/openpyxl/openpyxl-3.1.5.tar.gz", hash = "sha256:cf0e3cf56142039133628b5acffe8ef0c12bc902d2aadd3e0fe5878dc08d1050" }
wheels = [
{ url = "https://bytedpypi.byted.org/packages/openpyxl/openpyxl-3.1.5-py2.py3-none-any.whl", hash = "sha256:5282c12b107bffeef825f4617dc029afaf41d0ea60823bbb665ef3079dc79de2" },
]
[[package]]
name = "pillow"
version = "12.2.0"
source = { registry = "https://bytedpypi.byted.org/simple" }
sdist = { url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0.tar.gz", hash = "sha256:a830b1a40919539d07806aa58e1b114df53ddd43213d9c8b75847eee6c0182b5" }
wheels = [
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:8be29e59487a79f173507c30ddf57e733a357f67881430449bb32614075a40ab" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:71cde9a1e1551df7d34a25462fc60325e8a11a82cc2e2f54578e5e9a1e153d65" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f490f9368b6fc026f021db16d7ec2fbf7d89e2edb42e8ec09d2c60505f5729c7" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8bd7903a5f2a4545f6fd5935c90058b89d30045568985a71c79f5fd6edf9b91e" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3997232e10d2920a68d25191392e3a4487d8183039e1c74c2297f00ed1c50705" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e74473c875d78b8e9d5da2a70f7099549f9eb37ded4e2f6a463e60125bccd176" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:56a3f9c60a13133a98ecff6197af34d7824de9b7b38c3654861a725c970c197b" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:90e6f81de50ad6b534cab6e5aef77ff6e37722b2f5d908686f4a5c9eba17a909" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp311-cp311-win32.whl", hash = "sha256:8c984051042858021a54926eb597d6ee3012393ce9c181814115df4c60b9a808" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:6e6b2a0c538fc200b38ff9eb6628228b77908c319a005815f2dde585a0664b60" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp311-cp311-win_arm64.whl", hash = "sha256:9a8a34cc89c67a65ea7437ce257cea81a9dad65b29805f3ecee8c8fe8ff25ffe" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2d192a155bbcec180f8564f693e6fd9bccff5a7af9b32e2e4bf8c9c69dbad6b5" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f3f40b3c5a968281fd507d519e444c35f0ff171237f4fdde090dd60699458421" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:03e7e372d5240cc23e9f07deca4d775c0817bffc641b01e9c3af208dbd300987" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b86024e52a1b269467a802258c25521e6d742349d760728092e1bc2d135b4d76" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7371b48c4fa448d20d2714c9a1f775a81155050d383333e0a6c15b1123dda005" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:62f5409336adb0663b7caa0da5c7d9e7bdbaae9ce761d34669420c2a801b2780" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:01afa7cf67f74f09523699b4e88c73fb55c13346d212a59a2db1f86b0a63e8c5" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fc3d34d4a8fbec3e88a79b92e5465e0f9b842b628675850d860b8bd300b159f5" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp312-cp312-win32.whl", hash = "sha256:58f62cc0f00fd29e64b29f4fd923ffdb3859c9f9e6105bfc37ba1d08994e8940" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:7f84204dee22a783350679a0333981df803dac21a0190d706a50475e361c93f5" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp312-cp312-win_arm64.whl", hash = "sha256:af73337013e0b3b46f175e79492d96845b16126ddf79c438d7ea7ff27783a414" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:8297651f5b5679c19968abefd6bb84d95fe30ef712eb1b2d9b2d31ca61267f4c" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:50d8520da2a6ce0af445fa6d648c4273c3eeefbc32d7ce049f22e8b5c3daecc2" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:766cef22385fa1091258ad7e6216792b156dc16d8d3fa607e7545b2b72061f1c" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5d2fd0fa6b5d9d1de415060363433f28da8b1526c1c129020435e186794b3795" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:56b25336f502b6ed02e889f4ece894a72612fe885889a6e8c4c80239ff6e5f5f" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f1c943e96e85df3d3478f7b691f229887e143f81fedab9b20205349ab04d73ed" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:03f6fab9219220f041c74aeaa2939ff0062bd5c364ba9ce037197f4c6d498cd9" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5cdfebd752ec52bf5bb4e35d9c64b40826bc5b40a13df7c3cda20a2c03a0f5ed" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:eedf4b74eda2b5a4b2b2fb4c006d6295df3bf29e459e198c90ea48e130dc75c3" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:00a2865911330191c0b818c59103b58a5e697cae67042366970a6b6f1b20b7f9" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1e1757442ed87f4912397c6d35a0db6a7b52592156014706f17658ff58bbf795" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp313-cp313-win32.whl", hash = "sha256:144748b3af2d1b358d41286056d0003f47cb339b8c43a9ea42f5fea4d8c66b6e" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:390ede346628ccc626e5730107cde16c42d3836b89662a115a921f28440e6a3b" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp313-cp313-win_arm64.whl", hash = "sha256:8023abc91fba39036dbce14a7d6535632f99c0b857807cbbbf21ecc9f4717f06" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:042db20a421b9bafecc4b84a8b6e444686bd9d836c7fd24542db3e7df7baad9b" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:dd025009355c926a84a612fecf58bb315a3f6814b17ead51a8e48d3823d9087f" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:88ddbc66737e277852913bd1e07c150cc7bb124539f94c4e2df5344494e0a612" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d362d1878f00c142b7e1a16e6e5e780f02be8195123f164edf7eddd911eefe7c" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2c727a6d53cb0018aadd8018c2b938376af27914a68a492f59dfcaca650d5eea" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:efd8c21c98c5cc60653bcb311bef2ce0401642b7ce9d09e03a7da87c878289d4" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9f08483a632889536b8139663db60f6724bfcb443c96f1b18855860d7d5c0fd4" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dac8d77255a37e81a2efcbd1fc05f1c15ee82200e6c240d7e127e25e365c39ea" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp313-cp313t-win32.whl", hash = "sha256:ee3120ae9dff32f121610bb08e4313be87e03efeadfc6c0d18f89127e24d0c24" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp313-cp313t-win_amd64.whl", hash = "sha256:325ca0528c6788d2a6c3d40e3568639398137346c3d6e66bb61db96b96511c98" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp313-cp313t-win_arm64.whl", hash = "sha256:2e5a76d03a6c6dcef67edabda7a52494afa4035021a79c8558e14af25313d453" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:3adc9215e8be0448ed6e814966ecf3d9952f0ea40eb14e89a102b87f450660d8" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:6a9adfc6d24b10f89588096364cc726174118c62130c817c2837c60cf08a392b" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:6a6e67ea2e6feda684ed370f9a1c52e7a243631c025ba42149a2cc5934dec295" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:2bb4a8d594eacdfc59d9e5ad972aa8afdd48d584ffd5f13a937a664c3e7db0ed" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:80b2da48193b2f33ed0c32c38140f9d3186583ce7d516526d462645fd98660ae" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:22db17c68434de69d8ecfc2fe821569195c0c373b25cccb9cbdacf2c6e53c601" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7b14cc0106cd9aecda615dd6903840a058b4700fcb817687d0ee4fc8b6e389be" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8cbeb542b2ebc6fcdacabf8aca8c1a97c9b3ad3927d46b8723f9d4f033288a0f" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4bfd07bc812fbd20395212969e41931001fd59eb55a60658b0e5710872e95286" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:9aba9a17b623ef750a4d11b742cbafffeb48a869821252b30ee21b5e91392c50" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:deede7c263feb25dba4e82ea23058a235dcc2fe1f6021025dc71f2b618e26104" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp314-cp314-win32.whl", hash = "sha256:632ff19b2778e43162304d50da0181ce24ac5bb8180122cbe1bf4673428328c7" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp314-cp314-win_amd64.whl", hash = "sha256:4e6c62e9d237e9b65fac06857d511e90d8461a32adcc1b9065ea0c0fa3a28150" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp314-cp314-win_arm64.whl", hash = "sha256:b1c1fbd8a5a1af3412a0810d060a78b5136ec0836c8a4ef9aa11807f2a22f4e1" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:57850958fe9c751670e49b2cecf6294acc99e562531f4bd317fa5ddee2068463" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:d5d38f1411c0ed9f97bcb49b7bd59b6b7c314e0e27420e34d99d844b9ce3b6f3" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5c0a9f29ca8e79f09de89293f82fc9b0270bb4af1d58bc98f540cc4aedf03166" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1610dd6c61621ae1cf811bef44d77e149ce3f7b95afe66a4512f8c59f25d9ebe" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a34329707af4f73cf1782a36cd2289c0368880654a2c11f027bcee9052d35dd" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8e9c4f5b3c546fa3458a29ab22646c1c6c787ea8f5ef51300e5a60300736905e" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:fb043ee2f06b41473269765c2feae53fc2e2fbf96e5e22ca94fb5ad677856f06" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f278f034eb75b4e8a13a54a876cc4a5ab39173d2cdd93a638e1b467fc545ac43" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp314-cp314t-win32.whl", hash = "sha256:6bb77b2dcb06b20f9f4b4a8454caa581cd4dd0643a08bacf821216a16d9c8354" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp314-cp314t-win_amd64.whl", hash = "sha256:6562ace0d3fb5f20ed7290f1f929cae41b25ae29528f2af1722966a0a02e2aa1" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-cp314-cp314t-win_arm64.whl", hash = "sha256:aa88ccfe4e32d362816319ed727a004423aab09c5cea43c01a4b435643fa34eb" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0538bd5e05efec03ae613fd89c4ce0368ecd2ba239cc25b9f9be7ed426b0af1f" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:394167b21da716608eac917c60aa9b969421b5dcbbe02ae7f013e7b85811c69d" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5d04bfa02cc2d23b497d1e90a0f927070043f6cbf303e738300532379a4b4e0f" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0c838a5125cee37e68edec915651521191cef1e6aa336b855f495766e77a366e" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4a6c9fa44005fa37a91ebfc95d081e8079757d2e904b27103f4f5fa6f0bf78c0" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:25373b66e0dd5905ed63fa3cae13c82fbddf3079f2c8bf15c6fb6a35586324c1" },
{ url = "https://bytedpypi.byted.org/packages/pillow/pillow-12.2.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:bfa9c230d2fe991bed5318a5f119bd6780cda2915cca595393649fc118ab895e" },
]
[[package]]
name = "ruff"
version = "0.15.12"
source = { registry = "https://bytedpypi.byted.org/simple" }
sdist = { url = "https://bytedpypi.byted.org/packages/ruff/ruff-0.15.12.tar.gz", hash = "sha256:ecea26adb26b4232c0c2ca19ccbc0083a68344180bba2a600605538ce51a40a6" }
wheels = [
{ url = "https://bytedpypi.byted.org/packages/ruff/ruff-0.15.12-py3-none-linux_armv6l.whl", hash = "sha256:f86f176e188e94d6bdbc09f09bfd9dc729059ad93d0e7390b5a73efe19f8861c" },
{ url = "https://bytedpypi.byted.org/packages/ruff/ruff-0.15.12-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:e3bcd123364c3770b8e1b7baaf343cc99a35f197c5c6e8af79015c666c423a6c" },
{ url = "https://bytedpypi.byted.org/packages/ruff/ruff-0.15.12-py3-none-macosx_11_0_arm64.whl", hash = "sha256:fe87510d000220aa1ed530d4448a7c696a0cae1213e5ec30e5874287b66557b5" },
{ url = "https://bytedpypi.byted.org/packages/ruff/ruff-0.15.12-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:84a1630093121375a3e2a95b4a6dc7b59e2b4ee76216e32d81aae550a832d002" },
{ url = "https://bytedpypi.byted.org/packages/ruff/ruff-0.15.12-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fb129f40f114f089ebe0ca56c0d251cf2061b17651d464bb6478dc01e69f11f5" },
{ url = "https://bytedpypi.byted.org/packages/ruff/ruff-0.15.12-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b0c862b172d695db7598426b8af465e7e9ac00a3ea2a3630ee67eb82e366aaa6" },
{ url = "https://bytedpypi.byted.org/packages/ruff/ruff-0.15.12-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2849ea9f3484c3aca43a82f484210370319e7170df4dfe4843395ddf6c57bc33" },
{ url = "https://bytedpypi.byted.org/packages/ruff/ruff-0.15.12-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9e77c7e51c07fe396826d5969a5b846d9cd4c402535835fb6e21ce8b28fef847" },
{ url = "https://bytedpypi.byted.org/packages/ruff/ruff-0.15.12-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83b2f4f2f3b1026b5fb449b467d9264bf22067b600f7b6f41fc5958909f449d0" },
{ url = "https://bytedpypi.byted.org/packages/ruff/ruff-0.15.12-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:9ba3b8f1afd7e2e43d8943e55f249e13f9682fde09711644a6e7290eb4f3e339" },
{ url = "https://bytedpypi.byted.org/packages/ruff/ruff-0.15.12-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:e852ba9fdc890655e1d78f2df1499efbe0e54126bd405362154a75e2bde159c5" },
{ url = "https://bytedpypi.byted.org/packages/ruff/ruff-0.15.12-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:dd8aed930da53780d22fc70bdf84452c843cf64f8cb4eb38984319c24c5cd5fd" },
{ url = "https://bytedpypi.byted.org/packages/ruff/ruff-0.15.12-py3-none-musllinux_1_2_i686.whl", hash = "sha256:01da3988d225628b709493d7dc67c3b9b12c0210016b08690ef9bd27970b262b" },
{ url = "https://bytedpypi.byted.org/packages/ruff/ruff-0.15.12-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:9cae0f92bd5700d1213188b31cd3bdd2b315361296d10b96b8e2337d3d11f53e" },
{ url = "https://bytedpypi.byted.org/packages/ruff/ruff-0.15.12-py3-none-win32.whl", hash = "sha256:d0185894e038d7043ba8fd6aee7499ece6462dc0ea9f1e260c7451807c714c20" },
{ url = "https://bytedpypi.byted.org/packages/ruff/ruff-0.15.12-py3-none-win_amd64.whl", hash = "sha256:c87a162d61ab3adca47c03f7f717c68672edec7d1b5499e652331780fe74950d" },
{ url = "https://bytedpypi.byted.org/packages/ruff/ruff-0.15.12-py3-none-win_arm64.whl", hash = "sha256:a538f7a82d061cee7be55542aca1d86d1393d55d81d4fcc314370f4340930d4f" },
]