- 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
200 lines
18 KiB
Markdown
200 lines
18 KiB
Markdown
# 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`.
|