Files
OpenClaw Coder 5ff5993d98
CI / quality (push) Canceled after 0s
CI / test (3.10) (push) Canceled after 0s
CI / test (3.11) (push) Canceled after 0s
CI / test (3.12) (push) Canceled after 0s
CI / build-check (push) Canceled after 0s
feat(P4): extend tests, coverage config, build license fix, tasks.md
- geometry: property guard hex nut across-flats (regression guard)
- gui tests: rewrite to ASCII + cover _type_name/_mass helper paths
- coverage: source=fastengen, omit gui.py (UI headless); total 87%
- build: license-files for setuptools, sdist+wheel OK
- tasks.md: P4 recorded
2026-11-11 17:12:54 +10:00

200 lines
18 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# FastenGen — задачи и roadmap
Рабочий файл для отслеживания прогресса между сессиями. Обновляется после каждого шага.
- **Репозиторий:** Gitea `admin/fastengen`, ветка `master`
- **Тесты:** `PYTHONPATH=/tmp/fastengen/src python3 -m pytest -q` (полный ~5-8 мин; быстрый `-k "not gen_all"` и `-k "not gen_all_extended"`)
- **Python:** 3.10, cadquery 2.7.0
- **Доступ:** `/tmp/fastengen` — dev-копия, рабочий репозиторий на Gitea `admin/fastengen`
---
## 🔴 В работе / только что сделано
### #1 Закрытие пробелов API — **ГОТОВО** (commit `5fa3ac7`)
Замкнуть публичный API, добавить отсутствующие `add_*`, задедупить итераторы, добавить подкоманды CLI, сгенерировать реальный catalog.
- [x] `catalog.add_washer_l()` — увеличенная шайбиц ГОСТ 11372-78
- [x] `catalog.add_bolt_set()` — винт-набронник ГОСТ 1170-84
- [x] `catalog.add_all_extended()` — все 10 расшиremium семейств (7802,1149,5916,11889,11394,6402,13463,25709,Р51472,11372)
- [x] **fix коллизии id:** `from_spec()` берёт `id` из `model_filename(spec)[:-5]` (до этого `nut_high`/`nut_baran`/`nut_specing` → все `nut_M12`)
- [x] `standard.py model_filename()` — уникальные имена подтипов (`nut_high_M12`, `washer_grever_M12`, `washer_M12_large.step` и т.д.)
- [x] `cli.py` `_save_and_show()` — единый шаблон, все `*-gen` теперь сохраняют запись в каталог
- [x] Подкоманды: `gen-all-extended`, `washer-l-gen`, `bolt-set-gen`
- [x] Тесты: `test_cli_single_gen_saves_to_catalog`, `test_add_all_extended_covers_all_types`, `test_model_filename_large_washer_distinguished`, `test_catalog_ids_unique_for_large_washer`
- [x] **82 теста проходят (100%)**
- [x] Закоммичено и запушено в `admin/fastengen`
---
## 🟡 Следующий (P2)
### #2 Ведомость изделий по ГОСТ 2.119 — **ГОТОВО** (commit на Gitea)
Сводная ведомость из каталога. Команда `list` уже печатает таблицу — вынес в `.xlsx`/`.csv`/`.md`.
- [x] `src/fastengen/vedomost.py`: класс `Vedomost` (группировка записей по (наименование, ГОСТ, материал) → позиция), `render_markdown/csv/txt`, `write_xlsx`
- [x] CLI: `fastengen vedomost --catalog cat.json --format md|csv|txt|xlsx`, опция `--output` для xlsx
- [x] Тесты: `tests/test_vedomost.py` (7 тестов, все прошли)
- [x] **fix в vedomost**: размер парсится и из кириллической «М» (М6), и из «D10»/«6×80»**
- [x] **P2.2 (11.11, commit 6f7697e): автозаполнение графов ГОСТ 2.119** — ОКПД2 по типу изделия,
product_type для ведомости ВЗ, `render_markdown_full`, CLI-опция `--full`
- [x] **P2 полностью готов** на Gitea: `fastengen vedomost --cat cat.json --format md|csv|txt|xlsx [--full]`
- [ ] ✅ **Заметка об обнаруженном баге:** `src/fastengen/cli.py` не компилировался из-за **незакрытого тройного кавычка** в module docstring (я случайно затёр закрывающие `"""` при редактировании примеров → Python читал docstring до конца файла и падал на `—`). Все CLI-тесты (`from fastengen.cli import main`) падали с `SyntaxError: invalid character '—'`. **Исправлено: добавлены `"""` после примеров.** (Этот Python 3.10 без PEP 540 UTF-8 mode не парсит em-dash в коде.)
- [ ] **Наблюдение по данным (не баг vedomost):** в `product_params` (standard.py) для гаек material = «Сталь 8» (strength_class="8"), у шайб/саморезов нет «Мn»-размера в designation — vedomost корректно отражает то, что в каталоге.
### Заметка по окружению
- Тесты запускаются `PYTHONPATH=/tmp/fastengen/src python3 -m pytest`. На **этом** Python 3.10 (beze) UTF-8-режим в исходниках отключён — em-dash `—` **в коде** ломает парсинг. В docstrings/комментариях/строках помечайте аккуратно; лучше ASCII-дефис в коде, русские символы только в строках/помечах.
---
## ⚪ Отложено (P3)
- GUI (PyQt предпросмотр STEP)
- Конвертер в КОМПАС (`.con`/`.kds`)
- Локальный PyPI/pipx-сборка
- Конвертер bearingsinfo → boltgen
- Слияние устаревших `get_stud()`/`get_self_tacker()`/`iter_studs`/`iter_self_tackers` с `_long`/`_gost` версиями
- Property-тесты на рандомных размерах
---
## 📌 Контекст / договорённости
- `/tmp/fastengen` — dev-копия, а не настоящий workspace репозитория.
- `model_filename()` — единственный источник и `id`, и `model_file` (в `from_spec`).
- Долгие команды (`gen_all`, `gen-all-extended`) генерят тысячи STEP-моделей — не гонять в быстрых прогонах.
---
## 🔵 P3 (масса + геометрия) — начато (commit 74bc4b0)
### #3 Геометрический баг шестигранных головок — **Исправлено**
**Баг:** `cadquery Workplane.polygon(6, r)` даёт шестигранник with across-flats (расстояние между плоскостями, «под ключ») = `r·√3/2`, а не `r`. Все 8 сайтов использовали `head_r = S/2` или `S/√3` → across-flats был ≈ `0.866·S` вместо `S`. Модели были занижены по размеру головки (и по массе ~0.75×). Исправлено на `head_r = 2·S/√3` для across-flats = S.
- [x] Фикс 8 сайтов: bolts, nuts, bolt_set, nut_high, nut_baran, nut_specing (model.py)
- [x] Проверено по шагу: M12 nut ≈ 21.7 г (ГОСТ 5915 ~20-22г), M12×60 bolt ≈ 70 г (ГОСТ 7805 ~72г)
- [x] **Все STEP-модели нужно переренерировать** (старые занижены). Модель на диске пока отсутствуют
### #4 Масса 1 шт. из геометрии STEP — **Готово**
- [x] `src/fastengen/mass.py`: `step_volume_mm3()` через `OCP.BRepGProp.VolumeProperties_s`, `mass_of()` = объём × плотность (GOST 24705, сталь 7.85 г/см³ и т.д.), `_translit_lower()` для кириллических материалов (Сталь 8, Сталь 65Г)
- [x] `vedomost.build()` считает «Масса,г» по геометрии (`models_dir`), `cli` vedomost получил `--dir` для пути к моделям
- [x] `tests/test_mass.py` (4 теста): nut M12, bolt M12×60, washer>0, density default
---
## 🔵 P3 GUI — завершено (commit 76db982)
`fastengen gui --catalog cat.json --dir models` — графический просмотр каталога (tkinter, stdlib, без PyQt).
- [x] `src/fastengen/gui.py` `MainWindow`: фильтр по типу (bolt/nut/washer/stud/selftacker/screw), список с массой 1 шт. (из STEP-геометрии), двойной клик = переренерация STEP, экспорт ведомости md/csv/txt
- [x] `run_gui()` автоматически создаёт пустой каталог, если файла нет
- [x] `cli.py`: подкоманда `gui` (+ `--catalog`, `--dir`)
- [x] `tests/test_gui.py`: `_type_name` логика фильтра + отбор записей (2 теста)
- [x] Закоммичено и запушено в `admin/fastengen`
---
## 🔵 P3.1 Валидация геометрии по ГОСТ — **Готово** (commit c9d1f82)
Паттерн из **PartCAD / cq_warehouse**: семью части валидируется проверкой что сгенерированная геометрия воспроизводит **номинальные размеры стандарта** (across-flats S, наружный диаметр D, высота головки k) в пределах допуска, а не «масса похоже».
- [x] `src/fastengen/validate_geom.py`: `validate_model(path)` читает STEP через OCC, берёт bbox через `cq.Shape.BoundingBox()`, сверяет ключевые размеры с таблицами ГОСТа (`_BOLT_DIMS`, `_NUT_DIMS`, `_NUT_HIGH_DIMS`, `_WASHER_DIMS`, `_WASHER_L_DIMS`) в допуске 4%.
- [x] **Ключевой инсайт:** bbox шестигранника: min planar extent = across-flats, max = across-corners (`2S/√3`). Используется `min()` для S.
- [x] `DimensionResult`: `.ok`, `.failed`, `.checks` (dim -> measured). `validate_dir(models_dir)` — валидация всей папки.
- [x] `tests/test_validate_geom.py` (30 тестов): все размеры bolts/nuts/washers соответствуют ГОСТу, rejection при неверном S, sanity-тест bbox.
- [x] Полный suite (без gen_all) + все 30 тестов валидации проходят.
- [x] Закоммичено и запушено в `admin/fastengen`
---
## 🔵 P3.2 Конвертер в КОМПАС (.con) — **Готово**
Паттерн: KOMPAS `.con` — это XML-документ с product params. Конвертер генерит контейнер КОМПАСа (Gost, OKPД2, product params, ссылка на STEP); реальный импорт геометрии в КОМПАС делает сам КОМПАС через API.
- [x] `src/fastengen/kompas.py`: `build_document(rec)`/`save_document(rec, path)` — KOMPAS .con XML. `convert_step_to_kompas_template(step_path, rec)` — STEP->KOMPAS import container.
- [x] OKPД2 по типу: Bolt 28.93.21.110, Nut .210, Washer .310, Stud .410, SelfTacker .510, Screw .610, default .000.
- [x] `cli.py`: `fastengen kompas --output dir` — экспорт всех изделий каталога в .con.
- [x] `tests/test_kompas.py` (5): OKPД2 по типу, valid XML, save roundtrip, default OKPД2, end-to-end CLI. Все проходят.
- [x] Закоммичено и запушено.
- ⚠️ КОМПАС — Windows CAD-система, на Linux-host не установлен. Сгенерен валидный `.con` XML; импорт геометрии в КОМПАС не тестировался (нет API).
## 🔵 P3.3 Упаковка (pyproject) — проверено
- [x] `pyproject.toml`: name=FastenGen v0.2.0, console scripts `fastengen` + `fasten-gen`, deps `cadquery`, pytest config.
- [x] `pip install .` в venv прошёл, `fastengen --help` работает.
- [x] `tests/test_packaging.py`: metadata pyproject parseable (tomllib 3.11 + fallback 3.10).
## 🔵 P3.4 Слияние legacy-функций (мертвый код) — **Готово**
- Удалён dead code: `get_stud`/`get_self_tacker`, `iter_studs`/`iter_self_tackers`, `_stud_params`/`_self_tacker_params`, классы `StudSpec`/`SelfTackerSpec`/`BoltSetSpec2`.
- Активные пути: `StudSpecLong` (get_stud_long/iter_studs_long) и `SelfTackerSpecGost` (get_self_tacker_gost/iter_self_tackers_gost) — единственные wired-варианты.
- Удалён dead `build_stud/generate_stud`, `build_self_tacker/generate_self_tacker`, `_make_self_tacker_head`, `catalog add_stud/add_self_tacker`.
- ⚠️ Осторожно: после чистки `model_filename` потерял ветки `BoltSetSpec`/`BoltSpecHigh`/`ScrewPotaySpec` — восстановил; `model.py` вернул `BoltSpec/NutSpec/WasherSpec/BoltSetSpec` в import.
- Тесты: 131 passed, 3 deselected.
## 🔵 P3.5 Regen всех STEP-моделей + property-тесты — **Готово**
- Сгенерировал заново все 661 STEP-модели (`gen-all-extended`) в `out/`, catalog.json обновлён.
- Проверка масс vs GOST-таблицы: M30x200 bolt=1370.7g, M12 nut=21.7g, M20x60 bolt=227g, washer M12=6.8g — все ✓.
- Property-тесты геометрии (tests/test_geometry.py): positive-volume для stud_long/self_tacker_gost; across-flats==S для hex bolt head (guard против regression geometry bug).
- Итог: **139 passed in ~242s** (full suite, regen 661 STEP).
## Remaining P3
- Слияние legacy `get_stud()`/`get_self_tacker()`/`iter_studs`/`iter_self_tackers` с `_long`/`_gost` — сделано в P3.4 (мертвый код удалён, активные пути `_long`/`_gost`).
## 🔵 P4 Тесты + покрытие (P4 завершен)
### P4.1 — Расширение тестов
- `tests/test_geometry.py`: добавлен property-based guard `test_hex_nut_head_across_flats_matches_s` (parametrized по NUT_SIZES) — across-flats == S из STEP для шестигранных гаек, прямой regression guard.
- `tests/test_gui.py`: переписан на чистый ASCII (кириллица → строки/комментарии), добавлено покрытие чистых хелперов:
- `test_type_name_filter` — все ветки фильтра типов (bolt/nut/washer/stud/selftacker/screw/potay).
- `test_mass_helpers_paths` — путь без model_file → «—», путь с реальной моделью → числовая строка массы.
### P4.2 — Покрытие
- `pyproject.toml`: добавлен `[tool.coverage.run]` с `source=["fastengen"]` и `omit=["src/fastengen/gui.py"]` (UI нельзя тестировать headless; чистые хелперы покрыты отдельно).
- Итог: **87%** (было 81% до omits; gui.py исключён из счётчика). model.py 99%, standard.py 95%, kompas.py 92%.
### P4.3 — Сборка
- `pip install .` / `python -m build` — успешно (sdist + wheel).
- `pyproject.toml`: license-text → добавлен `license-files = ["LICENSE*"]` (устранена deprecated warning setuptools).
### P4.4 — CI
- `.github/workflows/ci.yml`: job `quality` (ruff), `test` гонит `tests/ -k "not gen_all"` с `--cov`, build-check собирает пакет.
### P4.5 — README
- `README.md`: обновлён под текущий API (all_extended, gui, vedomost, kompas), команды coverage/ruff, блок CI.
### Итог P4
- **145 passed, 3 deselected** (regen), `ruff check src/ tests/` — All checks passed,
покрытие 87%, сборка sdist+wheel OK. Коммитировано и запушено (master).
---
## 🟢 P4 Качество: ruff + покрытие + CI + README — **Готово**
### #4.1 Ruff (линт/форматирование)
- Настроен профиль в `pyproject.toml` (`[tool.ruff]`): E, W, F, I, B, RUF; target py310.
- Профиль отключает: `BLE001` (CAD-код ловит broad Exception по дизайну), `B008` (argparse defaults),
`E501` (русские docstrings/help-строки/ГОСТ-литералы), `RUF001/002/003` (кириллица в строках/комментариях — ГОСТ обозначения), `RUF100`.
- Авто-сортировка импортов + удаление dead code:
- `__init__.py`: 59 публичных переимпортов добавлены в `__all__` (отсортирован, RUF022).
- Удалены мёртвые присваивания: `threaded_len`/`s`/`d`/`coat`/`first_rec_for_size` в
`model.py`/`standard.py`/`validate_geom.py`/`vedomost.py`; мёртвое `self.cat` в `gui.py`.
- `vedomost.py`: `zip(..., strict=True)`.
- Переименованы переменные `l` → `ln` (E741) в cli/tests.
- Исправлены длинные строки: print в `cli.py`, assertion в `test_boltgen.py`/`test_geometry.py`,
`head_r`-комментарии в `model.py`, `cq.Compound.makeCompound`, сигнатура `generate_self_tacker_gost`,
`[*prof_pts_xy, prof_pts_xy[0]]` (RUF005).
- Тесты: убраны неиспользуемые imports (test_geometry расширенные семейства, удалены `NutSpec`/`WasherSpec`),
`.items()` → `.values()` в test_specs, `next(iter(parts.vals()))` в test_validate_geom.
- **Итог: `ruff check src/ tests/` — All checks passed.**
### #4.2 Тесты + CI
- CI (`.github/workflows/ci.yml`) расширена:新增 job `quality` (ruff на py3.12); `test` теперь гонит
`tests/ -k "not gen_all"` с `--cov`; сборка пакета в `build-check`.
- Полный suite (без regen) стабильно зелёный.
### #4.3 README
- Переписан: полный список команд (`bolt-gen`/`nut-gen`/`stud-long-gen`/`self-tacker-gen`/`gui`/`vedomost`/`kompas`),
схема каталога, API-модули, команды тестов + ruff + coverage, описание CI, блок «Окружение».
### Изменённые файлы
`src/fastengen/{__init__,model,standard,gui,validate_geom,vedomost,cli}.py`,
`tests/{test_geometry,test_boltgen,test_specs,test_validate_geom}.py`,
`pyproject.toml`, `README.md`, `.github/workflows/ci.yml`, `docs/tasks.md`.