Skip to content

Commit 9bc5c5b

Browse files
committed
fix: resolve ty type errors and update AGENTS rules
1 parent 94ee006 commit 9bc5c5b

5 files changed

Lines changed: 49 additions & 5 deletions

File tree

AGENTS.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@ source .venv/bin/activate # Linux/macOS
2222
pytest -n auto
2323
```
2424

25+
测试目录结构:
26+
27+
| 目录 | 说明 |
28+
|------|------|
29+
| `tests/unit/` | pytest 自动运行的单元测试 |
30+
| `tests/manual/` | 需真实设备的手动 e2e 测试 |
31+
2532
## pre-commit 检查
2633

2734
提交前务必运行:
@@ -32,6 +39,39 @@ pre-commit run --all-files
3239

3340
包含 **Ruff**(格式化与 lint)和 **ty**(类型检查)。
3441

42+
## 类型检查
43+
44+
本项目使用 **ty**(Astral 出品的 Python 类型检查器)进行静态类型检查。
45+
46+
- 优先通过正确的类型注解、返回值标注和类型窄化来消除类型错误。
47+
- **禁止**在工作代码中使用 `typing.cast` 来掩盖类型问题;`cast` 只允许在测试文件的 Mock 场景中使用。
48+
- 若类型检查器因容器型变(如 `list` 的 invariant)报错,优先考虑将函数参数改为 `Sequence``Mapping` 等协变抽象基类,而非使用 `cast`
49+
- 修复类型问题时尽量保持最小改动,避免不必要的重构。
50+
51+
### `ty: ignore` 注释规范
52+
53+
当必须通过注释忽略类型错误时,**必须使用 ty 原生格式**
54+
55+
```python
56+
# 正确
57+
c.r = 10 # ty: ignore[invalid-assignment]
58+
ctrl._device.shell.assert_called_once_with('input tap 480 270') # ty: ignore[unresolved-attribute]
59+
60+
# 错误 —— ty 无法识别 mypy 的 error code
61+
# type: ignore[invalid-assignment]
62+
# type: ignore[misc]
63+
64+
# 错误 —— 裸 ignore 会被 ruff PGH003 拦截,且无法精确控制
65+
# type: ignore
66+
# type: ignore # noqa: PGH003
67+
```
68+
69+
> 项目已启用 `unused-type-ignore-comment = "error"`,未使用的 `# ty: ignore[...]` 会导致 CI 失败。
70+
71+
## 单元测试要求
72+
73+
新增功能或修改核心逻辑时,必须在 `tests/unit/` 下提供对应的 pytest 单元测试。测试文件应与被测源文件一一对应。
74+
3575
## 约定式提交
3676

3777
## 文档

autowsgr/combat/engine.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ def __init__(
8383
def fight( # noqa: PLR0912
8484
self,
8585
plan: CombatPlan,
86-
initial_ship_stats: list[ShipDamageState],
86+
initial_ship_stats: list[ShipDamageState] | None,
8787
) -> CombatResult:
8888
"""执行一次完整的战斗循环。
8989

autowsgr/image_resources/keys.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ def _build_map() -> dict[TemplateKey, list[ImageTemplate]]:
106106
TemplateKey.END_EXERCISE_PAGE: [T.END_EXERCISE_PAGE],
107107
# 船坞已满
108108
TemplateKey.DOCK_FULL: [T.DOCK_FULL],
109+
# 战役次数耗尽
110+
TemplateKey.BATTLE_TIMES_EXCEED: [T.BATTLE_TIMES_EXCEED],
109111
# 战果评级
110112
TemplateKey.GRADE_SS: [T.Result.SS],
111113
TemplateKey.GRADE_S: [T.Result.S],

autowsgr/infra/logger.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -382,11 +382,11 @@ def save_image(
382382
保存的文件路径,未保存时返回 None。
383383
"""
384384

385-
target_dir = str(img_dir or _image_dir)
386-
target_dir = Path(target_dir)
385+
target_dir = img_dir or _image_dir
387386
if target_dir is None:
388387
raise ValueError('未配置图片保存目录,请在 setup_logger 中设置 log_dir 并启用 save_images')
389388

389+
target_dir = Path(target_dir)
390390
target_dir.mkdir(parents=True, exist_ok=True)
391391
ts = _time.strftime('%H%M%S') + f'_{int(_time.monotonic() * 1000) % 1000:03d}'
392392
filename = f'{tag}_{ts}.png'

pyproject.toml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ dev = [
3535
"pytest>=8.0",
3636
"pytest-cov",
3737
"pytest-xdist",
38+
"httpx>=0.28.0",
3839
"requests>=2.32.5",
3940
"beautifulsoup4",
4041
]
@@ -50,7 +51,8 @@ path = "autowsgr/__init__.py"
5051
ignore-words = "docs/spelling_wordlist.txt"
5152

5253
[tool.pytest.ini_options]
53-
testpaths = ["testing"]
54+
testpaths = ["tests/unit"]
55+
addopts = ["--import-mode=importlib"]
5456

5557
[tool.ruff]
5658
target-version = "py312"
@@ -170,7 +172,7 @@ extend-safe-fixes = [
170172
"__init__.py" = [
171173
"F401", # unused-import
172174
]
173-
"testing/**" = [
175+
"tests/**" = [
174176
"T201", # print
175177
]
176178
"tools/**" = [

0 commit comments

Comments
 (0)