woodwright 0.1.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.
Files changed (34) hide show
  1. woodwright-0.1.0/.gitignore +75 -0
  2. woodwright-0.1.0/LICENSE +21 -0
  3. woodwright-0.1.0/PKG-INFO +121 -0
  4. woodwright-0.1.0/README.md +96 -0
  5. woodwright-0.1.0/docs/initial_vision.md +19 -0
  6. woodwright-0.1.0/docs/plan.md +577 -0
  7. woodwright-0.1.0/docs/validation.md +145 -0
  8. woodwright-0.1.0/docs/vision.md +358 -0
  9. woodwright-0.1.0/pyproject.toml +65 -0
  10. woodwright-0.1.0/src/woodwright/__init__.py +124 -0
  11. woodwright-0.1.0/src/woodwright/assembly.py +173 -0
  12. woodwright-0.1.0/src/woodwright/cuts.py +791 -0
  13. woodwright-0.1.0/src/woodwright/examples/__init__.py +93 -0
  14. woodwright-0.1.0/src/woodwright/examples/__main__.py +42 -0
  15. woodwright-0.1.0/src/woodwright/examples/_common.py +17 -0
  16. woodwright-0.1.0/src/woodwright/examples/cuts.py +145 -0
  17. woodwright-0.1.0/src/woodwright/examples/frames.py +133 -0
  18. woodwright-0.1.0/src/woodwright/examples/joints.py +454 -0
  19. woodwright-0.1.0/src/woodwright/examples/projects.py +457 -0
  20. woodwright-0.1.0/src/woodwright/export.py +68 -0
  21. woodwright-0.1.0/src/woodwright/joints.py +915 -0
  22. woodwright-0.1.0/src/woodwright/part.py +230 -0
  23. woodwright-0.1.0/src/woodwright/placement.py +177 -0
  24. woodwright-0.1.0/src/woodwright/py.typed +0 -0
  25. woodwright-0.1.0/src/woodwright/rules.py +49 -0
  26. woodwright-0.1.0/src/woodwright/stock.py +15 -0
  27. woodwright-0.1.0/tests/test_assembly.py +133 -0
  28. woodwright-0.1.0/tests/test_cuts.py +325 -0
  29. woodwright-0.1.0/tests/test_examples.py +125 -0
  30. woodwright-0.1.0/tests/test_joints.py +488 -0
  31. woodwright-0.1.0/tests/test_part.py +138 -0
  32. woodwright-0.1.0/tests/test_placement.py +133 -0
  33. woodwright-0.1.0/tests/test_rules.py +19 -0
  34. woodwright-0.1.0/tests/test_smoke.py +5 -0
