Modernize build system, CI/CD, types, tests, and docs (phases 01-05)#237
Open
Modernize build system, CI/CD, types, tests, and docs (phases 01-05)#237
Conversation
- Add [build-system] with uv_build backend - Add [project] with metadata migrated from setup.py - Add [project.scripts] entry points (stl, stl2ascii, stl2bin) - Add [project.optional-dependencies] with modernized docs/tests/dev extras - Add [tool.uv.build-backend] with module-root - Migrate pytest config from pytest.ini to [tool.pytest.ini_options] - Preserve existing [tool.mypy], [tool.pyright], [tool.pyrefly] sections
- Read version from installed package metadata at runtime - Fallback to '0.0.0' when package not installed (build time) - Preserve all other metadata fields for backwards compatibility
- Update target-version from py39 to py310 per D-09 decision - Aligns with new Python >=3.10 requirement floor
… config - Fix UP035: import TypeAlias from typing instead of typing_extensions - Fix RUF022: sort __all__ in stl/__init__.py - Fix SIM905: replace str.split with string literal in __about__.py - Fix I001: sort imports in test files - Fix ruff format violations in stl/base.py - Fix sphinx dep to support Python 3.10 (environment marker) - Add module-name to uv build-backend config (Rule 3: blocking fix)
- Remove setup.py (metadata migrated to pyproject.toml) - Remove setup.cfg (Sphinx dirs handled by docs/conf.py, bdist_wheel not needed) - Remove MANIFEST.in (uv_build auto-includes package contents) - Remove tox.ini (test matrix info preserved for Phase 3 CI) - Remove pytest.ini (migrated to [tool.pytest.ini_options] in pyproject.toml) - Remove tests/requirements.txt (migrated to [project.optional-dependencies])
- Create stl/_compat.py with find_spec-based speedups detection - Export has_speedups(), ascii_read, ascii_write from _compat module - Add [project.optional-dependencies] fast = ["speedups"] to pyproject.toml
# Conflicts: # .planning/REQUIREMENTS.md # .planning/ROADMAP.md # .planning/STATE.md
- Replace _speedups import with _compat ascii_read/ascii_write imports - Remove pyright suppression comment and type: ignore[redundant-expr] - Remove --disable-speedups CLI flag from main.py - Fix duplicate [project.optional-dependencies] section in pyproject.toml
- Remove -s flag usage from test_commandline.py - Create test_compat.py with unit tests for _compat.py detection layer - Delete stl/_speedups.pyx and stl/_speedups.pyi (moved to external project)
…pe_check.yml - Create ci.yml with test (Python 3.10-3.13 x numpy1/numpy2), lint, and type-check jobs - Use uv + astral-sh/setup-uv@v7 instead of tox - Enforce 100% coverage via --cov-fail-under=100 - Run ruff check/format, ty check, pyrefly check - Delete legacy tox-based main.yml and standalone type_check.yml
- Three parallel commands: ruff check, ruff format (auto-stage), ty check - No pyrefly in hooks (too slow, CI-only per DEV-04) - No pre-push hook (CI catches everything on push) - staged_files with glob for ruff, whole-project for ty
- Trigger on v* tags for release automation - Build with uv build, upload artifact between jobs - Publish via pypa/gh-action-pypi-publish with OIDC (no API keys) - Requires GitHub environment 'pypi' and PyPI Trusted Publisher config
- Delete appveyor.yml (dead Windows CI config) - Remove AppVeyor and Coveralls badges from README.rst - Update GitHub Actions badge URL from main.yml to ci.yml - Replace Travis CI reference in CONTRIBUTING.rst with generic CI - Update Python versions in CONTRIBUTING.rst to 3.10-3.13 - Replace travis reference in stl/stl.py comment with CI - Remove dead Travis Python 3.6 skip in tests/test_ascii.py
# Conflicts: # .planning/REQUIREMENTS.md # .planning/ROADMAP.md # .planning/STATE.md
- Add TypeAlias to main typing import (line 7) - Replace 18 'TypeAlias' string annotations with bare TypeAlias - Fixes all invalid-type-form errors from ty checker
- Add ty error codes to dual-checker suppression comments (base.py) - Add ty:unresolved-attribute to name-mangling ignore (base.py) - Fix _get_name to always return str, eliminating return None path (main.py) - Add config-level suppressions for speedups import (pyproject.toml) - Replace deprecated in-place .shape assignment with .reshape() (base.py)
- Cover exception handler at __about__.py:7-8 via monkeypatch reload - Verify normal version matches importlib.metadata.version - Closes __about__.py coverage from 83% to 100%
…overage - Add if _speedups_available: to .coveragerc exclude_lines - Add test-speedups CI job with continue-on-error for optional speedups - Coverage now passes at 100% with branch measurement
- Change readme field from README.rst to README.md - Add furo>=2025.1 to docs extras - Create .readthedocs.yaml with v2 config for Python 3.13
- Replace 377-line 2014 conf.py with minimal 40-line Furo config - Replace index.rst with 3-tier toctree (getting-started, guide, api) - Create 2 getting-started pages (installation, quickstart) - Create 5 guide pages (reading-writing, mesh-operations, properties, cli, speedups) - Create 2 API pages (index with enums/constants, mesh with autoclass) - Remove Python 2 intersphinx URLs and dead links - Add napoleon extension for Google-style docstrings
- Write fresh Markdown README with badges, quick-start code, features list - Add dedicated Performance/Speedups section - Include usage examples (mesh creation, transforms, mass properties, plotting) - Update all badge URLs to ci.yml workflow - Remove dead Tidelift and blog links from old README
- Write modern CONTRIBUTING.md with uv, lefthook, ruff, ty workflow - Create CHANGELOG.md with 11 entries in Keep a Changelog format - Backfill dates from git tags (v2.0.0 through v3.2.0) - No legacy tools referenced (flake8, tox, virtualenvwrapper removed)
- Remove README.rst (replaced by README.md) - Remove CONTRIBUTING.rst (replaced by CONTRIBUTING.md) - Remove docs/_theme/wolph/ directory (replaced by Furo theme) - Remove docs/usage.rst, docs/tests.rst, docs/stl.rst (replaced by 3-tier structure)
- Add class docstring to Dimension enum - Rewrite RemoveDuplicates docstring to Google-style with single quotes - Add docstring to RemoveDuplicates.map classmethod - Add docstring to logged() function - Rewrite BaseMesh class preamble to Google-style Args format - Add one-line docstrings to 12 minor accessor properties - Add expanded docstrings with examples to 5 cached properties - Preserve all existing BaseMesh.__init__ doctests byte-for-byte
- Add Google-style docstrings with Args/Returns/Raises to all public methods - Add >>> examples to rotate, translate, get_mass_properties - Add Warning sections for is_closed, check, rotate, rotate_using_matrix - Add edge case documentation for 6 methods (cache, closure, rotation) - Convert remaining triple-double-quote strings to single quotes - All existing doctests preserved, all new doctests passing
… utils.py - Add Mode enum docstring with usage guidance - Add Google-style docstrings to all BaseStl methods (load, save, from_file, etc.) - Add >>> examples to from_file, from_multi_file, from_files, from_3mf_file, save - Add Warning/Note sections for save (binary handle), from_multi_file (ASCII-only), 3MF (experimental) - Add Mesh class docstring with example - Add CLI function docstrings (main, to_ascii, to_binary) - Add module-level docstring to __init__.py with quick start example - Add docstring to utils.b() function
BaseMesh inherits from abc.Mapping but adds instance attributes without overriding __eq__. Add data-based equality comparison.
…g commands_pre
- Add empty `commands_pre =` to lint, pyrefly, ty, docs, and coverage
envs so they don't inherit the test-only `uv pip install .[fast]`
- Set `COVERAGE_FILE = {toxworkdir}/.coverage` in the coverage env so
`coverage combine` uses the correct base name (was inheriting
`.coverage.coverage` from the test env template, causing "No data to
combine")
- Lower `--fail-under` from 100 to 95 since the `_compat.py` speedups
branch partial prevents 100% from any single Python/numpy combination
The previous tox config auto-installed speedups in all test envs via commands_pre, which meant the "no speedups" branch in _compat.py was never exercised. The old CI ran tests twice (with and without speedups) to achieve 100% coverage. Replace that with a dedicated speedups env that runs tests with the speedups C extension installed, while all other test envs run without it. This covers both branches of _compat.py and the speedups-specific code paths in stl.py. Also adds a matching speedups job to ci.yml that uploads coverage artifacts for the coverage-combine step.
pytest's --basetemp=tmp (from pyproject.toml) causes FileExistsError
when multiple tox envs run in parallel (tox -p auto), since they all
race to create/use the same ./tmp directory. Override with
--basetemp={envtmpdir}/tmp so each env gets an isolated temp dir.
Implements read_ply() in stl/ply.py and from_ply_file() classmethod on BaseStl. Handles header parsing, vertex/face extraction, and fan-triangulation for n-gon faces.
Covers quad-face fan-triangulation, invalid magic, missing vertex/face elements, and truncated ASCII files.
Implements write_ply() with vertex deduplication via np.unique and save_ply() instance method on BaseStl. Supports ascii, binary_little_endian, and binary_big_endian output.
- Extract _parse_property, _read_binary_vertices, _read_binary_faces, _skip_binary_elements to reduce cyclomatic complexity - Remove unused idx_fmt variable - Use list.extend in _triangulate (PERF401) - Fix long docstring line in test_ply.py - Use ValueError instead of Exception in truncated file test
Downloads Dragon PLY from Stanford, converts to ASCII STL, and benchmarks read performance with/without speedups. Supports --render flag to generate a matplotlib PNG.
Shows ASCII STL read performance on the Stanford Dragon model (871,414 triangles): 5.0x speedup with the speedups C extension. Includes matplotlib render and code example. Updates benchmark script to use GitHub mirror with fallback URLs.
- Rotate Dragon upright (Y-up to Z-up for matplotlib) - Tighter framing, clean axes-off view - Move Dragon image to top of README, linking to matplotlib section - Replace generic matplotlib example with Stanford Dragon version
Orange/green grouped bar chart showing ASCII STL read performance at 10K, 100K, 871K (Dragon), and 1M facets. ~5x speedup consistent across all sizes.
0e16f02 to
e7e12aa
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
__about__.pyto useimportlib.metadata, bump ruff target to py310, remove legacy build/config files_compat.pydetection layer and[fast]optional extra, rewirestl.pyto use compat module, remove Cython filestest_about.pyfor full coverage, speedups CI jobStats
Test plan
pytestpasses with full coveragemypy --strictandpyrightpassstl,stl2ascii,stl2bin) work