Permalink
Browse files

Merge pull request #39 from steveb/issue/38

Absolutely!  Sorry to let this one sit so long.   If you've got slides from the talk, I'd love to see them!
  • Loading branch information...
etjones committed Sep 8, 2015
2 parents f8dac5f + 3a053c4 commit de02d28e85718eeb70bae088fb794ce096dc1577
Showing with 229 additions and 121 deletions.
  1. +1 −1 Doc/Makefile
  2. +216 −113 solid/solidpython.py
  3. +2 −6 solid/test/test_solidpython.py
  4. +10 −1 tox.ini
View
@@ -3,7 +3,7 @@
# You can set these variables from the command line.
SPHINXOPTS =
-SPHINXBUILD = /usr/local/bin/sphinx-build
+SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = _build
View
@@ -14,112 +14,8 @@
import subprocess
import tempfile
-openscad_builtins = [
- # 2D primitives
- {'name': 'polygon', 'args': ['points', 'paths'], 'kwargs': []} ,
- {'name': 'circle', 'args': [], 'kwargs': ['r', 'd', 'segments']} ,
- {'name': 'square', 'args': [], 'kwargs': ['size', 'center']} ,
-
- # 3D primitives
- {'name': 'sphere', 'args': [], 'kwargs': ['r', 'd', 'segments']} ,
- {'name': 'cube', 'args': [], 'kwargs': ['size', 'center']} ,
- {'name': 'cylinder', 'args': [], 'kwargs': ['r','h','r1', 'r2', 'd', 'd1', 'd2', 'center', 'segments']} ,
- {'name': 'polyhedron', 'args': ['points', 'faces' ], 'kwargs': ['convexity', 'triangles']} ,
-
- # Boolean operations
- {'name': 'union', 'args': [], 'kwargs': []} ,
- {'name': 'intersection', 'args': [], 'kwargs': []} ,
- {'name': 'difference', 'args': [], 'kwargs': []} ,
- {'name': 'hole', 'args': [], 'kwargs': []} ,
- {'name': 'part', 'args': [], 'kwargs': []} ,
-
- # Transforms
- {'name': 'translate', 'args': [], 'kwargs': ['v']} ,
- {'name': 'scale', 'args': [], 'kwargs': ['v']} ,
- {'name': 'rotate', 'args': [], 'kwargs': ['a', 'v']} ,
- {'name': 'mirror', 'args': ['v'], 'kwargs': []},
- {'name': 'multmatrix', 'args': ['m'], 'kwargs': []},
- {'name': 'color', 'args': ['c'], 'kwargs': []},
- {'name': 'minkowski', 'args': [], 'kwargs': []},
- {'name': 'hull', 'args': [], 'kwargs': []},
- {'name': 'render', 'args': [], 'kwargs': ['convexity']},
-
- # 2D to 3D transitions
- # FIXME: linear_extrude now has a scale parameter as of OpenSCAD 13.06 -ETJ 20 Jan 2014
- # Also: Check release notes for any other changes to the language, here:
- # https://github.com/openscad/openscad/blob/master/RELEASE_NOTES
- # Add Colors as here: http://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Transformations
- {'name': 'linear_extrude', 'args': [], 'kwargs': ['height', 'center', 'convexity', 'twist','slices']} ,
- {'name': 'rotate_extrude', 'args': [], 'kwargs': ['convexity', 'segments']} ,
- {'name': 'dxf_linear_extrude', 'args': ['file'],'kwargs': ['layer', 'height', 'center', 'convexity', 'twist', 'slices']} ,
- {'name': 'projection', 'args': [], 'kwargs': ['cut']} ,
- {'name': 'surface', 'args': ['file'], 'kwargs': ['center','convexity','invert']} ,
- {'name': 'text', 'args': ['text'], 'kwargs': ['size','font','halign','valign','spacing','direction','language','script','segments']} ,
-
- #Child/ren
- {'name': 'child', 'args': [], 'kwargs': ['index', 'vector', 'range']} ,
- {'name': 'children', 'args': [], 'kwargs': ['index', 'vector', 'range']} ,
-
- # FIXME: support 'resize' as well -ETJ 20 Jan 2014
-
- # Import/export
- {'name': 'import_stl', 'args': ['file'], 'kwargs': ['layer', 'origin']} ,
- {'name': 'import_dxf', 'args': ['file'], 'kwargs': ['layer', 'origin']},
- {'name': 'import_', 'args': ['file'], 'kwargs': ['layer', 'origin']},
-
-
- # Modifiers; These are implemented by calling e.g.
- # obj.set_modifier( '*') or
- # obj.set_modifier('disable')
- # disable(obj)
- # on an existing object.
- # {'name': 'background', 'args': [], 'kwargs': []}, # %{}
- # {'name': 'debug', 'args': [], 'kwargs': []} , # #{}
- # {'name': 'root', 'args': [], 'kwargs': []} , # !{}
- # {'name': 'disable', 'args': [], 'kwargs': []} , # *{}
-
- {'name': 'intersection_for', 'args': ['n'], 'kwargs': []} , # e.g.: intersection_for(n=[1..6]){}
-
- # Not really needed for Python. Also needs a **args argument so it accepts anything
- {'name': 'assign', 'args': [], 'kwargs': []}
-]
-
-# Some functions need custom code in them; put that code here
-builtin_literals = {
- 'polygon': '''class polygon(OpenSCADObject):
- def __init__(self, points, paths=None):
- if not paths:
- paths = [ list(range(len(points)))]
- OpenSCADObject.__init__(self, 'polygon', {'points':points, 'paths': paths})
-
- ''',
- 'hole': '''class hole(OpenSCADObject):
- def __init__(self):
- OpenSCADObject.__init__(self, 'hole', {})
- self.set_hole(True)
-
- ''',
- 'part': '''class part(OpenSCADObject):
- def __init__(self):
- OpenSCADObject.__init__(self, 'part', {})
- self.set_part_root(True)
- ''',
- # Import, import_dxf, and import_stl all resolve to the same OpenSCAD
- # keyword, 'import'
- 'import_': '''class import_(OpenSCADObject):
- def __init__(self, file, origin=(0,0), layer=None):
- OpenSCADObject.__init__(self, 'import', {'file':file, 'origin':origin, 'layer':layer})
- ''',
- 'import_dxf': '''class import_dxf(OpenSCADObject):
- def __init__(self, file, origin=(0,0), layer=None):
- OpenSCADObject.__init__(self, 'import', {'file':file, 'origin':origin, 'layer':layer})
- ''',
- 'import_stl': '''class import_stl(OpenSCADObject):
- def __init__(self, file, origin=(0,0), layer=None):
- OpenSCADObject.__init__(self, 'import', {'file':file, 'origin':origin, 'layer':layer})
- '''
-}
+
# These are features added to SolidPython but NOT in OpenSCAD.
# Mark them for special treatment
non_rendered_classes = ['hole', 'part']
@@ -815,12 +711,219 @@ def parse_scad_callables(scad_code_str):
return callables
-# Dynamically add all builtins to this namespace on import
-for sym_dict in openscad_builtins:
- # entries in 'builtin_literals' override the entries in 'openscad_builtins'
- if sym_dict['name'] in builtin_literals:
- class_str = builtin_literals[sym_dict['name']]
- else:
- class_str = new_openscad_class_str(sym_dict['name'], sym_dict['args'], sym_dict['kwargs'])
+# ===============================
+# Classes for OpenSCAD builtins =
+# ===============================
+class polygon(OpenSCADObject):
+ def __init__(self, points, paths=None):
+ if not paths:
+ paths = [list(range(len(points)))]
+ OpenSCADObject.__init__(self, 'polygon',
+ {'points': points, 'paths': paths})
+
+
+class circle(OpenSCADObject):
+ def __init__(self, r=None, d=None, segments=None):
+ OpenSCADObject.__init__(self, 'circle',
+ {'r': r, 'd': d, 'segments': segments})
+
+
+class square(OpenSCADObject):
+ def __init__(self, size=None, center=None):
+ OpenSCADObject.__init__(self, 'square',
+ {'size': size, 'center': center})
+
+
+class sphere(OpenSCADObject):
+ def __init__(self, r=None, d=None, segments=None):
+ OpenSCADObject.__init__(self, 'sphere',
+ {'r': r, 'd': d, 'segments': segments})
+
+
+class cube(OpenSCADObject):
+ def __init__(self, size=None, center=None):
+ OpenSCADObject.__init__(self, 'cube',
+ {'size': size, 'center': center})
+
+
+class cylinder(OpenSCADObject):
+ def __init__(self, r=None, h=None, r1=None, r2=None, d=None, d1=None,
+ d2=None, center=None, segments=None):
+ OpenSCADObject.__init__(self, 'cylinder',
+ {'r': r, 'h': h, 'r1': r1, 'r2': r2, 'd': d,
+ 'd1': d1, 'd2': d2, 'center': center,
+ 'segments': segments})
+
+
+class polyhedron(OpenSCADObject):
+ def __init__(self, points, faces, convexity=None, triangles=None):
+ OpenSCADObject.__init__(self, 'polyhedron',
+ {'points': points, 'faces': faces,
+ 'convexity': convexity,
+ 'triangles': triangles})
+
+
+class union(OpenSCADObject):
+ def __init__(self):
+ OpenSCADObject.__init__(self, 'union', {})
+
+
+class intersection(OpenSCADObject):
+ def __init__(self):
+ OpenSCADObject.__init__(self, 'intersection', {})
+
+
+class difference(OpenSCADObject):
+ def __init__(self):
+ OpenSCADObject.__init__(self, 'difference', {})
+
+
+class hole(OpenSCADObject):
+ def __init__(self):
+ OpenSCADObject.__init__(self, 'hole', {})
+ self.set_hole(True)
+
+
+class part(OpenSCADObject):
+ def __init__(self):
+ OpenSCADObject.__init__(self, 'part', {})
+ self.set_part_root(True)
+
+
+class translate(OpenSCADObject):
+ def __init__(self, v=None):
+ OpenSCADObject.__init__(self, 'translate', {'v': v})
+
- exec(class_str)
+class scale(OpenSCADObject):
+ def __init__(self, v=None):
+ OpenSCADObject.__init__(self, 'scale', {'v': v})
+
+
+class rotate(OpenSCADObject):
+ def __init__(self, a=None, v=None):
+ OpenSCADObject.__init__(self, 'rotate', {'a': a, 'v': v})
+
+
+class mirror(OpenSCADObject):
+ def __init__(self, v):
+ OpenSCADObject.__init__(self, 'mirror', {'v': v})
+
+
+class multmatrix(OpenSCADObject):
+ def __init__(self, m):
+ OpenSCADObject.__init__(self, 'multmatrix', {'m': m})
+
+
+class color(OpenSCADObject):
+ def __init__(self, c):
+ OpenSCADObject.__init__(self, 'color', {'c': c})
+
+
+class minkowski(OpenSCADObject):
+ def __init__(self):
+ OpenSCADObject.__init__(self, 'minkowski', {})
+
+
+class hull(OpenSCADObject):
+ def __init__(self):
+ OpenSCADObject.__init__(self, 'hull', {})
+
+
+class render(OpenSCADObject):
+ def __init__(self, convexity=None):
+ OpenSCADObject.__init__(self, 'render', {'convexity': convexity})
+
+
+class linear_extrude(OpenSCADObject):
+ def __init__(self, height=None, center=None, convexity=None, twist=None,
+ slices=None):
+ OpenSCADObject.__init__(self, 'linear_extrude',
+ {'height': height, 'center': center,
+ 'convexity': convexity, 'twist': twist,
+ 'slices': slices})
+
+
+class rotate_extrude(OpenSCADObject):
+ def __init__(self, convexity=None, segments=None):
+ OpenSCADObject.__init__(self, 'rotate_extrude',
+ {'convexity': convexity, 'segments': segments})
+
+
+class dxf_linear_extrude(OpenSCADObject):
+ def __init__(self, file, layer=None, height=None, center=None,
+ convexity=None, twist=None, slices=None):
+ OpenSCADObject.__init__(self, 'dxf_linear_extrude',
+ {'file': file, 'layer': layer,
+ 'height': height, 'center': center,
+ 'convexity': convexity, 'twist': twist,
+ 'slices': slices})
+
+
+class projection(OpenSCADObject):
+ def __init__(self, cut=None):
+ OpenSCADObject.__init__(self, 'projection', {'cut': cut})
+
+
+class surface(OpenSCADObject):
+ def __init__(self, file, center=None, convexity=None, invert=None):
+ OpenSCADObject.__init__(self, 'surface',
+ {'file': file, 'center': center,
+ 'convexity': convexity, 'invert': invert})
+
+
+class text(OpenSCADObject):
+ def __init__(self, text, size=None, font=None, halign=None, valign=None,
+ spacing=None, direction=None, language=None, script=None,
+ segments=None):
+ OpenSCADObject.__init__(self, 'text',
+ {'text': text, 'size': size, 'font': font,
+ 'halign': halign, 'valign': valign,
+ 'spacing': spacing, 'direction': direction,
+ 'language': language, 'script': script,
+ 'segments': segments})
+
+
+class child(OpenSCADObject):
+ def __init__(self, index=None, vector=None, range=None):
+ OpenSCADObject.__init__(self, 'child',
+ {'index': index, 'vector': vector,
+ 'range': range})
+
+
+class children(OpenSCADObject):
+ def __init__(self, index=None, vector=None, range=None):
+ OpenSCADObject.__init__(self, 'children',
+ {'index': index, 'vector': vector,
+ 'range': range})
+
+
+class import_stl(OpenSCADObject):
+ def __init__(self, file, origin=(0, 0), layer=None):
+ OpenSCADObject.__init__(self, 'import',
+ {'file': file, 'origin': origin,
+ 'layer': layer})
+
+
+class import_dxf(OpenSCADObject):
+ def __init__(self, file, origin=(0, 0), layer=None):
+ OpenSCADObject.__init__(self, 'import',
+ {'file': file, 'origin': origin,
+ 'layer': layer})
+
+
+class import_(OpenSCADObject):
+ def __init__(self, file, origin=(0, 0), layer=None):
+ OpenSCADObject.__init__(self, 'import',
+ {'file': file, 'origin': origin,
+ 'layer': layer})
+
+
+class intersection_for(OpenSCADObject):
+ def __init__(self, n):
+ OpenSCADObject.__init__(self, 'intersection_for', {'n': n})
+
+
+class assign(OpenSCADObject):
+ def __init__(self):
+ OpenSCADObject.__init__(self, 'assign', {})
@@ -45,14 +45,10 @@
class TestSolidPython(DiffOutput):
# test cases will be dynamically added to this instance
- scad_path = ['solid', '..', '.']
def expand_scad_path(self, filename):
- for path in self.scad_path:
- full_path = os.path.join(path, filename)
- if os.path.exists(full_path):
- return full_path
- return None
+ path = os.path.join(os.path.dirname(os.path.realpath(__file__)), '../')
+ return os.path.join(path, filename)
def test_infix_union(self):
a = cube(2)
View
11 tox.ini
@@ -1,9 +1,18 @@
# content of: tox.ini , put in same dir as setup.py
[tox]
-envlist = py27
+envlist = py27,pep8
[testenv]
commands=
python solid/test/test_screw_thread.py
python solid/test/test_solidpython.py
python solid/test/test_utils.py
+
+[testenv:pep8]
+deps=flake8
+commands =
+ flake8 solid
+
+[flake8]
+show-source = true
+ignore = E111,E113,E121,E122,E126,E127,E201,E202,E203,E221,E222,E231,E241,E261,E265,E303,E401,E501,E711,F401,F403,F841,H101,H201,H301,H302,H303,H305,H306,H307,H404,H405,W291,W293,W391

0 comments on commit de02d28

Please sign in to comment.