Skip to content

Commit 94e0976

Browse files
Fix examples and start testing them (#609)
* Fix examples * Added test for examples * Fix example testing code * Sweep example fix * Reformat examples * Test examples from the docs too * Add docutils to the test requirements * Example test fix on win+cleanup * Use union
1 parent 68bac66 commit 94e0976

8 files changed

+84
-10
lines changed

conda/meta.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ requirements:
2525

2626
test:
2727
requires:
28-
- pytest
28+
- pytest
29+
- docutils
2930
source_files:
3031
- tests/
3132
commands:

doc/examples.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -874,7 +874,7 @@ A Parametric Enclosure
874874
topOfLid = topOfLid.rotateAboutCenter((1,0,0),180)
875875

876876
#return the combined result
877-
result =topOfLid.combineSolids(bottom)
877+
result =topOfLid.union(bottom)
878878

879879

880880
.. topic:: Api References
@@ -893,7 +893,7 @@ A Parametric Enclosure
893893
* :py:meth:`Workplane.workplane`
894894
* :py:meth:`Workplane.fillet`
895895
* :py:meth:`Workplane.cut`
896-
* :py:meth:`Workplane.combineSolids`
896+
* :py:meth:`Workplane.union`
897897
* :py:meth:`Workplane.rotateAboutCenter`
898898
* :py:meth:`Workplane.cboreHole`
899899
* :py:meth:`Workplane.cskHole`

examples/Ex009_Polylines.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
# Define the points that the polyline will be drawn to/thru
88
pts = [
9+
(0, H / 2.0),
910
(W / 2.0, H / 2.0),
1011
(W / 2.0, (H / 2.0 - t)),
1112
(t / 2.0, (H / 2.0 - t)),
@@ -30,7 +31,7 @@
3031
# 3. Only half of the I-beam profile has been drawn so far. That half is
3132
# mirrored around the Y-axis to create the complete I-beam profile.
3233
# 4. The I-beam profile is extruded to the final length of the beam.
33-
result = cq.Workplane("front").moveTo(0, H / 2.0).polyline(pts).mirrorY().extrude(L)
34+
result = cq.Workplane("front").polyline(pts).mirrorY().extrude(L)
3435

3536
# Displays the result of this script
3637
show_object(result)

examples/Ex010_Defining_an_Edge_with_a_Spline.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
# 2. Generate our plate with the spline feature and make sure it is a
2020
# closed entity
21-
r = s.lineTo(3.0, 0).lineTo(3.0, 1.0).spline(sPnts).close()
21+
r = s.lineTo(3.0, 0).lineTo(3.0, 1.0).spline(sPnts, includeCurrent=True).close()
2222

2323
# 3. Extrude to turn the wire into a plate
2424
result = r.extrude(0.5)

examples/Ex013_Locating_a_Workplane_on_a_Vertex.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
# 3a. The top-most Z face is selected using the >Z selector.
1212
# 3b. The lower-left vertex of the faces is selected with the <XY selector.
1313
# 3c. A new workplane is created on the vertex to build future geometry on.
14-
result = result.faces(">Z").vertices("<XY").workplane()
14+
result = result.faces(">Z").vertices("<XY").workplane(centerOption="CenterOfMass")
1515

1616
# 4. A circle is drawn with the selected vertex as its center.
1717
# 4a. The circle is cut down through the box to cut the corner out.

examples/Ex023_Sweep.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
defaultRect = cq.Workplane("XY").rect(1.0, 1.0).sweep(path)
1818

1919
# Switch to a polyline path, but have it use the same points as the spline
20-
path = cq.Workplane("XZ").polyline(pts)
20+
path = cq.Workplane("XZ").polyline(pts, includeCurrent=True)
2121

2222
# Using a polyline path leads to the resulting solid having segments rather than a single swept outer face
2323
plineSweep = cq.Workplane("XY").circle(1.0).sweep(path)
@@ -32,5 +32,5 @@
3232
show_object(defaultSweep)
3333
show_object(frenetShell.translate((5, 0, 0)))
3434
show_object(defaultRect.translate((10, 0, 0)))
35-
show_object(plineSweep.translate((15, 0, 0)))
35+
show_object(plineSweep)
3636
show_object(arcSweep.translate((20, 0, 0)))

examples/Ex024_Sweep_With_Multiple_Sections.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,11 @@
7070
.workplane(offset=-5)
7171
.moveTo(0, 4)
7272
.circle(1.5)
73-
.workplane(offset=5)
73+
.workplane(offset=5, centerOption="CenterOfMass")
7474
.circle(1.5)
7575
.moveTo(0, -8)
7676
.circle(1.0)
77-
.workplane(offset=-5)
77+
.workplane(offset=-5, centerOption="CenterOfMass")
7878
.circle(1.0)
7979
.sweep(path, multisection=True)
8080
)

tests/test_examples.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import pytest
2+
3+
from glob import glob
4+
from itertools import chain, count
5+
6+
from docutils.parsers.rst import directives, Directive
7+
from docutils.core import publish_doctree
8+
from docutils.utils import Reporter
9+
10+
import cadquery as cq
11+
from cadquery import cqgi
12+
from cadquery.cq_directive import cq_directive
13+
14+
15+
def find_examples(pattern="examples/*.py"):
16+
17+
for p in glob(pattern):
18+
with open(p, encoding="UTF-8") as f:
19+
code = f.read()
20+
21+
yield code
22+
23+
24+
def find_examples_in_docs(pattern="doc/*.rst"):
25+
26+
# dummy CQ directive for code
27+
class dummy_cq_directive(cq_directive):
28+
29+
codes = []
30+
31+
def run(self):
32+
33+
self.codes.append("\n".join(self.content))
34+
35+
return []
36+
37+
directives.register_directive("cadquery", dummy_cq_directive)
38+
39+
# read and parse all rst files
40+
for p in glob(pattern):
41+
with open(p, encoding="UTF-8") as f:
42+
doc = f.read()
43+
44+
publish_doctree(
45+
doc, settings_overrides={"report_level": Reporter.SEVERE_LEVEL + 1}
46+
)
47+
48+
# yield all code snippets
49+
for c in dummy_cq_directive.codes:
50+
51+
yield c
52+
53+
54+
@pytest.mark.parametrize(
55+
"code", chain(find_examples(), find_examples_in_docs()), ids=count(0)
56+
)
57+
def test_example(code):
58+
59+
# build
60+
res = cqgi.parse(code).build()
61+
62+
assert res.exception is None
63+
64+
# check if the resulting objects are valid
65+
for r in res.results:
66+
r = r.shape
67+
if isinstance(r, cq.Workplane):
68+
for v in r.vals():
69+
if isinstance(v, cq.Shape):
70+
assert v.isValid()
71+
elif isinstance(r, cq.Shape):
72+
assert r.isValid()

0 commit comments

Comments
 (0)