- 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
18 KiB
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-копия, рабочий репозиторий на Giteaadmin/fastengen
🔴 В работе / только что сделано
#1 Закрытие пробелов API — ГОТОВО (commit 5fa3ac7)
Замкнуть публичный API, добавить отсутствующие add_*, задедупить итераторы, добавить подкоманды CLI, сгенерировать реальный catalog.
catalog.add_washer_l()— увеличенная шайбиц ГОСТ 11372-78catalog.add_bolt_set()— винт-набронник ГОСТ 1170-84catalog.add_all_extended()— все 10 расшиremium семейств (7802,1149,5916,11889,11394,6402,13463,25709,Р51472,11372)- fix коллизии id:
from_spec()берётidизmodel_filename(spec)[:-5](до этогоnut_high/nut_baran/nut_specing→ всеnut_M12) standard.py model_filename()— уникальные имена подтипов (nut_high_M12,washer_grever_M12,washer_M12_large.stepи т.д.)cli.py_save_and_show()— единый шаблон, все*-genтеперь сохраняют запись в каталог- Подкоманды:
gen-all-extended,washer-l-gen,bolt-set-gen - Тесты:
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 - 82 теста проходят (100%)
- Закоммичено и запушено в
admin/fastengen
🟡 Следующий (P2)
#2 Ведомость изделий по ГОСТ 2.119 — ГОТОВО (commit на Gitea)
Сводная ведомость из каталога. Команда list уже печатает таблицу — вынес в .xlsx/.csv/.md.
src/fastengen/vedomost.py: классVedomost(группировка записей по (наименование, ГОСТ, материал) → позиция),render_markdown/csv/txt,write_xlsx- CLI:
fastengen vedomost --catalog cat.json --format md|csv|txt|xlsx, опция--outputдля xlsx - Тесты:
tests/test_vedomost.py(7 тестов, все прошли) - fix в vedomost: размер парсится и из кириллической «М» (М6), и из «D10»/«6×80»**
- P2.2 (11.11, commit
6f7697e): автозаполнение графов ГОСТ 2.119 — ОКПД2 по типу изделия, product_type для ведомости ВЗ,render_markdown_full, CLI-опция--full - 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.
- Фикс 8 сайтов: bolts, nuts, bolt_set, nut_high, nut_baran, nut_specing (model.py)
- Проверено по шагу: M12 nut ≈ 21.7 г (ГОСТ 5915 ~20-22г), M12×60 bolt ≈ 70 г (ГОСТ 7805 ~72г)
- Все STEP-модели нужно переренерировать (старые занижены). Модель на диске пока отсутствуют
#4 Масса 1 шт. из геометрии STEP — Готово
src/fastengen/mass.py:step_volume_mm3()черезOCP.BRepGProp.VolumeProperties_s,mass_of()= объём × плотность (GOST 24705, сталь 7.85 г/см³ и т.д.),_translit_lower()для кириллических материалов (Сталь 8, Сталь 65Г)vedomost.build()считает «Масса,г» по геометрии (models_dir),clivedomost получил--dirдля пути к моделям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).
src/fastengen/gui.pyMainWindow: фильтр по типу (bolt/nut/washer/stud/selftacker/screw), список с массой 1 шт. (из STEP-геометрии), двойной клик = переренерация STEP, экспорт ведомости md/csv/txtrun_gui()автоматически создаёт пустой каталог, если файла нетcli.py: подкомандаgui(+--catalog,--dir)tests/test_gui.py:_type_nameлогика фильтра + отбор записей (2 теста)- Закоммичено и запушено в
admin/fastengen
🔵 P3.1 Валидация геометрии по ГОСТ — Готово (commit c9d1f82)
Паттерн из PartCAD / cq_warehouse: семью части валидируется проверкой что сгенерированная геометрия воспроизводит номинальные размеры стандарта (across-flats S, наружный диаметр D, высота головки k) в пределах допуска, а не «масса похоже».
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%.- Ключевой инсайт: bbox шестигранника: min planar extent = across-flats, max = across-corners (
2S/√3). Используетсяmin()для S. DimensionResult:.ok,.failed,.checks(dim -> measured).validate_dir(models_dir)— валидация всей папки.tests/test_validate_geom.py(30 тестов): все размеры bolts/nuts/washers соответствуют ГОСТу, rejection при неверном S, sanity-тест bbox.- Полный suite (без gen_all) + все 30 тестов валидации проходят.
- Закоммичено и запушено в
admin/fastengen
🔵 P3.2 Конвертер в КОМПАС (.con) — Готово
Паттерн: KOMPAS .con — это XML-документ с product params. Конвертер генерит контейнер КОМПАСа (Gost, OKPД2, product params, ссылка на STEP); реальный импорт геометрии в КОМПАС делает сам КОМПАС через API.
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.- OKPД2 по типу: Bolt 28.93.21.110, Nut .210, Washer .310, Stud .410, SelfTacker .510, Screw .610, default .000.
cli.py:fastengen kompas --output dir— экспорт всех изделий каталога в .con.tests/test_kompas.py(5): OKPД2 по типу, valid XML, save roundtrip, default OKPД2, end-to-end CLI. Все проходят.- Закоммичено и запушено.
- ⚠️ КОМПАС — Windows CAD-система, на Linux-host не установлен. Сгенерен валидный
.conXML; импорт геометрии в КОМПАС не тестировался (нет API).
🔵 P3.3 Упаковка (pyproject) — проверено
pyproject.toml: name=FastenGen v0.2.0, console scriptsfastengen+fasten-gen, depscadquery, pytest config.pip install .в venv прошёл,fastengen --helpработает.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 guardtest_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: jobquality(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) расширена:新增 jobquality(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.