b3dkit 0.1.5__tar.gz → 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- b3dkit-0.4.0/.github/workflows/release.yml +72 -0
- b3dkit-0.4.0/.github/workflows/test.yml +99 -0
- b3dkit-0.4.0/.pre-commit-config.yaml +22 -0
- b3dkit-0.4.0/CHANGELOG.md +116 -0
- b3dkit-0.4.0/CONTRIBUTING.md +109 -0
- b3dkit-0.4.0/PKG-INFO +118 -0
- b3dkit-0.4.0/README.md +76 -0
- b3dkit-0.4.0/docs/CONTRIBUTING.md +1 -0
- {b3dkit-0.1.5 → b3dkit-0.4.0}/docs/antichamfer.md +16 -4
- b3dkit-0.4.0/docs/basic_shapes.md +129 -0
- b3dkit-0.4.0/docs/bolt_fittings.md +102 -0
- b3dkit-0.4.0/docs/dovetail.md +144 -0
- {b3dkit-0.1.5 → b3dkit-0.4.0}/docs/hexwall.md +2 -2
- {b3dkit-0.1.5 → b3dkit-0.4.0}/docs/high_top_slide_box.md +13 -63
- {b3dkit-0.1.5 → b3dkit-0.4.0}/docs/point.md +34 -14
- b3dkit-0.4.0/docs/reference/antichamfer.md +3 -0
- b3dkit-0.4.0/docs/reference/ball_socket.md +5 -0
- b3dkit-0.4.0/docs/reference/basic_shapes.md +25 -0
- b3dkit-0.4.0/docs/reference/bolt_fittings.md +13 -0
- b3dkit-0.4.0/docs/reference/click_fit.md +3 -0
- b3dkit-0.4.0/docs/reference/dovetail.md +9 -0
- b3dkit-0.4.0/docs/reference/hexwall.md +5 -0
- b3dkit-0.4.0/docs/reference/high_top_slide_box.md +7 -0
- b3dkit-0.4.0/docs/reference/index.md +23 -0
- b3dkit-0.4.0/docs/reference/point.md +7 -0
- b3dkit-0.4.0/docs/reference/slide_box.md +5 -0
- b3dkit-0.4.0/docs/reference/twist_snap.md +5 -0
- b3dkit-0.4.0/docs/requirements.txt +12 -0
- {b3dkit-0.1.5 → b3dkit-0.4.0}/docs/slide_box.md +15 -79
- b3dkit-0.4.0/docs/twist_snap.md +72 -0
- b3dkit-0.4.0/mkdocs.yml +68 -0
- b3dkit-0.4.0/pyproject.toml +92 -0
- b3dkit-0.4.0/readthedocs.yaml +13 -0
- b3dkit-0.4.0/src/b3dkit/__init__.py +105 -0
- {b3dkit-0.1.5 → b3dkit-0.4.0}/src/b3dkit/antichamfer.py +36 -6
- {b3dkit-0.1.5 → b3dkit-0.4.0}/src/b3dkit/ball_socket.py +20 -9
- {b3dkit-0.1.5 → b3dkit-0.4.0}/src/b3dkit/basic_shapes.py +40 -27
- {b3dkit-0.1.5 → b3dkit-0.4.0}/src/b3dkit/bolt_fittings.py +26 -15
- {b3dkit-0.1.5 → b3dkit-0.4.0}/src/b3dkit/click_fit.py +10 -5
- {b3dkit-0.1.5 → b3dkit-0.4.0}/src/b3dkit/dovetail.py +297 -162
- {b3dkit-0.1.5 → b3dkit-0.4.0}/src/b3dkit/hexwall.py +23 -14
- {b3dkit-0.1.5 → b3dkit-0.4.0}/src/b3dkit/high_top_slide_box.py +57 -19
- {b3dkit-0.1.5 → b3dkit-0.4.0}/src/b3dkit/point.py +51 -18
- b3dkit-0.4.0/src/b3dkit/py.typed +0 -0
- {b3dkit-0.1.5 → b3dkit-0.4.0}/src/b3dkit/slide_box.py +93 -40
- {b3dkit-0.1.5 → b3dkit-0.4.0}/src/b3dkit/twist_snap.py +25 -18
- b3dkit-0.4.0/tests/conftest.py +12 -0
- {b3dkit-0.1.5 → b3dkit-0.4.0}/tests/test_antichamfer.py +54 -5
- {b3dkit-0.1.5 → b3dkit-0.4.0}/tests/test_ball_socket.py +4 -2
- {b3dkit-0.1.5 → b3dkit-0.4.0}/tests/test_basic_shapes.py +6 -17
- {b3dkit-0.1.5 → b3dkit-0.4.0}/tests/test_bolt_fittings.py +9 -9
- {b3dkit-0.1.5 → b3dkit-0.4.0}/tests/test_click_fit.py +2 -7
- b3dkit-0.4.0/tests/test_docs.py +65 -0
- b3dkit-0.4.0/tests/test_dovetail.py +451 -0
- {b3dkit-0.1.5 → b3dkit-0.4.0}/tests/test_hexwall.py +5 -4
- {b3dkit-0.1.5 → b3dkit-0.4.0}/tests/test_high_top_slide_box.py +136 -50
- {b3dkit-0.1.5 → b3dkit-0.4.0}/tests/test_point.py +86 -4
- b3dkit-0.4.0/tests/test_public_api.py +168 -0
- {b3dkit-0.1.5 → b3dkit-0.4.0}/tests/test_slide_box.py +7 -9
- b3dkit-0.4.0/tests/test_twist_snap.py +83 -0
- b3dkit-0.1.5/.coverage +0 -0
- b3dkit-0.1.5/PKG-INFO +0 -57
- b3dkit-0.1.5/README.md +0 -28
- b3dkit-0.1.5/build.bat +0 -44
- b3dkit-0.1.5/build.sh +0 -44
- b3dkit-0.1.5/docs/Makefile +0 -20
- b3dkit-0.1.5/docs/basic_shapes.md +0 -319
- b3dkit-0.1.5/docs/bolt_fittings.md +0 -214
- b3dkit-0.1.5/docs/conf.py +0 -124
- b3dkit-0.1.5/docs/dovetail.md +0 -81
- b3dkit-0.1.5/docs/twist_snap.md +0 -69
- b3dkit-0.1.5/mkdocs.yml +0 -32
- b3dkit-0.1.5/pyproject.toml +0 -53
- b3dkit-0.1.5/readthedocs.yaml +0 -16
- b3dkit-0.1.5/src/b3dkit/__init__.py +0 -11
- b3dkit-0.1.5/tests/conftest.py +0 -14
- b3dkit-0.1.5/tests/test_dovetail.py +0 -229
- b3dkit-0.1.5/tests/test_twist_snap.py +0 -46
- {b3dkit-0.1.5 → b3dkit-0.4.0}/.coveragerc +0 -0
- {b3dkit-0.1.5 → b3dkit-0.4.0}/.gitignore +0 -0
- {b3dkit-0.1.5 → b3dkit-0.4.0}/.vscode/settings.json +0 -0
- {b3dkit-0.1.5 → b3dkit-0.4.0}/LICENSE +0 -0
- {b3dkit-0.1.5 → b3dkit-0.4.0}/docs/ball_socket.md +0 -0
- {b3dkit-0.1.5 → b3dkit-0.4.0}/docs/click_fit.md +0 -0
- {b3dkit-0.1.5 → b3dkit-0.4.0}/docs/dovetail.png +0 -0
- {b3dkit-0.1.5 → b3dkit-0.4.0}/docs/index.md +0 -0
- {b3dkit-0.1.5 → b3dkit-0.4.0}/docs/twist_snap.png +0 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
name: release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags: ["v*"]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
build:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
steps:
|
|
12
|
+
- uses: actions/checkout@v7
|
|
13
|
+
|
|
14
|
+
- uses: actions/setup-python@v7
|
|
15
|
+
with:
|
|
16
|
+
python-version: "3.12"
|
|
17
|
+
cache: pip
|
|
18
|
+
|
|
19
|
+
- name: Install and test
|
|
20
|
+
run: |
|
|
21
|
+
python -m pip install --upgrade pip build
|
|
22
|
+
python -m pip install -e ".[dev]"
|
|
23
|
+
pytest -q
|
|
24
|
+
|
|
25
|
+
- name: Check the tag matches the packaged version
|
|
26
|
+
run: |
|
|
27
|
+
tag="${GITHUB_REF_NAME#v}"
|
|
28
|
+
version=$(python -c "import re,pathlib;print(re.search(r'^version = \"([^\"]+)\"',pathlib.Path('pyproject.toml').read_text(),re.M).group(1))")
|
|
29
|
+
if [ "$tag" != "$version" ]; then
|
|
30
|
+
echo "::error::tag $GITHUB_REF_NAME does not match pyproject version $version"
|
|
31
|
+
exit 1
|
|
32
|
+
fi
|
|
33
|
+
echo "tag and version agree: $version"
|
|
34
|
+
|
|
35
|
+
- name: Build
|
|
36
|
+
run: python -m build
|
|
37
|
+
|
|
38
|
+
- uses: actions/upload-artifact@v7
|
|
39
|
+
with:
|
|
40
|
+
name: dist
|
|
41
|
+
path: dist/
|
|
42
|
+
|
|
43
|
+
publish:
|
|
44
|
+
needs: build
|
|
45
|
+
runs-on: ubuntu-latest
|
|
46
|
+
environment: pypi
|
|
47
|
+
permissions:
|
|
48
|
+
id-token: write # required for PyPI Trusted Publishing
|
|
49
|
+
steps:
|
|
50
|
+
- uses: actions/download-artifact@v7
|
|
51
|
+
with:
|
|
52
|
+
name: dist
|
|
53
|
+
path: dist/
|
|
54
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
55
|
+
|
|
56
|
+
smoke-test:
|
|
57
|
+
# Install the published artifact from PyPI and build something, mirroring the
|
|
58
|
+
# post-upload check the retired build.sh performed by hand.
|
|
59
|
+
needs: publish
|
|
60
|
+
runs-on: ubuntu-latest
|
|
61
|
+
steps:
|
|
62
|
+
- uses: actions/setup-python@v7
|
|
63
|
+
with:
|
|
64
|
+
python-version: "3.12"
|
|
65
|
+
- name: Wait for PyPI to serve the new version
|
|
66
|
+
run: sleep 60
|
|
67
|
+
- name: Install from PyPI and build a part
|
|
68
|
+
run: |
|
|
69
|
+
version="${GITHUB_REF_NAME#v}"
|
|
70
|
+
python -m pip install --upgrade pip
|
|
71
|
+
python -m pip install "b3dkit==$version"
|
|
72
|
+
python -c "from b3dkit import Divot; assert Divot().is_valid; print('smoke test OK')"
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
name: test
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
concurrency:
|
|
10
|
+
group: test-${{ github.ref }}
|
|
11
|
+
cancel-in-progress: true
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
test:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
strategy:
|
|
17
|
+
fail-fast: false
|
|
18
|
+
matrix:
|
|
19
|
+
python-version: ["3.11", "3.12", "3.13"]
|
|
20
|
+
build123d: [latest]
|
|
21
|
+
include:
|
|
22
|
+
# One job pinned at the declared dependency floor. b3dkit 0.1.5 shipped
|
|
23
|
+
# code that could not run against its own advertised minimum; this job
|
|
24
|
+
# is what stops that from happening again.
|
|
25
|
+
- python-version: "3.12"
|
|
26
|
+
build123d: floor
|
|
27
|
+
|
|
28
|
+
name: py${{ matrix.python-version }} / build123d ${{ matrix.build123d }}
|
|
29
|
+
|
|
30
|
+
steps:
|
|
31
|
+
- uses: actions/checkout@v7
|
|
32
|
+
|
|
33
|
+
- uses: actions/setup-python@v7
|
|
34
|
+
with:
|
|
35
|
+
python-version: ${{ matrix.python-version }}
|
|
36
|
+
cache: pip
|
|
37
|
+
|
|
38
|
+
- name: Install
|
|
39
|
+
run: |
|
|
40
|
+
python -m pip install --upgrade pip
|
|
41
|
+
python -m pip install -e ".[dev]"
|
|
42
|
+
|
|
43
|
+
- name: Pin build123d to the declared floor
|
|
44
|
+
if: matrix.build123d == 'floor'
|
|
45
|
+
run: |
|
|
46
|
+
floor=$(python -c "import re,pathlib;print(re.search(r'build123d>=([0-9.]+)',pathlib.Path('pyproject.toml').read_text()).group(1))")
|
|
47
|
+
echo "Installing build123d==$floor"
|
|
48
|
+
python -m pip install "build123d==$floor"
|
|
49
|
+
|
|
50
|
+
- name: Show resolved versions
|
|
51
|
+
run: python -c "import sys,build123d;print(sys.version);print('build123d',build123d.__version__)"
|
|
52
|
+
|
|
53
|
+
- name: Run tests
|
|
54
|
+
run: pytest --cov=b3dkit --cov-report=term-missing --junitxml=junit.xml
|
|
55
|
+
|
|
56
|
+
- name: Fail if any test was skipped
|
|
57
|
+
# A green suite that silently skips is how the broken 0.10.0 floor reached
|
|
58
|
+
# PyPI: 27 tests were skipped and nothing complained.
|
|
59
|
+
if: always()
|
|
60
|
+
run: |
|
|
61
|
+
python - <<'PY'
|
|
62
|
+
import sys, xml.etree.ElementTree as ET
|
|
63
|
+
suite = ET.parse("junit.xml").getroot()
|
|
64
|
+
skipped = sum(int(s.get("skipped", 0)) for s in suite.iter("testsuite"))
|
|
65
|
+
if skipped:
|
|
66
|
+
print(f"::error::{skipped} test(s) skipped; the skip budget is zero")
|
|
67
|
+
sys.exit(1)
|
|
68
|
+
print("No skipped tests.")
|
|
69
|
+
PY
|
|
70
|
+
|
|
71
|
+
lint:
|
|
72
|
+
runs-on: ubuntu-latest
|
|
73
|
+
steps:
|
|
74
|
+
- uses: actions/checkout@v7
|
|
75
|
+
- uses: actions/setup-python@v7
|
|
76
|
+
with:
|
|
77
|
+
python-version: "3.12"
|
|
78
|
+
cache: pip
|
|
79
|
+
- run: python -m pip install --upgrade pip ruff black
|
|
80
|
+
- run: ruff check .
|
|
81
|
+
- run: black --check .
|
|
82
|
+
|
|
83
|
+
docs:
|
|
84
|
+
runs-on: ubuntu-latest
|
|
85
|
+
steps:
|
|
86
|
+
- uses: actions/checkout@v7
|
|
87
|
+
- uses: actions/setup-python@v7
|
|
88
|
+
with:
|
|
89
|
+
python-version: "3.12"
|
|
90
|
+
cache: pip
|
|
91
|
+
- name: Install documentation dependencies only
|
|
92
|
+
# No build123d here on purpose: mkdocstrings reads the source with
|
|
93
|
+
# griffe, which analyses statically. If this job ever needs a CAD
|
|
94
|
+
# kernel, something has started importing the package to build docs.
|
|
95
|
+
run: |
|
|
96
|
+
python -m pip install --upgrade pip
|
|
97
|
+
python -m pip install -r docs/requirements.txt
|
|
98
|
+
- name: Build the site
|
|
99
|
+
run: mkdocs build --strict
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
3
|
+
rev: v0.14.5
|
|
4
|
+
hooks:
|
|
5
|
+
- id: ruff
|
|
6
|
+
args: [--fix]
|
|
7
|
+
- id: ruff-format
|
|
8
|
+
stages: [manual]
|
|
9
|
+
|
|
10
|
+
- repo: https://github.com/psf/black
|
|
11
|
+
rev: 25.9.0
|
|
12
|
+
hooks:
|
|
13
|
+
- id: black
|
|
14
|
+
|
|
15
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
16
|
+
rev: v6.0.0
|
|
17
|
+
hooks:
|
|
18
|
+
- id: end-of-file-fixer
|
|
19
|
+
- id: trailing-whitespace
|
|
20
|
+
- id: check-toml
|
|
21
|
+
- id: check-yaml
|
|
22
|
+
- id: check-merge-conflict
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to b3dkit are documented here. This project follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and
|
|
5
|
+
[Semantic Versioning](https://semver.org/). b3dkit is `0.x`, so breaking changes
|
|
6
|
+
ship in minor releases.
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.4.0] - 2026-09-08
|
|
11
|
+
|
|
12
|
+
### Removed
|
|
13
|
+
|
|
14
|
+
- **`TwistSnapConnector` no longer accepts `tolerance` or `wall_width`.** Both
|
|
15
|
+
were read by nothing. All fit clearance lives on the socket, which opens its
|
|
16
|
+
bore to `connector_radius + tolerance`; applying it on the connector as well
|
|
17
|
+
would have doubled the gap. Geometry is unchanged.
|
|
18
|
+
- **`HexCylindrical` no longer accepts `rotation` or `align`.** Both were inert.
|
|
19
|
+
Its cutters are positioned against the surface they wrap, so moving them off
|
|
20
|
+
it is never useful. Rotate the `cylindrical` argument instead.
|
|
21
|
+
- **`thumb_radius` removed from `high_top_slide_box`**, where it was threaded
|
|
22
|
+
through four signatures and read by nothing. It remains live in `slide_box`.
|
|
23
|
+
- `docs/conf.py` and `docs/Makefile`, dead Sphinx configuration that was being
|
|
24
|
+
served as static assets on the published site.
|
|
25
|
+
|
|
26
|
+
### Added
|
|
27
|
+
|
|
28
|
+
- **`dovetail_split(part, start, end, **kwargs) -> tuple[Part, Part]`** builds a
|
|
29
|
+
mating pair from one argument set, so the two halves cannot diverge.
|
|
30
|
+
- **Generated API reference.** Signatures and arguments now come from the source
|
|
31
|
+
via mkdocstrings and cannot drift from it.
|
|
32
|
+
- **`py.typed`**, so downstream type checkers see b3dkit's annotations, and
|
|
33
|
+
`b3dkit.__version__`.
|
|
34
|
+
- Input validation on `high_top_slide_box`: dimensions leaving less than
|
|
35
|
+
`wall_thickness` above `top_height + rail_height` previously produced a part
|
|
36
|
+
in three pieces and now raise.
|
|
37
|
+
- `CONTRIBUTING.md`, this changelog, CI across Python 3.11-3.13, and a release
|
|
38
|
+
workflow publishing through PyPI Trusted Publishing.
|
|
39
|
+
|
|
40
|
+
### Changed
|
|
41
|
+
|
|
42
|
+
- **`dovetail_subpart` rejects arguments the chosen style would discard.** Each
|
|
43
|
+
style uses only a subset of the shaping arguments; the rest were accepted and
|
|
44
|
+
silently ignored. Passing one now raises `ValueError` naming the styles it
|
|
45
|
+
applies to.
|
|
46
|
+
- **`Point` is stricter and immutable.** `Point((3, 4))` now works, where a
|
|
47
|
+
tuple was previously mis-parsed into `Point(x=(3, 4), y=None)`; `Point(3)` and
|
|
48
|
+
`Point()` raise instead of building a half-initialised point;
|
|
49
|
+
`axial_distance_to` raises for any axis but `Axis.X` or `Axis.Y`, where it
|
|
50
|
+
previously returned the Y distance for all of them; assigning to `x` or `y`
|
|
51
|
+
raises.
|
|
52
|
+
- **`anti_chamfer` refuses the wrong builder.** It identified itself as
|
|
53
|
+
`"chamfer"` in build123d's internal dispatch table, inheriting permission to
|
|
54
|
+
run inside a `BuildSketch`, where it completed silently and did the wrong
|
|
55
|
+
thing. It now raises and applies to `BuildPart` only.
|
|
56
|
+
- **`slide_box()` no longer packs or colours its result.** Print orientation is
|
|
57
|
+
kept; bed layout and viewer tint were presentation baked into geometry. Call
|
|
58
|
+
build123d's `pack()` yourself if you want the parts arranged.
|
|
59
|
+
- **Eight Part objects now validate their builder context** — `BallMount`,
|
|
60
|
+
`BallSocket`, `SquareNutSinkhole`, `Divot`, `HexWall`, `HexCylindrical`,
|
|
61
|
+
`TwistSnapConnector`, `TwistSnapSocket`. Using one inside a `BuildSketch`
|
|
62
|
+
previously produced no error and the wrong output.
|
|
63
|
+
- **`ocp_vscode` is now an optional `[viewer]` extra.** No library code path used
|
|
64
|
+
it; all nine imports fed only `__main__` demo blocks. Installing b3dkit no
|
|
65
|
+
longer pulls a viewer, web server and tessellation stack.
|
|
66
|
+
- **Python 3.11 or newer** is required. `ocp_tessellate`, reached through
|
|
67
|
+
`ocp_vscode`, imports `typing.NotRequired`, which is 3.11+.
|
|
68
|
+
- Documentation builds no longer install the package, so ReadTheDocs stops
|
|
69
|
+
pulling the OpenCascade wheels to render Markdown.
|
|
70
|
+
|
|
71
|
+
### Fixed
|
|
72
|
+
|
|
73
|
+
- **`dovetail_subpart` silently ignored four documented arguments.**
|
|
74
|
+
`linear_offset`, `tail_angle_offset`, `length_ratio` and `depth_ratio` were
|
|
75
|
+
accepted, passed one level down and dropped, so the module reported full line
|
|
76
|
+
coverage while four public knobs did nothing. Introduced when `subpart_section`
|
|
77
|
+
was extracted in "initial T Slot dovetail support". Callers who passed none of
|
|
78
|
+
them get identical geometry; callers who passed any get the geometry they
|
|
79
|
+
asked for.
|
|
80
|
+
- **Every documented example now runs.** The documentation described functions
|
|
81
|
+
that never existed (`heatsink_insert_cut`, `nut_cut`, `screw_cut`,
|
|
82
|
+
`socket_subpart`, `half_part`), imported others from the wrong module, listed
|
|
83
|
+
`anti_chamfer`'s arguments in the wrong order, and gave the dovetail
|
|
84
|
+
`tolerance` default as 0.05 where the source says 0.025.
|
|
85
|
+
|
|
86
|
+
### Renamed
|
|
87
|
+
|
|
88
|
+
| Old | New | Notes |
|
|
89
|
+
|---|---|---|
|
|
90
|
+
| `DovetailPart` | `DovetailSubpart` | The old name read as a build123d `Part`, which is the function's return type |
|
|
91
|
+
| `section=` | `subpart=` | `section` collides with build123d's own slice operation |
|
|
92
|
+
| `slide_tolerance=` | `tolerance=` | One module used two names and three defaults for one concept |
|
|
93
|
+
| `nut_legnth=` | `nut_length=` | Misspelled keyword argument |
|
|
94
|
+
| `subpart_section` | `_subpart_slab` | Private; it lofts a Z-slab |
|
|
95
|
+
|
|
96
|
+
Ten dovetail internals and `slider_template` became private. Nothing outside the
|
|
97
|
+
package used them.
|
|
98
|
+
|
|
99
|
+
`from b3dkit import *` no longer re-exports build123d. The namespace went from
|
|
100
|
+
129 names, 72 of them third-party, to the library's own. Import `Box`, `Mode`,
|
|
101
|
+
`Part` and friends from `build123d`.
|
|
102
|
+
|
|
103
|
+
## [0.3.2] - 2026-09-06
|
|
104
|
+
|
|
105
|
+
First release through the automated pipeline. Contains the dovetail argument
|
|
106
|
+
forwarding fix, the `__all__` export surface, the `DovetailSubpart` rename and
|
|
107
|
+
the Python 3.11 floor.
|
|
108
|
+
|
|
109
|
+
## [0.1.5] and earlier
|
|
110
|
+
|
|
111
|
+
See the git history. b3dkit began as `fb-library`; the rename accompanied a
|
|
112
|
+
rewrite that reworked names and usage to feel closer to native build123d.
|
|
113
|
+
|
|
114
|
+
[Unreleased]: https://github.com/x0pherl/b3dkit/compare/v0.4.0...HEAD
|
|
115
|
+
[0.4.0]: https://github.com/x0pherl/b3dkit/releases/tag/v0.4.0
|
|
116
|
+
[0.3.2]: https://github.com/x0pherl/b3dkit/releases/tag/v0.3.2
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# Contributing to b3dkit
|
|
2
|
+
|
|
3
|
+
Thank you for considering a contribution. Bug reports, fixes, docs and tests are
|
|
4
|
+
all welcome.
|
|
5
|
+
|
|
6
|
+
If you are unsure where to start, open an issue and describe your idea. Early
|
|
7
|
+
feedback prevents rework.
|
|
8
|
+
|
|
9
|
+
## Development Setup
|
|
10
|
+
|
|
11
|
+
1. Fork and clone the repository.
|
|
12
|
+
2. Create and activate a virtual environment (Python 3.11 or newer).
|
|
13
|
+
3. Install with the development extras:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pip install -e ".[dev]"
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
4. Run the tests:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pytest --cov
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
The `dev` extra pulls in `ocp_vscode` so the tests that execute each module's
|
|
26
|
+
`__main__` demo can run. The library itself never imports it — see
|
|
27
|
+
[Dependencies](#dependencies).
|
|
28
|
+
|
|
29
|
+
## Testing Standards
|
|
30
|
+
|
|
31
|
+
Tests are required for substantive changes.
|
|
32
|
+
|
|
33
|
+
- **Coverage floor is 90%**, measured on library code. It is a floor, not a
|
|
34
|
+
target, and there is no ratchet: a change that lowers coverage while deleting
|
|
35
|
+
a test that asserted nothing is an improvement.
|
|
36
|
+
- **Every test must be able to fail.** No test should pass without asserting on
|
|
37
|
+
a value the code produced. Tests that exist only to execute lines for coverage
|
|
38
|
+
credit are worse than no test, because they make the coverage number lie.
|
|
39
|
+
- **Assert on geometry, not just validity.** `is_valid` is true for nearly any
|
|
40
|
+
closed solid, including one built with every argument ignored. Prefer volume,
|
|
41
|
+
bounding box, solid count, or a raised exception. Where a change should alter
|
|
42
|
+
geometry, assert that it *differs* from the default; where it should not,
|
|
43
|
+
assert that it does not.
|
|
44
|
+
- **Bug fixes need a test that fails before the fix.**
|
|
45
|
+
- Run `pytest` before opening a pull request.
|
|
46
|
+
|
|
47
|
+
Two invariants are enforced mechanically rather than by review, because this
|
|
48
|
+
project is largely self-reviewed:
|
|
49
|
+
|
|
50
|
+
- `tests/test_public_api.py` walks `__all__` and checks that every export is
|
|
51
|
+
b3dkit's own, is documented, and follows the Part object contract.
|
|
52
|
+
- `tests/test_docs.py` executes every fenced `python` block in `README.md` and
|
|
53
|
+
`docs/`, in document order.
|
|
54
|
+
|
|
55
|
+
## Documentation Standards
|
|
56
|
+
|
|
57
|
+
Documentation is part of the change, not a follow-up. Update it in the same
|
|
58
|
+
commit.
|
|
59
|
+
|
|
60
|
+
- **Signatures and arguments are generated** by mkdocstrings from the source.
|
|
61
|
+
Do not hand-write them in `docs/`; a second copy is what let the old
|
|
62
|
+
documentation drift from the code.
|
|
63
|
+
- **Prose pages carry what the reference cannot**: what something is for, how to
|
|
64
|
+
choose between two options, print settings, tolerances, troubleshooting.
|
|
65
|
+
- **Examples must run.** They are executed by the test suite.
|
|
66
|
+
- **State units.** All linear dimensions are in millimeters and all angles in
|
|
67
|
+
degrees; say so for any argument where it could be ambiguous.
|
|
68
|
+
- Build the site locally with `mkdocs build --strict`.
|
|
69
|
+
|
|
70
|
+
## Dependencies
|
|
71
|
+
|
|
72
|
+
The library imports `build123d` and nothing else. `ocp_vscode` is an optional
|
|
73
|
+
`[viewer]` extra used only by the `__main__` demo blocks, so that installing
|
|
74
|
+
b3dkit headlessly does not pull a viewer, web server and tessellation stack.
|
|
75
|
+
|
|
76
|
+
If you add an import to library code, ask whether it belongs in
|
|
77
|
+
`dependencies` or in an extra.
|
|
78
|
+
|
|
79
|
+
## build123d Compatibility
|
|
80
|
+
|
|
81
|
+
b3dkit declares a minimum build123d version and CI runs one job pinned at
|
|
82
|
+
exactly that floor. Please keep it honest: if you use an API added in a newer
|
|
83
|
+
release, raise the floor in `pyproject.toml` in the same change. b3dkit 0.1.5
|
|
84
|
+
shipped code that could not run against its own advertised minimum, which is
|
|
85
|
+
what that CI job exists to prevent.
|
|
86
|
+
|
|
87
|
+
Do not add an upper bound. Caps propagate into every downstream resolution and
|
|
88
|
+
convert a runtime failure into an install failure for everyone.
|
|
89
|
+
|
|
90
|
+
## Public API
|
|
91
|
+
|
|
92
|
+
`b3dkit.__all__` is the public API. Anything not listed is an implementation
|
|
93
|
+
detail and may change. When adding an export, add it to the module's `__all__`
|
|
94
|
+
and to the package's, and give it a docstring — the contract tests check both.
|
|
95
|
+
|
|
96
|
+
## Versioning
|
|
97
|
+
|
|
98
|
+
b3dkit is `0.x`, so breaking changes ship in minor releases. Each release is
|
|
99
|
+
tagged `vX.Y.Z`, matching the version in `pyproject.toml`; the release workflow
|
|
100
|
+
refuses to publish if they disagree.
|
|
101
|
+
|
|
102
|
+
## Pull Request Checklist
|
|
103
|
+
|
|
104
|
+
- [ ] Tests added or updated, and each can fail
|
|
105
|
+
- [ ] `pytest` passes
|
|
106
|
+
- [ ] `ruff check .` and `black --check .` pass
|
|
107
|
+
- [ ] Documentation updated in the same commit
|
|
108
|
+
- [ ] `mkdocs build --strict` passes if you touched `docs/`
|
|
109
|
+
- [ ] PR describes what changed and why
|
b3dkit-0.4.0/PKG-INFO
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: b3dkit
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: build123d libraries and utilities
|
|
5
|
+
Project-URL: Homepage, https://github.com/x0pherl/b3dkit
|
|
6
|
+
Project-URL: Issues, https://github.com/x0pherl/b3dkit/issues
|
|
7
|
+
Project-URL: Documentation, https://b3dkit.readthedocs.io
|
|
8
|
+
Project-URL: Changelog, https://github.com/x0pherl/b3dkit/blob/main/CHANGELOG.md
|
|
9
|
+
Author: x0pherl
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: 3d-printing,build123d,cad,opencascade,parametric
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Intended Audience :: Manufacturing
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Multimedia :: Graphics :: 3D Modeling
|
|
22
|
+
Classifier: Topic :: Scientific/Engineering
|
|
23
|
+
Classifier: Typing :: Typed
|
|
24
|
+
Requires-Python: >=3.11
|
|
25
|
+
Requires-Dist: build123d>=0.11.0
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: ocp-vscode>=3.1.1; extra == 'dev'
|
|
28
|
+
Requires-Dist: pytest-cov>=7.0.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest>=9.0.2; extra == 'dev'
|
|
30
|
+
Provides-Extra: docs
|
|
31
|
+
Requires-Dist: markdown-include>=0.8.1; extra == 'docs'
|
|
32
|
+
Requires-Dist: mkdocs-material>=9.7.6; extra == 'docs'
|
|
33
|
+
Requires-Dist: mkdocs>=1.6.1; extra == 'docs'
|
|
34
|
+
Provides-Extra: maintain
|
|
35
|
+
Requires-Dist: build>=1.4.0; extra == 'maintain'
|
|
36
|
+
Requires-Dist: hatch-vcs>=0.5.0; extra == 'maintain'
|
|
37
|
+
Requires-Dist: hatchling>=1.29.0; extra == 'maintain'
|
|
38
|
+
Requires-Dist: twine>=6.2.0; extra == 'maintain'
|
|
39
|
+
Provides-Extra: viewer
|
|
40
|
+
Requires-Dist: ocp-vscode>=3.1.1; extra == 'viewer'
|
|
41
|
+
Description-Content-Type: text/markdown
|
|
42
|
+
|
|
43
|
+
# b3dkit
|
|
44
|
+
|
|
45
|
+
Utilities for [build123d](https://github.com/gumyr/build123d) parts that have to be
|
|
46
|
+
**printed and assembled**: splitting parts too big for the bed, snapping them
|
|
47
|
+
together, fastening them, and venting them.
|
|
48
|
+
|
|
49
|
+
All linear dimensions are in millimeters and all angles are in degrees, matching
|
|
50
|
+
build123d.
|
|
51
|
+
|
|
52
|
+
## Installation
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
pip install b3dkit
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Requires Python 3.11+ and build123d 0.11+. To run the `__main__` demo in each
|
|
59
|
+
module, which previews parts in VS Code, install the viewer extra:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
pip install b3dkit[viewer]
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## What's in it
|
|
66
|
+
|
|
67
|
+
| | |
|
|
68
|
+
|---|---|
|
|
69
|
+
| **dovetail** | Splits a `Part` into two that slide together with tight tolerances, for parts larger than your build volume. Includes a "snugtail" style suited to 3D printing, which wraps three sides for a large friction and glue surface. |
|
|
70
|
+
| **click_fit** | A tapered divot that prints and assembles better than a half sphere, letting parts click into place. |
|
|
71
|
+
| **twist_snap** | A connector and socket that lock with a twist, for joints meant to be opened repeatedly. |
|
|
72
|
+
| **ball_socket** | A ball mount and matching socket. |
|
|
73
|
+
| **bolt_fittings** | Bolt holes, countersinks, nut traps and heat-set insert recesses, sized for M3 by default. |
|
|
74
|
+
| **hexwall** | A honeycomb of hexagonal holes, flat or wrapped around a cone or cylinder, for venting and lightening. |
|
|
75
|
+
| **basic_shapes** | Rounded, polygonal, diamond and teardrop cylinders, plus the trigonometry helpers that place them. |
|
|
76
|
+
| **antichamfer** | Extends a face outward with a taper, like a foot or flat crown moulding. |
|
|
77
|
+
| **slide_box**, **high_top_slide_box** | Boxes with sliding lids. |
|
|
78
|
+
| **Point** | A lightweight 2D point with the geometry helpers the rest of the library needs. |
|
|
79
|
+
|
|
80
|
+
## Example
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
from build123d import Align, Box, BuildPart, Mode
|
|
84
|
+
from b3dkit import DovetailStyle, Point, dovetail_split
|
|
85
|
+
|
|
86
|
+
with BuildPart(mode=Mode.PRIVATE) as oversized:
|
|
87
|
+
Box(50, 40, 50, align=(Align.CENTER, Align.CENTER, Align.MIN))
|
|
88
|
+
|
|
89
|
+
# split it into a mating pair that fits the bed
|
|
90
|
+
tail, socket = dovetail_split(
|
|
91
|
+
oversized.part,
|
|
92
|
+
Point(0, -20),
|
|
93
|
+
Point(0, 20),
|
|
94
|
+
style=DovetailStyle.SNUGTAIL,
|
|
95
|
+
)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Documentation
|
|
99
|
+
|
|
100
|
+
Full documentation, including a generated API reference, is at
|
|
101
|
+
[b3dkit.readthedocs.io](https://b3dkit.readthedocs.io).
|
|
102
|
+
|
|
103
|
+
## Contributing
|
|
104
|
+
|
|
105
|
+
Pull requests are welcome. For major changes, please open an issue first to
|
|
106
|
+
discuss what you would like to change.
|
|
107
|
+
|
|
108
|
+
## History
|
|
109
|
+
|
|
110
|
+
b3dkit began as `fb-library`, a way to isolate common utilities from
|
|
111
|
+
[Fender-Bender](https://github.com/x0pherl/fender-bender). It outgrew that
|
|
112
|
+
project, and was renamed during a rewrite that reworked names and usage to feel
|
|
113
|
+
closer to native build123d.
|
|
114
|
+
|
|
115
|
+
## License
|
|
116
|
+
|
|
117
|
+
Licensed under the terms of the [MIT](https://choosealicense.com/licenses/mit/)
|
|
118
|
+
license.
|
b3dkit-0.4.0/README.md
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# b3dkit
|
|
2
|
+
|
|
3
|
+
Utilities for [build123d](https://github.com/gumyr/build123d) parts that have to be
|
|
4
|
+
**printed and assembled**: splitting parts too big for the bed, snapping them
|
|
5
|
+
together, fastening them, and venting them.
|
|
6
|
+
|
|
7
|
+
All linear dimensions are in millimeters and all angles are in degrees, matching
|
|
8
|
+
build123d.
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
pip install b3dkit
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Requires Python 3.11+ and build123d 0.11+. To run the `__main__` demo in each
|
|
17
|
+
module, which previews parts in VS Code, install the viewer extra:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pip install b3dkit[viewer]
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## What's in it
|
|
24
|
+
|
|
25
|
+
| | |
|
|
26
|
+
|---|---|
|
|
27
|
+
| **dovetail** | Splits a `Part` into two that slide together with tight tolerances, for parts larger than your build volume. Includes a "snugtail" style suited to 3D printing, which wraps three sides for a large friction and glue surface. |
|
|
28
|
+
| **click_fit** | A tapered divot that prints and assembles better than a half sphere, letting parts click into place. |
|
|
29
|
+
| **twist_snap** | A connector and socket that lock with a twist, for joints meant to be opened repeatedly. |
|
|
30
|
+
| **ball_socket** | A ball mount and matching socket. |
|
|
31
|
+
| **bolt_fittings** | Bolt holes, countersinks, nut traps and heat-set insert recesses, sized for M3 by default. |
|
|
32
|
+
| **hexwall** | A honeycomb of hexagonal holes, flat or wrapped around a cone or cylinder, for venting and lightening. |
|
|
33
|
+
| **basic_shapes** | Rounded, polygonal, diamond and teardrop cylinders, plus the trigonometry helpers that place them. |
|
|
34
|
+
| **antichamfer** | Extends a face outward with a taper, like a foot or flat crown moulding. |
|
|
35
|
+
| **slide_box**, **high_top_slide_box** | Boxes with sliding lids. |
|
|
36
|
+
| **Point** | A lightweight 2D point with the geometry helpers the rest of the library needs. |
|
|
37
|
+
|
|
38
|
+
## Example
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
from build123d import Align, Box, BuildPart, Mode
|
|
42
|
+
from b3dkit import DovetailStyle, Point, dovetail_split
|
|
43
|
+
|
|
44
|
+
with BuildPart(mode=Mode.PRIVATE) as oversized:
|
|
45
|
+
Box(50, 40, 50, align=(Align.CENTER, Align.CENTER, Align.MIN))
|
|
46
|
+
|
|
47
|
+
# split it into a mating pair that fits the bed
|
|
48
|
+
tail, socket = dovetail_split(
|
|
49
|
+
oversized.part,
|
|
50
|
+
Point(0, -20),
|
|
51
|
+
Point(0, 20),
|
|
52
|
+
style=DovetailStyle.SNUGTAIL,
|
|
53
|
+
)
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Documentation
|
|
57
|
+
|
|
58
|
+
Full documentation, including a generated API reference, is at
|
|
59
|
+
[b3dkit.readthedocs.io](https://b3dkit.readthedocs.io).
|
|
60
|
+
|
|
61
|
+
## Contributing
|
|
62
|
+
|
|
63
|
+
Pull requests are welcome. For major changes, please open an issue first to
|
|
64
|
+
discuss what you would like to change.
|
|
65
|
+
|
|
66
|
+
## History
|
|
67
|
+
|
|
68
|
+
b3dkit began as `fb-library`, a way to isolate common utilities from
|
|
69
|
+
[Fender-Bender](https://github.com/x0pherl/fender-bender). It outgrew that
|
|
70
|
+
project, and was renamed during a rewrite that reworked names and usage to feel
|
|
71
|
+
closer to native build123d.
|
|
72
|
+
|
|
73
|
+
## License
|
|
74
|
+
|
|
75
|
+
Licensed under the terms of the [MIT](https://choosealicense.com/licenses/mit/)
|
|
76
|
+
license.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{!CONTRIBUTING.md!}
|
|
@@ -10,12 +10,25 @@ The `antichamfer` module provides functionality to create anti-chamfers. An anti
|
|
|
10
10
|
|
|
11
11
|
#### arguments
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
- face
|
|
13
|
+
`anti_chamfer(face, length, length2=None) -> Part`
|
|
14
|
+
|
|
15
|
+
- `face`: the face or faces to apply the anti-chamfer to (a single `Face` or an iterable of `Face`)
|
|
16
|
+
- `length`: how far the anti-chamfer extends outward from the original face, in mm
|
|
17
|
+
- `length2`: the width of the taper measured across the face, in mm (optional, defaults to `length`)
|
|
16
18
|
|
|
17
19
|
The function creates a tapered extrusion that extends outward from the specified faces. The taper angle is calculated based on the ratio of length2 to length, creating different bevel profiles depending on these values.
|
|
18
20
|
|
|
21
|
+
#### builder context
|
|
22
|
+
|
|
23
|
+
`anti_chamfer` applies to `BuildPart` only; calling it inside a `BuildSketch` or `BuildLine` raises `RuntimeError`. Inside a `BuildPart` the context object is replaced with the result. Outside any builder it returns a new `Part` and leaves its input alone.
|
|
24
|
+
|
|
25
|
+
Like build123d's own `chamfer` and `fillet`, it takes no `mode` argument.
|
|
26
|
+
|
|
27
|
+
#### raises
|
|
28
|
+
|
|
29
|
+
- `ValueError`: if no faces are given, if any object passed is not a `Face`, or if the faces do not belong to a `Part`
|
|
30
|
+
- `RuntimeError`: if called inside a builder other than `BuildPart`
|
|
31
|
+
|
|
19
32
|
## Usage Notes
|
|
20
33
|
|
|
21
34
|
- When length2 is not specified, the anti-chamfer creates a 45-degree bevel
|
|
@@ -44,7 +57,6 @@ result = anti_chamfer(
|
|
|
44
57
|
base_part.faces().filter_by(Axis.Z)[-1], # top face
|
|
45
58
|
2.0, # length
|
|
46
59
|
2.0, # length2
|
|
47
|
-
|
|
48
60
|
)
|
|
49
61
|
|
|
50
62
|
# Apply anti-chamfer to multiple faces with different taper
|