v1.0.0: PinMAP → PinList 转换器 首次发布

- 支持 .xls (BIFF8) 和 .xlsx 格式
- GUI 文件选择 + 命令行双模式
- 智能结构验证(重复/间隙/空单元格检测)
- 逆时针 PinMAP → 顺时针 PinList 自动转换
- Python 标准库,零第三方依赖
This commit is contained in:
2026-05-25 13:27:08 +08:00
commit 6b718f7af3
24 changed files with 2720 additions and 0 deletions

103
Code/src/validator.py Normal file
View File

@@ -0,0 +1,103 @@
"""PinMAP data validator.
Validates a parsed PinMAP for structural and data integrity:
1. Pin-number uniqueness
2. Pin-number continuity (1..N with no gaps)
3. Missing PinName detection (warning, defaults to "NC")
4. Rectangular-structure sanity
Usage
-----
>>> from validator import validate_pinmap
>>> result = validate_pinmap(pinmap)
>>> if result.is_valid:
... print("All good")
... else:
... for e in result.errors:
... print(f"[ERROR] {e.message}: {e.details}")
"""
from collections import Counter
from models import PinMAP, ValidationResult, ValidationError
def validate_pinmap(pinmap: PinMAP) -> ValidationResult:
"""Validate a PinMAP and return a ValidationResult.
Checks performed
----------------
1. **Uniqueness** — every pin number must appear exactly once.
2. **Continuity** — pin numbers must form the sequence 1, 2, …, N
with no gaps.
3. **PinName completeness** — pins with empty / whitespace-only names
generate a *warning* (they will default to "NC" in the output).
4. **Structure** — width and height must each be ≥ 2.
Parameters
----------
pinmap : PinMAP
A pin map produced by ``pinmap_parser.parse_pinmap``.
Returns
-------
ValidationResult
"""
result = ValidationResult(is_valid=True, errors=[], warnings=[])
numbers = [p.number for p in pinmap.pins]
# ── 1. Uniqueness ────────────────────────────────────────────
if len(numbers) != len(set(numbers)):
counts = Counter(numbers)
duplicates = sorted(n for n, c in counts.items() if c > 1)
result.errors.append(ValidationError(
level="error",
message="Pin序号重复",
details=f"重复的序号: {duplicates}",
))
# ── 2. Continuity ────────────────────────────────────────────
if numbers:
expected = set(range(1, max(numbers) + 1))
actual = set(numbers)
missing = expected - actual
if missing:
result.errors.append(ValidationError(
level="error",
message="Pin序号不连续",
details=f"缺失的序号: {sorted(missing)}",
))
# ── 3. PinName completeness ──────────────────────────────────
missing_names = [
p for p in pinmap.pins
if not p.name or not p.name.strip()
]
if missing_names:
result.warnings.append(ValidationError(
level="warning",
message=(
f"检测到 {len(missing_names)} 个引脚缺少 PinName"
),
details=(
f"缺失引脚序号: {[p.number for p in missing_names]}"
f"将默认为 NC"
),
))
# ── 4. Structure sanity ──────────────────────────────────────
if pinmap.width < 2 or pinmap.height < 2:
result.errors.append(ValidationError(
level="error",
message="方形结构不完整",
details=(
f"尺寸: {pinmap.width}x{pinmap.height},至少需要 2x2"
),
))
# ── Final verdict ────────────────────────────────────────────
if result.errors:
result.is_valid = False
return result