57 lines
1.7 KiB
Python
57 lines
1.7 KiB
Python
"""数据文件各环节共用的异常、上限和警告文案的写法"""
|
||
|
||
from collections.abc import Callable, Sequence
|
||
|
||
# 每张表的数据行数上限
|
||
MAX_TABLE_ROWS = 1_000_000
|
||
|
||
UNSUPPORTED_FORMAT = "不支持的文件格式,支持 CSV、TSV、Excel、JSON、JSONL、Parquet"
|
||
|
||
|
||
class DataFileError(Exception):
|
||
"""文件无法接收或解析;status 是返回给调用方的 HTTP 状态码,message 可以直接展示
|
||
|
||
解析在子进程里执行,异常要能跨进程传递,所以参数原样放进 args
|
||
"""
|
||
|
||
def __init__(self, status: int, message: str):
|
||
super().__init__(status, message)
|
||
self.status = status
|
||
self.message = message
|
||
|
||
def __str__(self) -> str:
|
||
return self.message
|
||
|
||
|
||
def where(sheet: str | None) -> str:
|
||
"""警告和错误信息的位置前缀:Excel 写 sheet 名,其他格式不写"""
|
||
return f"{sheet}:" if sheet else ""
|
||
|
||
|
||
def brief(items: Sequence[str], sep: str = "、", limit: int = 5) -> str:
|
||
"""警告里列举的内容最多写 limit 个,多出的用“等”概括"""
|
||
return sep.join(items[:limit]) + ("等" if len(items) > limit else "")
|
||
|
||
|
||
def rows_exceeded(sheet: str | None) -> DataFileError:
|
||
return DataFileError(
|
||
422, f"{where(sheet)}超过 {MAX_TABLE_ROWS // 10_000} 万行,请拆分后上传"
|
||
)
|
||
|
||
|
||
# 解析进度的回调:参数是当前环节内已完成的比例,0 到 1
|
||
Reporter = Callable[[float], None]
|
||
|
||
|
||
def no_report(fraction: float) -> None:
|
||
pass
|
||
|
||
|
||
def scaled(report: Reporter, start: float, end: float) -> Reporter:
|
||
"""把环节内的进度映射到上一级进度的 start 到 end 之间"""
|
||
|
||
def inner(fraction: float) -> None:
|
||
report(start + (end - start) * min(max(fraction, 0.0), 1.0))
|
||
|
||
return inner
|