molejo 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.
molejo-0.1.0/LICENSE ADDED
@@ -0,0 +1,202 @@
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
178
+
179
+ APPENDIX: How to apply the Apache License to your work.
180
+
181
+ To apply the Apache License to your work, attach the following
182
+ boilerplate notice, with the fields enclosed by brackets "[]"
183
+ replaced with your own identifying information. (Don't include
184
+ the brackets!) The text should be enclosed in the appropriate
185
+ comment syntax for the file format. We also recommend that a
186
+ file or class name and description of purpose be included on the
187
+ same "printed page" as the copyright notice for easier
188
+ identification within third-party archives.
189
+
190
+ Copyright [yyyy] [name of copyright owner]
191
+
192
+ Licensed under the Apache License, Version 2.0 (the "License");
193
+ you may not use this file except in compliance with the License.
194
+ You may obtain a copy of the License at
195
+
196
+ http://www.apache.org/licenses/LICENSE-2.0
197
+
198
+ Unless required by applicable law or agreed to in writing, software
199
+ distributed under the License is distributed on an "AS IS" BASIS,
200
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
+ See the License for the specific language governing permissions and
202
+ limitations under the License.
@@ -0,0 +1,5 @@
1
+ # The test suite is a repository asset, not a source-distribution one: it
2
+ # reads the shared parity fixtures at `fixtures/`, one level above this
3
+ # package directory and outside anything an sdist may contain. Shipping it
4
+ # would ship a suite that cannot run. Clone the repository to run the tests.
5
+ prune tests
molejo-0.1.0/NOTICE ADDED
@@ -0,0 +1,2 @@
1
+ molejo - analytic flexible parts for mechanical CAD
2
+ Copyright (C) 2026 Luis Henrique Cassis Fagundes
molejo-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,169 @@
1
+ Metadata-Version: 2.4
2
+ Name: molejo
3
+ Version: 0.1.0
4
+ Summary: Analytic flexible parts for mechanical CAD: parametric swept shapes evaluated identically in Python and the browser
5
+ Author-email: Luis Henrique Cassis Fagundes <lhfagundes@gmail.com>
6
+ License-Expression: Apache-2.0
7
+ Project-URL: Homepage, https://github.com/LibreSolid/molejo
8
+ Project-URL: Documentation, https://molejo.readthedocs.io
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Manufacturing
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Topic :: Multimedia :: Graphics :: 3D Modeling
13
+ Classifier: Topic :: Scientific/Engineering
14
+ Requires-Python: >=3.10
15
+ Description-Content-Type: text/markdown
16
+ License-File: LICENSE
17
+ License-File: NOTICE
18
+ Requires-Dist: numpy
19
+ Provides-Extra: brep
20
+ Requires-Dist: cadquery-ocp; extra == "brep"
21
+ Dynamic: license-file
22
+
23
+ # molejo
24
+
25
+ *The give in your machine.*
26
+
27
+ **molejo** (Brazilian Portuguese: the springy give of a thing) is an
28
+ analytic representation for the flexible parts of a machine — valve
29
+ springs, timing belts, cable looms, filament — parts whose *shape* is a
30
+ function of machine state, not just their placement.
31
+
32
+ A molejo shape is a serializable **spec**: a planar profile swept along a
33
+ parametric path, whose numeric slots may reference named scalar
34
+ parameters. The spec is the model. Meshes are evaluations of it:
35
+
36
+ - the **Python evaluator** turns a spec plus parameter values into an
37
+ exact triangle mesh (and STL) for build pipelines, geometric tests,
38
+ and collision checks;
39
+ - the **JavaScript evaluator** turns the same spec plus the same values
40
+ into vertex buffers for three.js, cheap enough to re-evaluate every
41
+ animation frame;
42
+ - an optional **B-rep evaluator** (OCCT, via the `brep` extra of the
43
+ Python package) turns the same spec plus the same values into an
44
+ exact solid, for testing architectures that assert on exact shapes.
45
+
46
+ Both evaluators emit the same vertex count in the same order by
47
+ construction — tessellation is fixed and declared in the spec, never
48
+ curvature-adaptive — and are pinned to each other by shared parity
49
+ fixtures.
50
+
51
+ Full documentation: <https://molejo.readthedocs.io>
52
+
53
+ ## What it looks like
54
+
55
+ Authoring is Python-first; the JSON spec is the representation it
56
+ serializes to:
57
+
58
+ ```python
59
+ from molejo import Shape, Circle, Helix, P
60
+
61
+ spring = Shape(
62
+ profile=Circle(radius=2.0),
63
+ path=[Helix(radius=14.0, turns=6.5, height=P.height)],
64
+ path_samples=240, profile_samples=16,
65
+ )
66
+
67
+ mesh = spring.evaluate(height=46.8) # numpy vertices and faces
68
+ spring.to_json() # the spec — what a browser gets
69
+ ```
70
+
71
+ `P.height` is a plain reference, not an expression: derived values
72
+ (`free_length - lift`) are computed in ordinary Python and bound at
73
+ evaluation. The browser side consumes the serialized spec only:
74
+
75
+ ```js
76
+ import { evaluate } from 'molejo';
77
+ evaluate(spec, { height: 50.0 - lift(t) }, buffers); // per frame, in place
78
+ ```
79
+
80
+ ## Why
81
+
82
+ CAD kernels represent rigid geometry; animation systems interpolate
83
+ placement. A compressing spring, a circulating belt, or a cable loom
84
+ following a print head falls between the two: its geometry at any
85
+ instant is exact, closed-form math over a few scalars (a lift, a
86
+ carriage position), but no kernel evaluates that math in both a build
87
+ pipeline and a browser at frame rate.
88
+
89
+ Sampling the shape (morph targets, frame swapping) works for one
90
+ parameter and dies combinatorially at two or three — a loom that follows
91
+ X, Y and Z would need a sampled grid over all of them. molejo instead
92
+ keeps the shape analytic and moves the *evaluation* to wherever it is
93
+ needed.
94
+
95
+ ## Design properties
96
+
97
+ - **Analytic master, evaluations on demand.** The spec defines exact
98
+ curves and surfaces; every mesh is a deterministic sampling of them
99
+ at the declared resolution, and the B-rep evaluator constructs the
100
+ same curves exactly in OCCT. Line- and arc-based sweeps (belts) are
101
+ analytic surfaces; helix and spline sweeps are tolerance-declared
102
+ B-spline surfaces, as in any kernel.
103
+ - **Sweeps only, no booleans.** A closed profile swept along a path is
104
+ watertight by construction; there is no repair pass because no input
105
+ can be broken. Boolean interaction belongs to whatever mesh machinery
106
+ consumes the evaluation.
107
+ - **Parameters are plain named numbers.** molejo does not know where
108
+ they come from — a slider, a kinematic expression, a test instant.
109
+ Expression languages belong to the consumer.
110
+ - **Continuity and self-intersection are the author's obligation.** The
111
+ representation does not police an over-compressed spring; the
112
+ consumer's tests can.
113
+
114
+ ## Status
115
+
116
+ Version 0.1.0, implementing spec version 1: profiles (circle, polygon)
117
+ and path primitives (line, arc, helix, spline, wrap). Both packages
118
+ parse and validate the document against shared fixtures; the Python
119
+ package also authors it (`Shape`, `Circle`, …, `P`).
120
+
121
+ Circle and polygon profiles swept along the whole v1 path vocabulary —
122
+ `line`, `arc`, `helix`, `spline` and `wrap` — evaluate in both runtimes,
123
+ singly or chained, capped or closed into a loop and watertight either
124
+ way, from Python as numpy arrays and binary STL, from JavaScript as
125
+ reusable three.js buffers, pinned to each other by shared parity
126
+ fixtures. The spring in the sample above is one of those fixtures rather
127
+ than a promise, and so are a toothed belt around three pulleys whose
128
+ teeth circulate with a parameter and a filament loom whose head follows
129
+ three. The one gap in the v1 vocabulary raises naming itself: closing a
130
+ loop that is not a wrap.
131
+
132
+ The B-rep evaluator installs with `pip install molejo[brep]` and
133
+ evaluates the same documents to closed OCCT solids —
134
+ `molejo.brep.evaluate(spec, values)` or `shape.brep(**values)` — with the
135
+ same refusals, word for word, as the mesh evaluator. Every parity fixture
136
+ is checked through it on volume and area. An install without the extra
137
+ imports and meshes and exports STL exactly as before; asking it for a
138
+ solid raises naming the extra.
139
+
140
+ molejo 0.1 has done real work before being called a release: it is the
141
+ flexible-part representation of [solid-node](https://github.com/LibreSolid/solid-node)
142
+ machine models, where its springs and belts hold up in animated,
143
+ geometrically tested engines and 3D printers (a V8 engine's valve
144
+ springs, a Metamaquina 2's drive belts) rather than only in this
145
+ repository's fixtures.
146
+
147
+ A package version carries the spec version it implements. Both packages
148
+ carry spec v1 at `0.1.0` and release together for a given spec version.
149
+ One document, two implementations: neither runtime is ever published
150
+ against a spec version the other has not caught up to.
151
+
152
+ Publishing to PyPI (`python/`) and npm (`js/`) is the maintainer's
153
+ explicit decision, never a side effect of building: `scripts/check-dist`,
154
+ the release dry-run, packs each package, installs it into a throwaway
155
+ environment outside this repository and evaluates a fixture there — and
156
+ uploads nothing.
157
+
158
+ ## Origin
159
+
160
+ molejo was born from [solid-node](https://github.com/LibreSolid/solid-node),
161
+ a Python framework for mechanical CAD projects, which needed springs,
162
+ belts and cable looms in animated, testable machine models. solid-node
163
+ adapts molejo as one leaf-geometry technology among the several it
164
+ supports; molejo itself is independent and consumable by any Python or
165
+ three.js project.
166
+
167
+ ## License
168
+
169
+ Apache License 2.0 — see `LICENSE`.
molejo-0.1.0/README.md ADDED
@@ -0,0 +1,147 @@
1
+ # molejo
2
+
3
+ *The give in your machine.*
4
+
5
+ **molejo** (Brazilian Portuguese: the springy give of a thing) is an
6
+ analytic representation for the flexible parts of a machine — valve
7
+ springs, timing belts, cable looms, filament — parts whose *shape* is a
8
+ function of machine state, not just their placement.
9
+
10
+ A molejo shape is a serializable **spec**: a planar profile swept along a
11
+ parametric path, whose numeric slots may reference named scalar
12
+ parameters. The spec is the model. Meshes are evaluations of it:
13
+
14
+ - the **Python evaluator** turns a spec plus parameter values into an
15
+ exact triangle mesh (and STL) for build pipelines, geometric tests,
16
+ and collision checks;
17
+ - the **JavaScript evaluator** turns the same spec plus the same values
18
+ into vertex buffers for three.js, cheap enough to re-evaluate every
19
+ animation frame;
20
+ - an optional **B-rep evaluator** (OCCT, via the `brep` extra of the
21
+ Python package) turns the same spec plus the same values into an
22
+ exact solid, for testing architectures that assert on exact shapes.
23
+
24
+ Both evaluators emit the same vertex count in the same order by
25
+ construction — tessellation is fixed and declared in the spec, never
26
+ curvature-adaptive — and are pinned to each other by shared parity
27
+ fixtures.
28
+
29
+ Full documentation: <https://molejo.readthedocs.io>
30
+
31
+ ## What it looks like
32
+
33
+ Authoring is Python-first; the JSON spec is the representation it
34
+ serializes to:
35
+
36
+ ```python
37
+ from molejo import Shape, Circle, Helix, P
38
+
39
+ spring = Shape(
40
+ profile=Circle(radius=2.0),
41
+ path=[Helix(radius=14.0, turns=6.5, height=P.height)],
42
+ path_samples=240, profile_samples=16,
43
+ )
44
+
45
+ mesh = spring.evaluate(height=46.8) # numpy vertices and faces
46
+ spring.to_json() # the spec — what a browser gets
47
+ ```
48
+
49
+ `P.height` is a plain reference, not an expression: derived values
50
+ (`free_length - lift`) are computed in ordinary Python and bound at
51
+ evaluation. The browser side consumes the serialized spec only:
52
+
53
+ ```js
54
+ import { evaluate } from 'molejo';
55
+ evaluate(spec, { height: 50.0 - lift(t) }, buffers); // per frame, in place
56
+ ```
57
+
58
+ ## Why
59
+
60
+ CAD kernels represent rigid geometry; animation systems interpolate
61
+ placement. A compressing spring, a circulating belt, or a cable loom
62
+ following a print head falls between the two: its geometry at any
63
+ instant is exact, closed-form math over a few scalars (a lift, a
64
+ carriage position), but no kernel evaluates that math in both a build
65
+ pipeline and a browser at frame rate.
66
+
67
+ Sampling the shape (morph targets, frame swapping) works for one
68
+ parameter and dies combinatorially at two or three — a loom that follows
69
+ X, Y and Z would need a sampled grid over all of them. molejo instead
70
+ keeps the shape analytic and moves the *evaluation* to wherever it is
71
+ needed.
72
+
73
+ ## Design properties
74
+
75
+ - **Analytic master, evaluations on demand.** The spec defines exact
76
+ curves and surfaces; every mesh is a deterministic sampling of them
77
+ at the declared resolution, and the B-rep evaluator constructs the
78
+ same curves exactly in OCCT. Line- and arc-based sweeps (belts) are
79
+ analytic surfaces; helix and spline sweeps are tolerance-declared
80
+ B-spline surfaces, as in any kernel.
81
+ - **Sweeps only, no booleans.** A closed profile swept along a path is
82
+ watertight by construction; there is no repair pass because no input
83
+ can be broken. Boolean interaction belongs to whatever mesh machinery
84
+ consumes the evaluation.
85
+ - **Parameters are plain named numbers.** molejo does not know where
86
+ they come from — a slider, a kinematic expression, a test instant.
87
+ Expression languages belong to the consumer.
88
+ - **Continuity and self-intersection are the author's obligation.** The
89
+ representation does not police an over-compressed spring; the
90
+ consumer's tests can.
91
+
92
+ ## Status
93
+
94
+ Version 0.1.0, implementing spec version 1: profiles (circle, polygon)
95
+ and path primitives (line, arc, helix, spline, wrap). Both packages
96
+ parse and validate the document against shared fixtures; the Python
97
+ package also authors it (`Shape`, `Circle`, …, `P`).
98
+
99
+ Circle and polygon profiles swept along the whole v1 path vocabulary —
100
+ `line`, `arc`, `helix`, `spline` and `wrap` — evaluate in both runtimes,
101
+ singly or chained, capped or closed into a loop and watertight either
102
+ way, from Python as numpy arrays and binary STL, from JavaScript as
103
+ reusable three.js buffers, pinned to each other by shared parity
104
+ fixtures. The spring in the sample above is one of those fixtures rather
105
+ than a promise, and so are a toothed belt around three pulleys whose
106
+ teeth circulate with a parameter and a filament loom whose head follows
107
+ three. The one gap in the v1 vocabulary raises naming itself: closing a
108
+ loop that is not a wrap.
109
+
110
+ The B-rep evaluator installs with `pip install molejo[brep]` and
111
+ evaluates the same documents to closed OCCT solids —
112
+ `molejo.brep.evaluate(spec, values)` or `shape.brep(**values)` — with the
113
+ same refusals, word for word, as the mesh evaluator. Every parity fixture
114
+ is checked through it on volume and area. An install without the extra
115
+ imports and meshes and exports STL exactly as before; asking it for a
116
+ solid raises naming the extra.
117
+
118
+ molejo 0.1 has done real work before being called a release: it is the
119
+ flexible-part representation of [solid-node](https://github.com/LibreSolid/solid-node)
120
+ machine models, where its springs and belts hold up in animated,
121
+ geometrically tested engines and 3D printers (a V8 engine's valve
122
+ springs, a Metamaquina 2's drive belts) rather than only in this
123
+ repository's fixtures.
124
+
125
+ A package version carries the spec version it implements. Both packages
126
+ carry spec v1 at `0.1.0` and release together for a given spec version.
127
+ One document, two implementations: neither runtime is ever published
128
+ against a spec version the other has not caught up to.
129
+
130
+ Publishing to PyPI (`python/`) and npm (`js/`) is the maintainer's
131
+ explicit decision, never a side effect of building: `scripts/check-dist`,
132
+ the release dry-run, packs each package, installs it into a throwaway
133
+ environment outside this repository and evaluates a fixture there — and
134
+ uploads nothing.
135
+
136
+ ## Origin
137
+
138
+ molejo was born from [solid-node](https://github.com/LibreSolid/solid-node),
139
+ a Python framework for mechanical CAD projects, which needed springs,
140
+ belts and cable looms in animated, testable machine models. solid-node
141
+ adapts molejo as one leaf-geometry technology among the several it
142
+ supports; molejo itself is independent and consumable by any Python or
143
+ three.js project.
144
+
145
+ ## License
146
+
147
+ Apache License 2.0 — see `LICENSE`.
@@ -0,0 +1,79 @@
1
+ # molejo - analytic flexible parts for mechanical CAD
2
+ # Copyright (C) 2026 Luis Henrique Cassis Fagundes
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ """Analytic flexible parts for mechanical CAD.
6
+
7
+ A molejo shape is a serializable spec -- a planar profile swept along a
8
+ parametric path whose numeric slots may reference named scalar
9
+ parameters. This package is the Python side: the authoring layer that
10
+ writes the spec, and the evaluator that turns spec plus parameter values
11
+ into a deterministic triangle mesh::
12
+
13
+ from molejo import Shape, Circle, Line, P
14
+
15
+ tube = Shape(
16
+ profile=Circle(radius=2.0),
17
+ path=[Line(to=(0.0, 0.0, P.length))],
18
+ path_samples=8, profile_samples=32,
19
+ )
20
+ tube.to_json() # the spec -- what a browser gets
21
+ mesh = tube.evaluate(length=46.8) # numpy vertices and faces
22
+ mesh.to_stl() # binary STL bytes
23
+
24
+ Spec version 1 is defined in :mod:`molejo.spec` and evaluated in
25
+ :mod:`molejo.evaluator`, which sweeps a circle or polygon profile along
26
+ the whole v1 path vocabulary -- ``line``, ``arc``, ``helix``, ``spline``
27
+ and ``wrap`` -- open or closed into a loop.
28
+
29
+ :mod:`molejo.brep` evaluates the same documents exactly, to closed OCCT
30
+ solids, for a consumer whose testing architecture asserts on exact
31
+ shapes::
32
+
33
+ tube.brep(length=46.8).volume()
34
+
35
+ It needs the ``brep`` extra (``pip install molejo[brep]``) and is
36
+ imported only when asked for, so a plain install meshes and exports STL
37
+ on numpy alone. See the repository's openspec/ records.
38
+ """
39
+
40
+ from .authoring import (
41
+ Arc,
42
+ Circle,
43
+ Helix,
44
+ Line,
45
+ P,
46
+ ParamRef,
47
+ Polygon,
48
+ Shape,
49
+ Spline,
50
+ Teeth,
51
+ Wrap,
52
+ )
53
+ from .evaluator import EvaluationError, Mesh, evaluate
54
+ from .spec import SPEC_VERSION, SpecError, parameter_names, validate
55
+
56
+ __author__ = "Luis Henrique Cassis Fagundes"
57
+ __email__ = "lhfagundes@gmail.com"
58
+ __version__ = "0.1.0"
59
+
60
+ __all__ = [
61
+ "SPEC_VERSION",
62
+ "Arc",
63
+ "Circle",
64
+ "EvaluationError",
65
+ "Helix",
66
+ "Line",
67
+ "Mesh",
68
+ "P",
69
+ "ParamRef",
70
+ "Polygon",
71
+ "Shape",
72
+ "SpecError",
73
+ "Spline",
74
+ "Teeth",
75
+ "Wrap",
76
+ "evaluate",
77
+ "parameter_names",
78
+ "validate",
79
+ ]