def test_restrict_on_nested_blocks(self): b1 = Block('a=0;b=a+1') b2 = Block('x=99;z=x-1') composite = Block([b1, b2]) self.assertSimilar(Block('a=0'), composite.restrict(outputs=['a'])) self.assertSimilar(Block('x=99'), composite.restrict(outputs=['x']))
def test_imports(self): 'restrict blocks containing imports' # Test 'from' syntax b = Block('from math import sin, pi\n'\ 'b=sin(pi/a)\n' \ 'd = c * 3.3') sub_block = b.restrict(inputs=('a')) self.assertEqual(sub_block.inputs, set(['a'])) self.assertEqual(sub_block.outputs, set(['b'])) self.assertEqual(sub_block.fromimports, set(['pi', 'sin'])) context = {'a':2, 'c':0.0} sub_block.execute(context) self.assertTrue(context.has_key('b')) self.assertEqual(context['b'], 1.0) # Test 'import' syntax b = Block('import math\n'\ 'b=math.sin(math.pi/a)\n' \ 'd = c * 3.3') sub_block = b.restrict(inputs=('a')) self.assertEqual(sub_block.inputs, set(['a'])) self.assertEqual(sub_block.outputs, set(['b'])) self.assertEqual(sub_block.fromimports, set(['math'])) context = {'a':2, 'c':0.0} sub_block.execute(context) self.assertTrue(context.has_key('b')) self.assertEqual(context['b'], 1.0)
def test_imports(self): 'restrict blocks containing imports' # Test 'from' syntax b = Block('from math import sin, pi\n'\ 'b=sin(pi/a)\n' \ 'd = c * 3.3') sub_block = b.restrict(inputs=('a')) self.assertEqual(sub_block.inputs, set(['a'])) self.assertEqual(sub_block.outputs, set(['b'])) self.assertEqual(sub_block.fromimports, set(['pi', 'sin'])) context = {'a': 2, 'c': 0.0} sub_block.execute(context) self.assertTrue('b' in context) self.assertEqual(context['b'], 1.0) # Test 'import' syntax b = Block('import math\n'\ 'b=math.sin(math.pi/a)\n' \ 'd = c * 3.3') sub_block = b.restrict(inputs=('a')) self.assertEqual(sub_block.inputs, set(['a'])) self.assertEqual(sub_block.outputs, set(['b'])) self.assertEqual(sub_block.fromimports, set(['math'])) context = {'a': 2, 'c': 0.0} sub_block.execute(context) self.assertTrue('b' in context) self.assertEqual(context['b'], 1.0)
def test_restrict_on_nested_blocks(self): b1 = Block('a=0;b=a+1') b2 = Block('x=99;z=x-1') composite=Block([b1,b2]) self.assertSimilar( Block('a=0'), composite.restrict(outputs=['a'])) self.assertSimilar( Block('x=99'), composite.restrict(outputs=['x']))
def test_caching_dep_graph_restrict(self): "Caching: '_dep_graph', 'restrict'" # '_dep_graph' determines the behavior of 'restrict', so we can test # them together. b = Block('a=2; b=a; z=a') self.assertSimilar(b.restrict(outputs='z'), Block('a=2; z=a')) b.sub_blocks = [Block('z=0')] self.assertSimilar(b.restrict(outputs='z'), Block('z=0')) b = Block('a=2; b=a; z=a') self.assertSimilar(b.restrict(outputs='z'), Block('a=2; z=a')) b.ast = Block('z=0').ast self.assertSimilar(b.restrict(outputs='z'), Block('z=0'))
def test_restrict_outputs(): """Test a basic use of the restrict(outputs=(...)) method.""" code = 'x = a + b\ny = b - c\nz = c**2' b = Block(code) br = b.restrict(outputs=('z', )) names = dict(c=5) br.execute(names) assert_equal(sorted(names), ['c', 'z']) assert_equal(names['c'], 5) assert_equal(names['z'], 25)
def test_restrict_outputs(): """Test a basic use of the restrict(outputs=(...)) method.""" code = 'x = a + b\ny = b - c\nz = c**2' b = Block(code) br = b.restrict(outputs=('z',)) names = dict(c=5) br.execute(names) assert_equal(sorted(names), ['c', 'z']) assert_equal(names['c'], 5) assert_equal(names['z'], 25)
def test_bound_inputs(self): code = "c = a * b\n" \ "x = 3 + c\n" block = Block(code) context = DataContext() context['a'] = 1 context['b'] = 2 sub_block = block.restrict(inputs=('c')) self.assertEqual(sub_block.inputs, set(['c']))
def test_restrict_inputs(): """Test a basic use of the restrict(inputs=(...)) method.""" code = 'x = a + b\ny = b - c\nz = c**2' b = Block(code) assert_equal(b.inputs, set(['a','b','c'])) assert_equal(b.outputs, set(['x','y','z'])) br = b.restrict(inputs=('a',)) names = dict(a=100, b=200) br.execute(names) assert_equal(sorted(names), ['a', 'b', 'x']) assert_equal(names['a'], 100) assert_equal(names['b'], 200) assert_equal(names['x'], 300)
def test_restrict_inputs(): """Test a basic use of the restrict(inputs=(...)) method.""" code = 'x = a + b\ny = b - c\nz = c**2' b = Block(code) assert_equal(b.inputs, set(['a', 'b', 'c'])) assert_equal(b.outputs, set(['x', 'y', 'z'])) br = b.restrict(inputs=('a', )) names = dict(a=100, b=200) br.execute(names) assert_equal(sorted(names), ['a', 'b', 'x']) assert_equal(names['a'], 100) assert_equal(names['b'], 200) assert_equal(names['x'], 300)
def test_simple_output_reduction(self): code = 'from blockcanvas.debug.my_operator import add, mul\n' \ 'c = add(a,b)\n' \ 'd = mul(a,16)\n' block = Block(code) context = DataContext() context['a'] = 1 context['b'] = 2 sub_block = block.restrict(outputs=('d')) self.assertEqual(sub_block.inputs, set(['a'])) sub_block.execute(context) self.assertTrue(context.has_key('d')) self.assertEqual(context['d'], 16)
def test_unbound_inputs(self): code = 'from blockcanvas.debug.my_operator import add, mul\n' \ "c = add(a,b)\n" \ "d = mul(c,a)\n" \ "z = add(b, 2)" block = Block(code) context = DataContext() context['a'] = 2 context['b'] = 1 sub_block = block.restrict(inputs=('a')) self.assertEqual(sub_block.inputs, set(['a', 'b'])) self.assertEqual(sub_block.outputs, set(['c', 'd', 'add', 'mul'])) sub_block.execute(context) self.assertTrue(context.has_key('c')) self.assertEqual(context['c'], 3) self.assertTrue(context.has_key('d')) self.assertEqual(context['d'], 6)
# Compose c = Block((a,b)) try: c.execute({}) except NameError, e: test(tracebacks()[-1], 2, 'foo/a.py') try: c.execute({'x':0}) except IndexError, e: test(tracebacks()[-1], 3, 'foo/b.py') del a,b,c # Restrict a = Block(File('foo/a.py', 'a = 0\nb = 1\nc = 2/a')) try: a.restrict(outputs='c').execute({}) except ZeroDivisionError, e: test(tracebacks()[-1], 3, 'foo/a.py') del a # Throw out a sub-block a = Block(File('foo/a.py', 'a = 0\nb = 1\nc = 2/a')) a.sub_blocks.pop(1) try: a.execute({}) except ZeroDivisionError, e: test(tracebacks()[-1], 3, 'foo/a.py') del a # Swap sub-blocks between blocks a = Block(File('foo/a.py', 'a = 0\nb = 1'))
def test_tracebacks(self): 'Tracebacks have correct file names and line numbers' # If we want tracebacks to make sense, then the reported file names and # line numbers need to associate with the code being executed # regardless which block represents and executes the code. def test(tb, lineno, filename): self.assertEqual(tb.tb_lineno, lineno + 1) self.assertEqual(tb.tb_frame.f_code.co_filename, filename) def tracebacks(): "A list of the current exception's traceback objects." tb = sys.exc_info()[2] l = [tb] while tb.tb_next is not None: tb = tb.tb_next l.append(tb) return l class File(StringIO, object): "Extend StringIO with a 'name' attribute." def __init__(self, name, *args, **kw): super(File, self).__init__(*args, **kw) self.name = name a = Block(File('foo/a.py', 'y = x')) try: a.execute({}) except NameError as e: test(tracebacks()[-1], 1, 'foo/a.py') del a a = Block(File('foo/a.py', 'import sys\ny = x')) try: a.execute({}) except NameError as e: test(tracebacks()[-1], 2, 'foo/a.py') #del a # (use below in 'Compose') b = Block( File('foo/b.py', "import re\nl=re.findall('a(.*?)a', 'abacada')\nx = l[2]")) try: b.execute({}) except IndexError as e: test(tracebacks()[-1], 3, 'foo/b.py') #del b # (use below in 'Compose') # Compose c = Block((a, b)) try: c.execute({}) except NameError as e: test(tracebacks()[-1], 2, 'foo/a.py') try: c.execute({'x': 0}) except IndexError as e: test(tracebacks()[-1], 3, 'foo/b.py') del a, b, c # Restrict a = Block(File('foo/a.py', 'a = 0\nb = 1\nc = 2/a')) try: a.restrict(outputs='c').execute({}) except ZeroDivisionError as e: test(tracebacks()[-1], 3, 'foo/a.py') del a # Throw out a sub-block a = Block(File('foo/a.py', 'a = 0\nb = 1\nc = 2/a')) a.sub_blocks.pop(1) try: a.execute({}) except ZeroDivisionError as e: test(tracebacks()[-1], 3, 'foo/a.py') del a # Swap sub-blocks between blocks a = Block(File('foo/a.py', 'a = 0\nb = 1')) b = Block(File('foo/b.py', 'c = 2\nd = x')) a.sub_blocks = b.sub_blocks try: a.execute({}) except NameError as e: test(tracebacks()[-1], 2, 'foo/b.py') a.sub_blocks = b.sub_blocks[:] try: a.execute({}) except NameError as e: test(tracebacks()[-1], 2, 'foo/b.py') del a, b