@@ -0,0 +1,75 @@
1
+ ### macOS
2
+ # Finder metadata
3
+ .DS_Store
4
+
5
+ # Thumbnails
6
+ ._*
7
+
8
+ # Custom folder icons
9
+ Icon
10
+
11
+
12
+ # Volume root files
13
+ .DocumentRevisions-V100
14
+ .fseventsd
15
+ .Spotlight-V100
16
+ .TemporaryItems
17
+ .Trashes
18
+ .VolumeIcon.icns
19
+ .com.apple.timemachine.donotpresent
20
+
21
+ ### JetBrains
22
+ # JetBrains IDE directory
23
+ .idea/
24
+
25
+ # CMake build directories
26
+ cmake-build-*/
27
+
28
+ # File-based project format
29
+ *.iws
30
+ *.iml
31
+
32
+ # IntelliJ build output
33
+ out/
34
+
35
+ ### Python
36
+ # Byte-compiled files
37
+ __pycache__/
38
+ *.py[cod]
39
+ *$py.class
40
+
41
+ # C extensions
42
+ *.so
43
+
44
+ # Distribution / packaging
45
+ build/
46
+ dist/
47
+ *.egg-info/
48
+ *.egg
49
+
50
+ # dotenv environment variable files
51
+ .env
52
+
53
+ # Virtual environments
54
+ .venv
55
+ env/
56
+ venv/
57
+
58
+ # Unit test / coverage reports
59
+ htmlcov/
60
+ .tox/
61
+ .nox/
62
+ .coverage
63
+ .coverage.*
64
+ .pytest_cache/
65
+
66
+ # Type checkers
67
+ .mypy_cache/
68
+
69
+ # Jupyter Notebook
70
+ .ipynb_checkpoints
71
+
72
+ # pyenv
73
+ # .python-version
74
+
75
+ output/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Bohumír Zámečník
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,121 @@
1
+ Metadata-Version: 2.5
2
+ Name: woodwright
3
+ Version: 0.1.0
4
+ Summary: A semantic CAD library for woodworking.
5
+ Project-URL: Homepage, https://github.com/bzamecnik/woodwright
6
+ Project-URL: Source, https://github.com/bzamecnik/woodwright
7
+ Project-URL: Issues, https://github.com/bzamecnik/woodwright/issues
8
+ Project-URL: Documentation, https://github.com/bzamecnik/woodwright/tree/HEAD/docs
9
+ Author-email: Bohumir Zamecnik <bohumir.zamecnik@gmail.com>
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: build123d,cad,cut list,furniture,joinery,woodworking
13
+ Classifier: Development Status :: 3 - Alpha
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.14
19
+ Classifier: Topic :: Multimedia :: Graphics :: 3D Modeling
20
+ Classifier: Topic :: Scientific/Engineering
21
+ Classifier: Typing :: Typed
22
+ Requires-Python: >=3.14
23
+ Requires-Dist: build123d>=0.13.0
24
+ Description-Content-Type: text/markdown
25
+
26
+ # woodwright
27
+
28
+ A semantic CAD library for woodworking. You describe furniture the way a
29
+ woodworker thinks about it: boards with named sides, and the joints between
30
+ them. woodwright works out the joinery, the cut sizes and where every part
31
+ goes, and produces 3D models (STEP, STL), drawings (SVG) and cut lists.
32
+
33
+ It is built on [build123d](https://github.com/gumyr/build123d). This is an
34
+ early alpha: the API will still change.
35
+
36
+ ## Installation
37
+
38
+ ```shell
39
+ pip install woodwright # or: uv add woodwright
40
+ ```
41
+
42
+ Requires Python 3.14. Source: <https://github.com/bzamecnik/woodwright>
43
+
44
+ ## Quickstart
45
+
46
+ A rail tenoned into a stile. You give the design dimensions and the joint;
47
+ the tenon, the mortise, the rail's cut length and its placement are derived.
48
+
49
+ ```python
50
+ from pathlib import Path
51
+
52
+ import woodwright as ww
53
+ from woodwright.export import export_model
54
+
55
+ oak = ww.Stock.board(thickness=20, species="oak")
56
+
57
+ frame = ww.Assembly("corner", root_location=ww.orient(right_end=ww.UP, back_edge=ww.RIGHT))
58
+ stile = frame.add(ww.Board("stile", oak, length=600, width=60))
59
+ rail = frame.add(ww.Board("rail", oak, length=300, width=60)) # shoulder to shoulder
60
+ frame.join(ww.MortiseTenon(tenon=rail.left_end, mortise=stile.back_edge))
61
+
62
+ model = frame.resolve()
63
+ print(model.cut_list())
64
+ export_model(model, Path("output/corner")) # STEP, STL, SVG views, cut list
65
+ ```
66
+
67
+ ```text
68
+ stile 600 x 60 x 20 mm oak
69
+ - mortise 50 x 8 mm, 42 deep, in stile.back_edge
70
+ rail 340 x 60 x 20 mm oak
71
+ - tenon 50 x 8 mm, 40 long, on rail.left_end
72
+ ```
73
+
74
+ Cuts and joints so far: grooves, dados, rabbets, mortises, tenons (haunched,
75
+ mitred), chamfers, mitres, tapers; butt, dado, rabbet, groove, tongue and
76
+ groove, mortise and tenon, bridle, half lap, cross lap, mitre corners and
77
+ splices, sliding, through and half-blind dovetails, and table-top buttons.
78
+
79
+ ## Example library
80
+
81
+ `woodwright.examples` holds over fifty examples, from single cuts through
82
+ joints to projects: a try square, a mallet, a bookshelf, a dovetailed drawer
83
+ with a bottom, a dining table.
84
+
85
+ ```shell
86
+ python -m woodwright.examples list
87
+ python -m woodwright.examples export projects.table --out output
88
+ ```
89
+
90
+ The design ideas are in [docs/vision.md](https://github.com/bzamecnik/woodwright/blob/HEAD/docs/vision.md)
91
+ and [docs/plan.md](https://github.com/bzamecnik/woodwright/blob/HEAD/docs/plan.md).
92
+
93
+ ## Development
94
+
95
+ Install the environment and dependencies:
96
+ ```shell
97
+ uv sync
98
+ pre-commit install # ruff lint + format on commit
99
+ ```
100
+
101
+ Optionally, for notebooks with an interactive 3D viewer:
102
+ ```shell
103
+ uv sync --group notebook
104
+ uv run jupyter lab
105
+ ```
106
+
107
+ Run the tests and the linters:
108
+ ```shell
109
+ uv run pytest
110
+ uv run ruff format
111
+ uv run ruff check --fix
112
+ ```
113
+
114
+ ## License
115
+
116
+ [MIT License](./LICENSE).
117
+
118
+ ### Credits
119
+
120
+ - Ideas and guidance: Bohumír Zámečník
121
+ - Most of the implementation: Claude Code (Opus 5.5)
@@ -0,0 +1,96 @@
1
+ # woodwright
2
+
3
+ A semantic CAD library for woodworking. You describe furniture the way a
4
+ woodworker thinks about it: boards with named sides, and the joints between
5
+ them. woodwright works out the joinery, the cut sizes and where every part
6
+ goes, and produces 3D models (STEP, STL), drawings (SVG) and cut lists.
7
+
8
+ It is built on [build123d](https://github.com/gumyr/build123d). This is an
9
+ early alpha: the API will still change.
10
+
11
+ ## Installation
12
+
13
+ ```shell
14
+ pip install woodwright # or: uv add woodwright
15
+ ```
16
+
17
+ Requires Python 3.14. Source: <https://github.com/bzamecnik/woodwright>
18
+
19
+ ## Quickstart
20
+
21
+ A rail tenoned into a stile. You give the design dimensions and the joint;
22
+ the tenon, the mortise, the rail's cut length and its placement are derived.
23
+
24
+ ```python
25
+ from pathlib import Path
26
+
27
+ import woodwright as ww
28
+ from woodwright.export import export_model
29
+
30
+ oak = ww.Stock.board(thickness=20, species="oak")
31
+
32
+ frame = ww.Assembly("corner", root_location=ww.orient(right_end=ww.UP, back_edge=ww.RIGHT))
33
+ stile = frame.add(ww.Board("stile", oak, length=600, width=60))
34
+ rail = frame.add(ww.Board("rail", oak, length=300, width=60)) # shoulder to shoulder
35
+ frame.join(ww.MortiseTenon(tenon=rail.left_end, mortise=stile.back_edge))
36
+
37
+ model = frame.resolve()
38
+ print(model.cut_list())
39
+ export_model(model, Path("output/corner")) # STEP, STL, SVG views, cut list
40
+ ```
41
+
42
+ ```text
43
+ stile 600 x 60 x 20 mm oak
44
+ - mortise 50 x 8 mm, 42 deep, in stile.back_edge
45
+ rail 340 x 60 x 20 mm oak
46
+ - tenon 50 x 8 mm, 40 long, on rail.left_end
47
+ ```
48
+
49
+ Cuts and joints so far: grooves, dados, rabbets, mortises, tenons (haunched,
50
+ mitred), chamfers, mitres, tapers; butt, dado, rabbet, groove, tongue and
51
+ groove, mortise and tenon, bridle, half lap, cross lap, mitre corners and
52
+ splices, sliding, through and half-blind dovetails, and table-top buttons.
53
+
54
+ ## Example library
55
+
56
+ `woodwright.examples` holds over fifty examples, from single cuts through
57
+ joints to projects: a try square, a mallet, a bookshelf, a dovetailed drawer
58
+ with a bottom, a dining table.
59
+
60
+ ```shell
61
+ python -m woodwright.examples list
62
+ python -m woodwright.examples export projects.table --out output
63
+ ```
64
+
65
+ The design ideas are in [docs/vision.md](https://github.com/bzamecnik/woodwright/blob/HEAD/docs/vision.md)
66
+ and [docs/plan.md](https://github.com/bzamecnik/woodwright/blob/HEAD/docs/plan.md).
67
+
68
+ ## Development
69
+
70
+ Install the environment and dependencies:
71
+ ```shell
72
+ uv sync
73
+ pre-commit install # ruff lint + format on commit
74
+ ```
75
+
76
+ Optionally, for notebooks with an interactive 3D viewer:
77
+ ```shell
78
+ uv sync --group notebook
79
+ uv run jupyter lab
80
+ ```
81
+
82
+ Run the tests and the linters:
83
+ ```shell
84
+ uv run pytest
85
+ uv run ruff format
86
+ uv run ruff check --fix
87
+ ```
88
+
89
+ ## License
90
+
91
+ [MIT License](./LICENSE).
92
+
93
+ ### Credits
94
+
95
+ - Ideas and guidance: Bohumír Zámečník
96
+ - Most of the implementation: Claude Code (Opus 5.5)
@@ -0,0 +1,19 @@
1
+ # Initial vision
2
+
3
+ Let's design a textual markup language to describe furniture design and construction. For a programmer and hobby woodworker it feels limiting that description of furniture to be designed or documented is purely visual - 2D sketches on paper or possibly 3D CAD models which take a lot work to make in specialized software. It makes it unsuitable to discuss with LLMs, to parametrize, easily work with programmatically, construct, modify or convert into other representations (2D plans, 3D models, images).
4
+
5
+ Furniture is typically composed of pieces which are first shaped from rough lumber to given size and shape, including joints, and then assembled together and surface-finished. Thus, it could be represented as a graph where the pieces are vertices and their joints are edges. Also the shaping process can be expressed this way: individual stages can be vertices, while the shaping operations (cutting, drilling, etc.) can be expressed as edges or a different kind of vertices connected by edges. Similarly for gluing, fastening with screws, nails, finishing, etc. The various vertices or edges can have properties, such as a kind of material, sizes, etc.
6
+
7
+ A crucial aspect is representing shapes. One possible paradigm could be constructive solid geometry (CSG), nicely represented e.g. by OpenSCAD, where shapes can be constructed using text-based representation language. Maybe that is too general for furniture. I guess there can be some standard library where common shapes (in a parametric form) can be represented and then applied in a composable way. For example, there can be a primitive "board" as a cuboid with 3 dimensions (length, width, thickness). It may be possible to apply operations, such as cutting through or partially in some way. Those could be combined to make a shape of a mortice or tenon. Those can be then applied on a board to make e.g. an apron for a table or with different parameter a stretcher. Typically multiple copies of the same shape (maybe with different parameters) may be needed. Then they can be assembled by orienting the pieces and connecting their joints.
8
+
9
+ A construction and assembly process could then be expressed by a graph of shaping and joining those primitive objects.
10
+
11
+ 3D modeling software often allows using geometric constraints so that some properties of the shapes can be enforced and some dimensions can be calculated automatically, while others are fixed.
12
+
13
+ The language could be an application of an existing markup language, so that any infrastructure for it can be reused. It should be nicely readable and writable by human. YAML or something similar might be a nice basis.
14
+
15
+ One of the open questions is a coordinate system. Either we can rely one some local cartesian coordinates or try a coordinate-free approach with Geometric Algebra but still keep it approachable for casual users.
16
+
17
+ This opens up door for more advances possibilities, such as static load analysis for safety and material optimization.
18
+
19
+ The original idea comes from 2025-12-11.