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

18 KiB
Raw Permalink Blame History

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.

  • catalog.add_washer_l() — увеличенная шайбиц ГОСТ 11372-78
  • catalog.add_bolt_set() — винт-набронник ГОСТ 1170-84
  • catalog.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), cli vedomost получил --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.py MainWindow: фильтр по типу (bolt/nut/washer/stud/selftacker/screw), список с массой 1 шт. (из STEP-геометрии), двойной клик = переренерация STEP, экспорт ведомости md/csv/txt
  • run_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 не установлен. Сгенерен валидный .con XML; импорт геометрии в КОМПАС не тестировался (нет API).

🔵 P3.3 Упаковка (pyproject) — проверено

  • pyproject.toml: name=FastenGen v0.2.0, console scripts fastengen + fasten-gen, deps cadquery, 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 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.