v1.1.0: 增加交互提示、路径输入、窗口属性配置
- main.py: 增加show_banner()启动说明、各阶段[INFO]日志、结果摘要、任意键退出 - file_selector.py: 重写为路径输入→验证→空输入弹窗回退→不存在循环重试 - run.bat: 新建启动脚本(chcp 65001, mode con cols=80 lines=20, color 0B, title固定署名, pause) - Code/docs/modification-assessment.md: 修改需求评估文档
This commit is contained in:
103
Releases/v1.0.1/source/validator.py
Normal file
103
Releases/v1.0.1/source/validator.py
Normal 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
|
||||
Reference in New Issue
Block a user