diff --git a/cadquery/cqgi.py b/cadquery/cqgi.py index fb41e9fd7..87f2ce917 100644 --- a/cadquery/cqgi.py +++ b/cadquery/cqgi.py @@ -219,6 +219,10 @@ class BooleanParameterType(ParameterType): pass +class TupleParameterType(ParameterType): + pass + + class InputParameter: """ Defines a parameter that can be supplied when the model is executed. @@ -304,6 +308,15 @@ def set_value(self, new_value): self.ast_node.value = False else: self.ast_node.id = "False" + elif self.varType == TupleParameterType: + self.ast_node.n = new_value + + # Build the list of constants to set as the tuple value + constants = [] + for nv in new_value: + constants.append(ast.Constant(value=nv)) + self.ast_node.elts = constants + ast.fix_missing_locations(self.ast_node) else: raise ValueError("Unknown Type of var: ", str(self.varType)) @@ -478,7 +491,6 @@ def __init__(self, cq_model): def handle_assignment(self, var_name, value_node): try: - if type(value_node) == ast.Num: self.cqModel.add_script_parameter( InputParameter.create( @@ -504,6 +516,17 @@ def handle_assignment(self, var_name, value_node): value_node, var_name, BooleanParameterType, False ) ) + elif type(value_node) == ast.Tuple: + # Handle multi-length tuples + tup = () + for entry in value_node.elts: + tup = tup + (entry.value,) + + self.cqModel.add_script_parameter( + InputParameter.create( + value_node, var_name, TupleParameterType, tup, + ) + ) elif hasattr(ast, "NameConstant") and type(value_node) == ast.NameConstant: if value_node.value == True: self.cqModel.add_script_parameter( @@ -525,6 +548,7 @@ def handle_assignment(self, var_name, value_node): str: StringParameterType, float: NumberParameterType, int: NumberParameterType, + tuple: TupleParameterType, } self.cqModel.add_script_parameter( @@ -561,8 +585,7 @@ def visit_Assign(self, node): self.handle_assignment(left_side.id, node.value) elif type(node.value) == ast.Tuple: if isinstance(left_side, ast.Name): - # skip unsupported parameter type - pass + self.handle_assignment(left_side.id, node.value) else: # we have a multi-value assignment for n, v in zip(left_side.elts, node.value.elts): diff --git a/tests/test_cqgi.py b/tests/test_cqgi.py index f94463503..33f371ad5 100644 --- a/tests/test_cqgi.py +++ b/tests/test_cqgi.py @@ -7,6 +7,7 @@ defining a build_object function to return results """ +import pytest from cadquery import cqgi from tests import BaseTest import textwrap @@ -16,9 +17,10 @@ height=2.0 width=3.0 (a,b) = (1.0,1.0) + o = (2, 2, 0) foo="bar" - result = "%s|%s|%s|%s" % ( str(height) , str(width) , foo , str(a) ) + result = "%s|%s|%s|%s|%s" % ( str(height) , str(width) , foo , str(a) , str(o) ) show_object(result) """ ) @@ -28,9 +30,10 @@ height=2.0 width=3.0 (a,b) = (1.0,1.0) + o = (2, 2, 0) foo="bar" debug(foo, { "color": 'yellow' } ) - result = "%s|%s|%s|%s" % ( str(height) , str(width) , foo , str(a) ) + result = "%s|%s|%s|%s|%s" % ( str(height) , str(width) , foo , str(a) , str(o) ) show_object(result) debug(height ) """ @@ -41,9 +44,8 @@ class TestCQGI(BaseTest): def test_parser(self): model = cqgi.CQModel(TESTSCRIPT) metadata = model.metadata - self.assertEqual( - set(metadata.parameters.keys()), {"height", "width", "a", "b", "foo"} + set(metadata.parameters.keys()), {"height", "width", "a", "b", "foo", "o"} ) def test_build_with_debug(self): @@ -62,12 +64,19 @@ def test_build_with_empty_params(self): self.assertTrue(result.success) self.assertTrue(len(result.results) == 1) - self.assertTrue(result.results[0].shape == "2.0|3.0|bar|1.0") + self.assertTrue(result.results[0].shape == "2.0|3.0|bar|1.0|(2, 2, 0)") def test_build_with_different_params(self): model = cqgi.CQModel(TESTSCRIPT) - result = model.build({"height": 3.0}) - self.assertTrue(result.results[0].shape == "3.0|3.0|bar|1.0") + result = model.build({"height": 3.0, "o": (3, 3)}) + print(result.results[0].shape) + self.assertTrue(result.results[0].shape == "3.0|3.0|bar|1.0|(3, 3)") + + def test_build_with_nested_tuple_params(self): + model = cqgi.CQModel(TESTSCRIPT) + result = model.build({"height": 3.0, "o": ((2, 2), (3, 3))}) + print(result.results[0].shape) + self.assertTrue(result.results[0].shape == "3.0|3.0|bar|1.0|((2, 2), (3, 3))") def test_describe_parameters(self): script = textwrap.dedent( @@ -222,3 +231,19 @@ def do_stuff(): model = cqgi.parse(script) self.assertEqual(2, len(model.metadata.parameters)) + + def test_invalid_parameter_type(self): + """Contrived test in case a parameter type that is not valid for InputParameter sneaks through.""" + + # Made up parameter class + class UnknowParameter: + def __init__(): + return 1 + + # Set up the most basic InputParameter object that is possible + p = cqgi.InputParameter() + p.varType = UnknowParameter + + # Setting the parameter should throw an unknown parameter type error + with pytest.raises(ValueError) as info: + p.set_value(2)