draftwright 0.1.0__tar.gz → 0.1.2__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.
- {draftwright-0.1.0 → draftwright-0.1.2}/PKG-INFO +3 -1
- {draftwright-0.1.0 → draftwright-0.1.2}/pyproject.toml +4 -1
- {draftwright-0.1.0 → draftwright-0.1.2}/src/draftwright/make_drawing.py +54 -10
- {draftwright-0.1.0 → draftwright-0.1.2}/tests/test_make_drawing.py +6 -3
- {draftwright-0.1.0 → draftwright-0.1.2}/.gitignore +0 -0
- {draftwright-0.1.0 → draftwright-0.1.2}/CHANGELOG.md +0 -0
- {draftwright-0.1.0 → draftwright-0.1.2}/LICENSE +0 -0
- {draftwright-0.1.0 → draftwright-0.1.2}/README.md +0 -0
- {draftwright-0.1.0 → draftwright-0.1.2}/skills/SKILL.md +0 -0
- {draftwright-0.1.0 → draftwright-0.1.2}/src/draftwright/__init__.py +0 -0
- {draftwright-0.1.0 → draftwright-0.1.2}/src/draftwright/pmi.py +0 -0
- {draftwright-0.1.0 → draftwright-0.1.2}/tests/fixtures/nist_ctc_01_asme1_ap242.stp +0 -0
- {draftwright-0.1.0 → draftwright-0.1.2}/tests/test_e2e_standards.py +0 -0
- {draftwright-0.1.0 → draftwright-0.1.2}/tests/test_pmi.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: draftwright
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
4
4
|
Summary: Automated technical-drawing generation for build123d
|
|
5
5
|
Project-URL: Homepage, https://github.com/pzfreo/draftwright
|
|
6
6
|
Project-URL: Repository, https://github.com/pzfreo/draftwright
|
|
@@ -683,6 +683,8 @@ Requires-Python: >=3.10
|
|
|
683
683
|
Requires-Dist: build123d-drafting-helpers>=0.10.0
|
|
684
684
|
Requires-Dist: build123d>=0.9.0
|
|
685
685
|
Requires-Dist: kiwisolver<2,>=1.4
|
|
686
|
+
Provides-Extra: pdf
|
|
687
|
+
Requires-Dist: cairosvg>=2.7; extra == 'pdf'
|
|
686
688
|
Description-Content-Type: text/markdown
|
|
687
689
|
|
|
688
690
|
# draftwright
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "draftwright"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.2"
|
|
8
8
|
description = "Automated technical-drawing generation for build123d"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { file = "LICENSE" }
|
|
@@ -28,6 +28,9 @@ classifiers = [
|
|
|
28
28
|
"Programming Language :: Python :: 3.12",
|
|
29
29
|
]
|
|
30
30
|
|
|
31
|
+
[project.optional-dependencies]
|
|
32
|
+
pdf = ["cairosvg>=2.7"]
|
|
33
|
+
|
|
31
34
|
[project.scripts]
|
|
32
35
|
draftwright = "draftwright.make_drawing:_cli"
|
|
33
36
|
|
|
@@ -1142,6 +1142,27 @@ class Drawing:
|
|
|
1142
1142
|
self.dxf_path = dxf_path
|
|
1143
1143
|
return svg_path, dxf_path
|
|
1144
1144
|
|
|
1145
|
+
def export_pdf(self, out=None) -> str:
|
|
1146
|
+
"""Write a PDF rendered from the SVG. Requires ``cairosvg`` (install with
|
|
1147
|
+
``pip install draftwright[pdf]``). Calls :meth:`export` first if the SVG
|
|
1148
|
+
hasn't been written yet. Returns the PDF path."""
|
|
1149
|
+
try:
|
|
1150
|
+
import cairosvg
|
|
1151
|
+
except ImportError as exc:
|
|
1152
|
+
raise ImportError(
|
|
1153
|
+
"PDF export requires cairosvg. Install it with: pip install draftwright[pdf]"
|
|
1154
|
+
) from exc
|
|
1155
|
+
|
|
1156
|
+
svg_path: str
|
|
1157
|
+
if not hasattr(self, "svg_path") or self.svg_path is None:
|
|
1158
|
+
svg_path, _ = self.export(out=out)
|
|
1159
|
+
else:
|
|
1160
|
+
svg_path = self.svg_path
|
|
1161
|
+
pdf_path = svg_path[:-4] + ".pdf" if svg_path.endswith(".svg") else svg_path + ".pdf"
|
|
1162
|
+
cairosvg.svg2pdf(url=svg_path, write_to=pdf_path)
|
|
1163
|
+
_log.info("PDF → %s", pdf_path)
|
|
1164
|
+
return pdf_path
|
|
1165
|
+
|
|
1145
1166
|
def _add_shapes(self, exporter):
|
|
1146
1167
|
"""Add every view layer and annotation to *exporter* with error context."""
|
|
1147
1168
|
for name, (vis, hid) in self.views.items():
|
|
@@ -1233,15 +1254,14 @@ def _auto_annotate(dwg, a):
|
|
|
1233
1254
|
return a.PV_Y + (y - a.cy) * a.SCALE
|
|
1234
1255
|
|
|
1235
1256
|
# Tighten right-strip outer_limits to the actual iso view left edge now
|
|
1236
|
-
# that the iso has been projected and fitted.
|
|
1237
|
-
#
|
|
1238
|
-
#
|
|
1257
|
+
# that the iso has been projected and fitted. Always apply so that any
|
|
1258
|
+
# future allocations are bounded; warn when the cursor has already passed
|
|
1259
|
+
# the limit (dims already placed may overlap the iso view).
|
|
1239
1260
|
_iso_x0, _, _, _ = _iso_bbox(dwg)
|
|
1240
1261
|
_iso_x_limit = _iso_x0 - 4
|
|
1241
1262
|
for _rs in (a.fv_zones.right, a.pv_zones.right, a.sv_zones.right):
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
else:
|
|
1263
|
+
_rs.outer_limit = min(_rs.outer_limit, _iso_x_limit)
|
|
1264
|
+
if _rs._cursor >= _iso_x_limit:
|
|
1245
1265
|
_log.warning(
|
|
1246
1266
|
"right-strip cursor %.1f >= iso_x limit %.1f: right-strip dims"
|
|
1247
1267
|
" may overlap iso view (iso view overflows into annotation zone)",
|
|
@@ -2672,7 +2692,10 @@ def _fit_iso_view(dwg, a):
|
|
|
2672
2692
|
if extent > 0
|
|
2673
2693
|
]
|
|
2674
2694
|
needed = min(ratios, default=1.0)
|
|
2675
|
-
|
|
2695
|
+
# Apply a 2 % safety margin and floor to 4 decimal places to avoid
|
|
2696
|
+
# floating-point creep past the region boundary. The iso is NTS so
|
|
2697
|
+
# there is no need to constrain to "clean" fractions.
|
|
2698
|
+
factor = math.floor(needed * 0.98 * 10000) / 10000
|
|
2676
2699
|
_project_iso(dwg, a, a.SCALE * factor)
|
|
2677
2700
|
bb = _iso_bbox(dwg)
|
|
2678
2701
|
if not _bbox_within(bb, region):
|
|
@@ -2960,7 +2983,6 @@ def generate_script(
|
|
|
2960
2983
|
|
|
2961
2984
|
|
|
2962
2985
|
def _cli():
|
|
2963
|
-
logging.basicConfig(level=logging.INFO, format="%(message)s")
|
|
2964
2986
|
ap = argparse.ArgumentParser(
|
|
2965
2987
|
description="Zero-AI STEP → technical drawing (SVG + DXF, or editable .py script)",
|
|
2966
2988
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
|
@@ -2997,13 +3019,29 @@ def _cli():
|
|
|
2997
3019
|
"'annotate' — add PMI-derived dimensions to the drawing"
|
|
2998
3020
|
),
|
|
2999
3021
|
)
|
|
3022
|
+
ap.add_argument(
|
|
3023
|
+
"--pdf",
|
|
3024
|
+
action="store_true",
|
|
3025
|
+
help="Also write a PDF (requires draftwright[pdf] / cairosvg)",
|
|
3026
|
+
)
|
|
3027
|
+
ap.add_argument(
|
|
3028
|
+
"-v",
|
|
3029
|
+
"--verbose",
|
|
3030
|
+
action="store_true",
|
|
3031
|
+
help="Show detailed progress (default: warnings and errors only)",
|
|
3032
|
+
)
|
|
3000
3033
|
args = ap.parse_args()
|
|
3001
3034
|
|
|
3035
|
+
logging.basicConfig(
|
|
3036
|
+
level=logging.INFO if args.verbose else logging.WARNING,
|
|
3037
|
+
format="%(message)s",
|
|
3038
|
+
)
|
|
3039
|
+
|
|
3002
3040
|
if args.script and (args.scale is not None or args.page is not None):
|
|
3003
3041
|
ap.error("--scale/--page only apply to direct output; edit the generated script instead")
|
|
3004
3042
|
|
|
3005
3043
|
if args.script:
|
|
3006
|
-
generate_script(
|
|
3044
|
+
py_path = generate_script(
|
|
3007
3045
|
step_file=args.step_file,
|
|
3008
3046
|
out=args.out,
|
|
3009
3047
|
title=args.title,
|
|
@@ -3012,8 +3050,9 @@ def _cli():
|
|
|
3012
3050
|
drawn_by=args.drawn_by,
|
|
3013
3051
|
pmi=args.pmi,
|
|
3014
3052
|
)
|
|
3053
|
+
print(py_path)
|
|
3015
3054
|
else:
|
|
3016
|
-
|
|
3055
|
+
dwg = build_drawing(
|
|
3017
3056
|
step_file=args.step_file,
|
|
3018
3057
|
out=args.out,
|
|
3019
3058
|
title=args.title,
|
|
@@ -3024,6 +3063,11 @@ def _cli():
|
|
|
3024
3063
|
page=args.page,
|
|
3025
3064
|
pmi=args.pmi,
|
|
3026
3065
|
)
|
|
3066
|
+
svg_path, dxf_path = dwg.export()
|
|
3067
|
+
print(svg_path)
|
|
3068
|
+
print(dxf_path)
|
|
3069
|
+
if args.pdf:
|
|
3070
|
+
print(dwg.export_pdf())
|
|
3027
3071
|
|
|
3028
3072
|
|
|
3029
3073
|
if __name__ == "__main__":
|
|
@@ -1167,10 +1167,13 @@ def test_shrunk_iso_keeps_world_to_page_mapping(shrunk_iso_drawing):
|
|
|
1167
1167
|
vis, _hid = dwg.views["iso"]
|
|
1168
1168
|
bb = vis.bounding_box()
|
|
1169
1169
|
assert bb.min.X < centre[0] < bb.max.X and bb.min.Y < centre[1] < bb.max.Y
|
|
1170
|
-
#
|
|
1171
|
-
#
|
|
1170
|
+
# World +Z maps to page +Y; the offset must use the shrunk view scale (not
|
|
1171
|
+
# the sheet scale). Derive the actual shrunk scale from _coords so the
|
|
1172
|
+
# test does not depend on a specific discretised shrink factor.
|
|
1173
|
+
shrunk_scale = dwg._coords["iso"]._scale
|
|
1174
|
+
assert shrunk_scale < dwg.scale, "iso should be shrunk below sheet scale"
|
|
1172
1175
|
raised = dwg.at("iso", cx, cy, cz + 100)
|
|
1173
|
-
assert raised[1] - centre[1] == pytest.approx(100 *
|
|
1176
|
+
assert raised[1] - centre[1] == pytest.approx(100 * shrunk_scale)
|
|
1174
1177
|
|
|
1175
1178
|
|
|
1176
1179
|
@pytest.mark.timeout(60)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|