pythonscad-stl-generator 0.1.1__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.
- pythonscad_stl_generator-0.1.1/LICENSE +21 -0
- pythonscad_stl_generator-0.1.1/MANIFEST.in +2 -0
- pythonscad_stl_generator-0.1.1/PKG-INFO +159 -0
- pythonscad_stl_generator-0.1.1/README.md +125 -0
- pythonscad_stl_generator-0.1.1/VERSION.txt +1 -0
- pythonscad_stl_generator-0.1.1/docs/generate-pythonscad-stls.1 +100 -0
- pythonscad_stl_generator-0.1.1/docs/generate-pythonscad-stls.1.md +99 -0
- pythonscad_stl_generator-0.1.1/pyproject.toml +76 -0
- pythonscad_stl_generator-0.1.1/setup.cfg +4 -0
- pythonscad_stl_generator-0.1.1/src/pythonscad_stl_generator/__init__.py +10 -0
- pythonscad_stl_generator-0.1.1/src/pythonscad_stl_generator/cli.py +92 -0
- pythonscad_stl_generator-0.1.1/src/pythonscad_stl_generator/discovery.py +42 -0
- pythonscad_stl_generator-0.1.1/src/pythonscad_stl_generator/presets.py +47 -0
- pythonscad_stl_generator-0.1.1/src/pythonscad_stl_generator/py.typed +0 -0
- pythonscad_stl_generator-0.1.1/src/pythonscad_stl_generator/render.py +215 -0
- pythonscad_stl_generator-0.1.1/src/pythonscad_stl_generator.egg-info/PKG-INFO +159 -0
- pythonscad_stl_generator-0.1.1/src/pythonscad_stl_generator.egg-info/SOURCES.txt +23 -0
- pythonscad_stl_generator-0.1.1/src/pythonscad_stl_generator.egg-info/dependency_links.txt +1 -0
- pythonscad_stl_generator-0.1.1/src/pythonscad_stl_generator.egg-info/entry_points.txt +2 -0
- pythonscad_stl_generator-0.1.1/src/pythonscad_stl_generator.egg-info/requires.txt +7 -0
- pythonscad_stl_generator-0.1.1/src/pythonscad_stl_generator.egg-info/top_level.txt +1 -0
- pythonscad_stl_generator-0.1.1/tests/test_cli.py +42 -0
- pythonscad_stl_generator-0.1.1/tests/test_discovery.py +45 -0
- pythonscad_stl_generator-0.1.1/tests/test_presets.py +39 -0
- pythonscad_stl_generator-0.1.1/tests/test_render.py +183 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Nomike
|
|
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,159 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pythonscad-stl-generator
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Render PythonSCAD design scripts to STL files, including customizer presets.
|
|
5
|
+
Author: Nomike
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/nomike/pythonscad-stl-generator
|
|
8
|
+
Project-URL: Repository, https://github.com/nomike/pythonscad-stl-generator
|
|
9
|
+
Project-URL: Issues, https://github.com/nomike/pythonscad-stl-generator/issues
|
|
10
|
+
Project-URL: Changelog, https://github.com/nomike/pythonscad-stl-generator/blob/main/CHANGELOG.md
|
|
11
|
+
Keywords: 3d,cad,openscad,pythonscad,stl,3d-printing
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Manufacturing
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
22
|
+
Classifier: Topic :: Multimedia :: Graphics :: 3D Modeling
|
|
23
|
+
Classifier: Topic :: Utilities
|
|
24
|
+
Requires-Python: >=3.10
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
License-File: LICENSE
|
|
27
|
+
Requires-Dist: docopt-ng<1,>=0.9
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: build>=1.5; extra == "dev"
|
|
30
|
+
Requires-Dist: pytest>=8; extra == "dev"
|
|
31
|
+
Requires-Dist: pytest-cov>=7; extra == "dev"
|
|
32
|
+
Requires-Dist: ruff>=0.15; extra == "dev"
|
|
33
|
+
Dynamic: license-file
|
|
34
|
+
|
|
35
|
+
# PythonSCAD STL Generator
|
|
36
|
+
|
|
37
|
+
PythonSCAD STL Generator is a small command line tool for batch-rendering
|
|
38
|
+
PythonSCAD design files. It scans a directory for Python files that import
|
|
39
|
+
`pythonscad`, renders each design with the `pythonscad` executable from
|
|
40
|
+
`PATH`, and optionally renders once per customizer preset from a sibling JSON
|
|
41
|
+
file.
|
|
42
|
+
|
|
43
|
+
## Installation
|
|
44
|
+
|
|
45
|
+
Install the published package with `pipx`:
|
|
46
|
+
|
|
47
|
+
```sh
|
|
48
|
+
pipx install pythonscad-stl-generator
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Or install it into an existing environment with `pip`:
|
|
52
|
+
|
|
53
|
+
```sh
|
|
54
|
+
python -m pip install pythonscad-stl-generator
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
For development:
|
|
58
|
+
|
|
59
|
+
```sh
|
|
60
|
+
git clone https://github.com/nomike/pythonscad-stl-generator.git
|
|
61
|
+
cd pythonscad-stl-generator
|
|
62
|
+
python -m pip install -e ".[dev]"
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
PythonSCAD itself is not bundled. The tool expects a `pythonscad` executable to
|
|
66
|
+
be available on `PATH`, or you can point to it explicitly with
|
|
67
|
+
`--pythonscad=/path/to/pythonscad`.
|
|
68
|
+
|
|
69
|
+
## Usage
|
|
70
|
+
|
|
71
|
+
From a directory containing PythonSCAD designs:
|
|
72
|
+
|
|
73
|
+
```sh
|
|
74
|
+
generate-pythonscad-stls
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
The command writes STL files to `output/` by default. A Python file is treated
|
|
78
|
+
as a design when it imports `pythonscad`, for example:
|
|
79
|
+
|
|
80
|
+
```python
|
|
81
|
+
from pythonscad import *
|
|
82
|
+
|
|
83
|
+
width = add_parameter("width", 20)
|
|
84
|
+
cube([width, width, width]).show()
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Useful options:
|
|
88
|
+
|
|
89
|
+
```sh
|
|
90
|
+
generate-pythonscad-stls --output-dir stls
|
|
91
|
+
generate-pythonscad-stls --pythonscad ~/bin/pythonscad
|
|
92
|
+
generate-pythonscad-stls --format 3mf
|
|
93
|
+
generate-pythonscad-stls --dry-run --verbose
|
|
94
|
+
generate-pythonscad-stls --recursive
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
The generated PythonSCAD command includes `--trust-python`, because PythonSCAD
|
|
98
|
+
requires that flag for command-line execution of Python input files.
|
|
99
|
+
|
|
100
|
+
## Customizer Presets
|
|
101
|
+
|
|
102
|
+
If `box.py` has a sibling `box.json`, the tool reads its top-level
|
|
103
|
+
`parameterSets` object and renders once per preset:
|
|
104
|
+
|
|
105
|
+
```json
|
|
106
|
+
{
|
|
107
|
+
"parameterSets": {
|
|
108
|
+
"small": {
|
|
109
|
+
"width": "10"
|
|
110
|
+
},
|
|
111
|
+
"large": {
|
|
112
|
+
"width": "50"
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
"fileFormatVersion": "1"
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
This produces files like:
|
|
120
|
+
|
|
121
|
+
```text
|
|
122
|
+
output/box-small.stl
|
|
123
|
+
output/box-large.stl
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Without a sibling preset file, the design renders once to `output/box.stl`.
|
|
127
|
+
|
|
128
|
+
## Up-To-Date Checks
|
|
129
|
+
|
|
130
|
+
Existing output files are skipped when they are newer than their inputs. For a
|
|
131
|
+
plain design, the input is the `.py` file. For preset renders, both the `.py`
|
|
132
|
+
file and the sibling `.json` preset file must be older than the output.
|
|
133
|
+
|
|
134
|
+
Use `--force` to render everything regardless of timestamps.
|
|
135
|
+
|
|
136
|
+
## Development
|
|
137
|
+
|
|
138
|
+
Run tests:
|
|
139
|
+
|
|
140
|
+
```sh
|
|
141
|
+
python -m pytest
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Run linting and formatting:
|
|
145
|
+
|
|
146
|
+
```sh
|
|
147
|
+
ruff check .
|
|
148
|
+
ruff format .
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Run all pre-commit hooks:
|
|
152
|
+
|
|
153
|
+
```sh
|
|
154
|
+
pre-commit run --all-files
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## License
|
|
158
|
+
|
|
159
|
+
This project is licensed under the MIT License. See `LICENSE`.
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# PythonSCAD STL Generator
|
|
2
|
+
|
|
3
|
+
PythonSCAD STL Generator is a small command line tool for batch-rendering
|
|
4
|
+
PythonSCAD design files. It scans a directory for Python files that import
|
|
5
|
+
`pythonscad`, renders each design with the `pythonscad` executable from
|
|
6
|
+
`PATH`, and optionally renders once per customizer preset from a sibling JSON
|
|
7
|
+
file.
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
Install the published package with `pipx`:
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
pipx install pythonscad-stl-generator
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Or install it into an existing environment with `pip`:
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
python -m pip install pythonscad-stl-generator
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
For development:
|
|
24
|
+
|
|
25
|
+
```sh
|
|
26
|
+
git clone https://github.com/nomike/pythonscad-stl-generator.git
|
|
27
|
+
cd pythonscad-stl-generator
|
|
28
|
+
python -m pip install -e ".[dev]"
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
PythonSCAD itself is not bundled. The tool expects a `pythonscad` executable to
|
|
32
|
+
be available on `PATH`, or you can point to it explicitly with
|
|
33
|
+
`--pythonscad=/path/to/pythonscad`.
|
|
34
|
+
|
|
35
|
+
## Usage
|
|
36
|
+
|
|
37
|
+
From a directory containing PythonSCAD designs:
|
|
38
|
+
|
|
39
|
+
```sh
|
|
40
|
+
generate-pythonscad-stls
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
The command writes STL files to `output/` by default. A Python file is treated
|
|
44
|
+
as a design when it imports `pythonscad`, for example:
|
|
45
|
+
|
|
46
|
+
```python
|
|
47
|
+
from pythonscad import *
|
|
48
|
+
|
|
49
|
+
width = add_parameter("width", 20)
|
|
50
|
+
cube([width, width, width]).show()
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Useful options:
|
|
54
|
+
|
|
55
|
+
```sh
|
|
56
|
+
generate-pythonscad-stls --output-dir stls
|
|
57
|
+
generate-pythonscad-stls --pythonscad ~/bin/pythonscad
|
|
58
|
+
generate-pythonscad-stls --format 3mf
|
|
59
|
+
generate-pythonscad-stls --dry-run --verbose
|
|
60
|
+
generate-pythonscad-stls --recursive
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
The generated PythonSCAD command includes `--trust-python`, because PythonSCAD
|
|
64
|
+
requires that flag for command-line execution of Python input files.
|
|
65
|
+
|
|
66
|
+
## Customizer Presets
|
|
67
|
+
|
|
68
|
+
If `box.py` has a sibling `box.json`, the tool reads its top-level
|
|
69
|
+
`parameterSets` object and renders once per preset:
|
|
70
|
+
|
|
71
|
+
```json
|
|
72
|
+
{
|
|
73
|
+
"parameterSets": {
|
|
74
|
+
"small": {
|
|
75
|
+
"width": "10"
|
|
76
|
+
},
|
|
77
|
+
"large": {
|
|
78
|
+
"width": "50"
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
"fileFormatVersion": "1"
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
This produces files like:
|
|
86
|
+
|
|
87
|
+
```text
|
|
88
|
+
output/box-small.stl
|
|
89
|
+
output/box-large.stl
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Without a sibling preset file, the design renders once to `output/box.stl`.
|
|
93
|
+
|
|
94
|
+
## Up-To-Date Checks
|
|
95
|
+
|
|
96
|
+
Existing output files are skipped when they are newer than their inputs. For a
|
|
97
|
+
plain design, the input is the `.py` file. For preset renders, both the `.py`
|
|
98
|
+
file and the sibling `.json` preset file must be older than the output.
|
|
99
|
+
|
|
100
|
+
Use `--force` to render everything regardless of timestamps.
|
|
101
|
+
|
|
102
|
+
## Development
|
|
103
|
+
|
|
104
|
+
Run tests:
|
|
105
|
+
|
|
106
|
+
```sh
|
|
107
|
+
python -m pytest
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Run linting and formatting:
|
|
111
|
+
|
|
112
|
+
```sh
|
|
113
|
+
ruff check .
|
|
114
|
+
ruff format .
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Run all pre-commit hooks:
|
|
118
|
+
|
|
119
|
+
```sh
|
|
120
|
+
pre-commit run --all-files
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## License
|
|
124
|
+
|
|
125
|
+
This project is licensed under the MIT License. See `LICENSE`.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.1.1
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
.TH GENERATE-PYTHONSCAD-STLS 1 "July 2026" "pythonscad-stl-generator" "User Commands"
|
|
2
|
+
.SH NAME
|
|
3
|
+
generate-pythonscad-stls \- render PythonSCAD designs and customizer presets
|
|
4
|
+
.SH SYNOPSIS
|
|
5
|
+
.B generate-pythonscad-stls
|
|
6
|
+
[\fB--directory=\fR\fIDIR\fR] [\fB--output-dir=\fR\fIDIR\fR]
|
|
7
|
+
[\fB--pythonscad=\fR\fIPATH\fR] [\fB--format=\fR\fIEXT\fR]
|
|
8
|
+
[\fB--force\fR] [\fB--dry-run\fR] [\fB--recursive\fR]
|
|
9
|
+
[\fB-v\fR|\fB--verbose\fR]
|
|
10
|
+
.br
|
|
11
|
+
.B generate-pythonscad-stls
|
|
12
|
+
\fB-h\fR|\fB--help\fR
|
|
13
|
+
.br
|
|
14
|
+
.B generate-pythonscad-stls
|
|
15
|
+
\fB--version\fR
|
|
16
|
+
.SH DESCRIPTION
|
|
17
|
+
.B generate-pythonscad-stls
|
|
18
|
+
scans a directory for Python files that import
|
|
19
|
+
.B pythonscad
|
|
20
|
+
and renders each detected design by invoking the PythonSCAD command line
|
|
21
|
+
application. It passes
|
|
22
|
+
.B --trust-python
|
|
23
|
+
automatically.
|
|
24
|
+
.PP
|
|
25
|
+
When a design has a sibling JSON file with a top-level
|
|
26
|
+
.B parameterSets
|
|
27
|
+
object, the design is rendered once for each named preset using PythonSCAD's
|
|
28
|
+
.B -p
|
|
29
|
+
and
|
|
30
|
+
.B -P
|
|
31
|
+
customizer options.
|
|
32
|
+
.SH OPTIONS
|
|
33
|
+
.TP
|
|
34
|
+
.B -h, --help
|
|
35
|
+
Show help text.
|
|
36
|
+
.TP
|
|
37
|
+
.B --version
|
|
38
|
+
Show the program version.
|
|
39
|
+
.TP
|
|
40
|
+
.BI --directory= DIR
|
|
41
|
+
Directory to scan for PythonSCAD designs. Defaults to the current directory.
|
|
42
|
+
.TP
|
|
43
|
+
.BI --output-dir= DIR
|
|
44
|
+
Directory for generated output files. Relative paths are resolved below the
|
|
45
|
+
scan directory. Defaults to
|
|
46
|
+
.BR output .
|
|
47
|
+
.TP
|
|
48
|
+
.BI --pythonscad= PATH
|
|
49
|
+
PythonSCAD executable to run. Defaults to
|
|
50
|
+
.B pythonscad
|
|
51
|
+
from
|
|
52
|
+
.BR PATH .
|
|
53
|
+
.TP
|
|
54
|
+
.BI --format= EXT
|
|
55
|
+
Output file extension and PythonSCAD export format. Defaults to
|
|
56
|
+
.BR stl .
|
|
57
|
+
.TP
|
|
58
|
+
.B --force
|
|
59
|
+
Render even when output files are newer than their inputs.
|
|
60
|
+
.TP
|
|
61
|
+
.B --dry-run
|
|
62
|
+
Print render commands without executing them.
|
|
63
|
+
.TP
|
|
64
|
+
.B --recursive
|
|
65
|
+
Search for designs recursively below the scan directory.
|
|
66
|
+
.TP
|
|
67
|
+
.B -v, --verbose
|
|
68
|
+
Enable debug logging.
|
|
69
|
+
.SH FILES
|
|
70
|
+
.TP
|
|
71
|
+
.I design.py
|
|
72
|
+
PythonSCAD design script. The file is detected as a design when it imports
|
|
73
|
+
.BR pythonscad .
|
|
74
|
+
.TP
|
|
75
|
+
.I design.json
|
|
76
|
+
Optional customizer preset file with a top-level
|
|
77
|
+
.B parameterSets
|
|
78
|
+
object.
|
|
79
|
+
.SH EXAMPLES
|
|
80
|
+
.EX
|
|
81
|
+
generate-pythonscad-stls
|
|
82
|
+
.EE
|
|
83
|
+
.PP
|
|
84
|
+
.EX
|
|
85
|
+
generate-pythonscad-stls --dry-run --verbose
|
|
86
|
+
.EE
|
|
87
|
+
.PP
|
|
88
|
+
.EX
|
|
89
|
+
generate-pythonscad-stls --pythonscad ~/bin/pythonscad --output-dir stls
|
|
90
|
+
.EE
|
|
91
|
+
.SH EXIT STATUS
|
|
92
|
+
.TP
|
|
93
|
+
.B 0
|
|
94
|
+
All requested renders completed successfully, or no designs were found.
|
|
95
|
+
.TP
|
|
96
|
+
.B 2
|
|
97
|
+
Command line input, scan directory, or preset JSON was invalid.
|
|
98
|
+
.TP
|
|
99
|
+
.B other non-zero status from pythonscad
|
|
100
|
+
At least one render command failed; the PythonSCAD exit code is returned.
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# generate-pythonscad-stls(1)
|
|
2
|
+
|
|
3
|
+
## Name
|
|
4
|
+
|
|
5
|
+
generate-pythonscad-stls - render PythonSCAD designs and customizer presets
|
|
6
|
+
|
|
7
|
+
## Synopsis
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
generate-pythonscad-stls [--directory=<dir>] [--output-dir=<dir>]
|
|
11
|
+
[--pythonscad=<path>] [--format=<ext>]
|
|
12
|
+
[--force] [--dry-run] [--recursive]
|
|
13
|
+
[-v | --verbose]
|
|
14
|
+
generate-pythonscad-stls -h | --help
|
|
15
|
+
generate-pythonscad-stls --version
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Description
|
|
19
|
+
|
|
20
|
+
`generate-pythonscad-stls` scans a directory for Python files that import
|
|
21
|
+
`pythonscad` and renders each detected design by invoking the PythonSCAD
|
|
22
|
+
command line application. It passes `--trust-python` automatically.
|
|
23
|
+
|
|
24
|
+
When a design has a sibling JSON file with a top-level `parameterSets` object,
|
|
25
|
+
the design is rendered once for each named preset using PythonSCAD's `-p` and
|
|
26
|
+
`-P` customizer options.
|
|
27
|
+
|
|
28
|
+
## Options
|
|
29
|
+
|
|
30
|
+
`-h`, `--help`
|
|
31
|
+
: Show help text.
|
|
32
|
+
|
|
33
|
+
`--version`
|
|
34
|
+
: Show the program version.
|
|
35
|
+
|
|
36
|
+
`--directory=<dir>`
|
|
37
|
+
: Directory to scan for PythonSCAD designs. Defaults to the current directory.
|
|
38
|
+
|
|
39
|
+
`--output-dir=<dir>`
|
|
40
|
+
: Directory for generated output files. Relative paths are resolved below the
|
|
41
|
+
scan directory. Defaults to `output`.
|
|
42
|
+
|
|
43
|
+
`--pythonscad=<path>`
|
|
44
|
+
: PythonSCAD executable to run. Defaults to `pythonscad` from `PATH`.
|
|
45
|
+
|
|
46
|
+
`--format=<ext>`
|
|
47
|
+
: Output file extension and PythonSCAD export format. Defaults to `stl`.
|
|
48
|
+
|
|
49
|
+
`--force`
|
|
50
|
+
: Render even when output files are newer than their inputs.
|
|
51
|
+
|
|
52
|
+
`--dry-run`
|
|
53
|
+
: Print render commands without executing them.
|
|
54
|
+
|
|
55
|
+
`--recursive`
|
|
56
|
+
: Search for designs recursively below the scan directory.
|
|
57
|
+
|
|
58
|
+
`-v`, `--verbose`
|
|
59
|
+
: Enable debug logging.
|
|
60
|
+
|
|
61
|
+
## Files
|
|
62
|
+
|
|
63
|
+
`<design>.py`
|
|
64
|
+
: PythonSCAD design script. The file is detected as a design when it imports
|
|
65
|
+
`pythonscad`.
|
|
66
|
+
|
|
67
|
+
`<design>.json`
|
|
68
|
+
: Optional customizer preset file with a top-level `parameterSets` object.
|
|
69
|
+
|
|
70
|
+
## Examples
|
|
71
|
+
|
|
72
|
+
Render designs in the current directory:
|
|
73
|
+
|
|
74
|
+
```sh
|
|
75
|
+
generate-pythonscad-stls
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Preview the commands that would be run:
|
|
79
|
+
|
|
80
|
+
```sh
|
|
81
|
+
generate-pythonscad-stls --dry-run --verbose
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Use a specific PythonSCAD binary and output directory:
|
|
85
|
+
|
|
86
|
+
```sh
|
|
87
|
+
generate-pythonscad-stls --pythonscad ~/bin/pythonscad --output-dir stls
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Exit Status
|
|
91
|
+
|
|
92
|
+
`0`
|
|
93
|
+
: All requested renders completed successfully, or no designs were found.
|
|
94
|
+
|
|
95
|
+
`2`
|
|
96
|
+
: Command line input, scan directory, or preset JSON was invalid.
|
|
97
|
+
|
|
98
|
+
Any other non-zero status from `pythonscad`
|
|
99
|
+
: At least one render command failed; the PythonSCAD exit code is returned.
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "pythonscad-stl-generator"
|
|
7
|
+
dynamic = ["version"]
|
|
8
|
+
description = "Render PythonSCAD design scripts to STL files, including customizer presets."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "Nomike" },
|
|
14
|
+
]
|
|
15
|
+
keywords = ["3d", "cad", "openscad", "pythonscad", "stl", "3d-printing"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 3 - Alpha",
|
|
18
|
+
"Environment :: Console",
|
|
19
|
+
"Intended Audience :: Manufacturing",
|
|
20
|
+
"Operating System :: OS Independent",
|
|
21
|
+
"Programming Language :: Python :: 3",
|
|
22
|
+
"Programming Language :: Python :: 3.10",
|
|
23
|
+
"Programming Language :: Python :: 3.11",
|
|
24
|
+
"Programming Language :: Python :: 3.12",
|
|
25
|
+
"Programming Language :: Python :: 3.13",
|
|
26
|
+
"Programming Language :: Python :: 3.14",
|
|
27
|
+
"Topic :: Multimedia :: Graphics :: 3D Modeling",
|
|
28
|
+
"Topic :: Utilities",
|
|
29
|
+
]
|
|
30
|
+
dependencies = [
|
|
31
|
+
"docopt-ng>=0.9,<1",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
[project.optional-dependencies]
|
|
35
|
+
dev = [
|
|
36
|
+
"build>=1.5",
|
|
37
|
+
"pytest>=8",
|
|
38
|
+
"pytest-cov>=7",
|
|
39
|
+
"ruff>=0.15",
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
[project.scripts]
|
|
43
|
+
generate-pythonscad-stls = "pythonscad_stl_generator.cli:main"
|
|
44
|
+
|
|
45
|
+
[project.urls]
|
|
46
|
+
Homepage = "https://github.com/nomike/pythonscad-stl-generator"
|
|
47
|
+
Repository = "https://github.com/nomike/pythonscad-stl-generator"
|
|
48
|
+
Issues = "https://github.com/nomike/pythonscad-stl-generator/issues"
|
|
49
|
+
Changelog = "https://github.com/nomike/pythonscad-stl-generator/blob/main/CHANGELOG.md"
|
|
50
|
+
|
|
51
|
+
[tool.setuptools]
|
|
52
|
+
package-dir = { "" = "src" }
|
|
53
|
+
include-package-data = true
|
|
54
|
+
|
|
55
|
+
[tool.setuptools.dynamic]
|
|
56
|
+
version = { file = "VERSION.txt" }
|
|
57
|
+
|
|
58
|
+
[tool.setuptools.packages.find]
|
|
59
|
+
where = ["src"]
|
|
60
|
+
|
|
61
|
+
[tool.setuptools.package-data]
|
|
62
|
+
pythonscad_stl_generator = ["py.typed"]
|
|
63
|
+
|
|
64
|
+
[tool.pytest.ini_options]
|
|
65
|
+
addopts = "-ra"
|
|
66
|
+
testpaths = ["tests"]
|
|
67
|
+
|
|
68
|
+
[tool.ruff]
|
|
69
|
+
line-length = 100
|
|
70
|
+
target-version = "py310"
|
|
71
|
+
|
|
72
|
+
[tool.ruff.lint]
|
|
73
|
+
select = ["E", "F", "I", "UP", "B", "SIM"]
|
|
74
|
+
|
|
75
|
+
[tool.ruff.format]
|
|
76
|
+
quote-style = "double"
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"""Tools for batch-rendering PythonSCAD designs."""
|
|
2
|
+
|
|
3
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
4
|
+
|
|
5
|
+
try:
|
|
6
|
+
__version__ = version("pythonscad-stl-generator")
|
|
7
|
+
except PackageNotFoundError:
|
|
8
|
+
__version__ = "0.0.0"
|
|
9
|
+
|
|
10
|
+
__all__ = ["__version__"]
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"""Command line interface for PythonSCAD STL generation."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
import sys
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import NoReturn
|
|
9
|
+
|
|
10
|
+
from docopt import docopt
|
|
11
|
+
|
|
12
|
+
from . import __version__
|
|
13
|
+
from .discovery import discover_designs
|
|
14
|
+
from .presets import PresetError
|
|
15
|
+
from .render import plan_jobs, run_jobs
|
|
16
|
+
|
|
17
|
+
USAGE = """PythonSCAD STL Generator.
|
|
18
|
+
|
|
19
|
+
Usage:
|
|
20
|
+
generate-pythonscad-stls [--directory=<dir>] [--output-dir=<dir>]
|
|
21
|
+
[--pythonscad=<path>] [--format=<ext>]
|
|
22
|
+
[--force] [--dry-run] [--recursive]
|
|
23
|
+
[-v | --verbose]
|
|
24
|
+
generate-pythonscad-stls -h | --help
|
|
25
|
+
generate-pythonscad-stls --version
|
|
26
|
+
|
|
27
|
+
Options:
|
|
28
|
+
-h --help Show this screen.
|
|
29
|
+
--version Show the version.
|
|
30
|
+
--directory=<dir> Directory to scan for PythonSCAD designs [default: .].
|
|
31
|
+
--output-dir=<dir> Directory to save generated files to [default: output].
|
|
32
|
+
--pythonscad=<path> PythonSCAD executable to run [default: pythonscad].
|
|
33
|
+
--format=<ext> Output file extension/export format [default: stl].
|
|
34
|
+
--force Render even when output files are up to date.
|
|
35
|
+
--dry-run Print commands without executing them.
|
|
36
|
+
--recursive Search for designs recursively below the scan directory.
|
|
37
|
+
-v --verbose Show debug messages.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def main(argv: list[str] | None = None) -> int:
|
|
42
|
+
"""Run the CLI and return a process-style exit code."""
|
|
43
|
+
arguments = docopt(USAGE, argv=argv, version=f"generate-pythonscad-stls {__version__}")
|
|
44
|
+
_configure_logging(verbose=bool(arguments["--verbose"]))
|
|
45
|
+
|
|
46
|
+
directory = Path(str(arguments["--directory"])).resolve()
|
|
47
|
+
output_dir = Path(str(arguments["--output-dir"]))
|
|
48
|
+
if not output_dir.is_absolute():
|
|
49
|
+
output_dir = directory / output_dir
|
|
50
|
+
|
|
51
|
+
if not directory.is_dir():
|
|
52
|
+
logging.error("%s is not a directory", directory)
|
|
53
|
+
return 2
|
|
54
|
+
|
|
55
|
+
try:
|
|
56
|
+
designs = discover_designs(directory, recursive=bool(arguments["--recursive"]))
|
|
57
|
+
if not designs:
|
|
58
|
+
logging.info("No PythonSCAD designs found in %s", directory)
|
|
59
|
+
return 0
|
|
60
|
+
|
|
61
|
+
jobs = plan_jobs(
|
|
62
|
+
designs,
|
|
63
|
+
output_dir=output_dir,
|
|
64
|
+
output_format=str(arguments["--format"]),
|
|
65
|
+
pythonscad=str(arguments["--pythonscad"]),
|
|
66
|
+
base_dir=directory,
|
|
67
|
+
)
|
|
68
|
+
except PresetError as error:
|
|
69
|
+
logging.error("%s", error)
|
|
70
|
+
return 2
|
|
71
|
+
|
|
72
|
+
logging.info("Planned %d render job(s) from %d design(s)", len(jobs), len(designs))
|
|
73
|
+
return run_jobs(
|
|
74
|
+
jobs,
|
|
75
|
+
force=bool(arguments["--force"]),
|
|
76
|
+
dry_run=bool(arguments["--dry-run"]),
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def _configure_logging(*, verbose: bool) -> None:
|
|
81
|
+
logging.basicConfig(
|
|
82
|
+
level=logging.DEBUG if verbose else logging.INFO,
|
|
83
|
+
format="%(levelname)s: %(message)s",
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def _entrypoint() -> NoReturn:
|
|
88
|
+
raise SystemExit(main())
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
if __name__ == "__main__":
|
|
92
|
+
sys.exit(main())
|