def test_reserve_name(self): scope = codegen.Scope() name1 = scope.reserve_name('name') name2 = scope.reserve_name('name') self.assertEqual(name1, 'name') self.assertNotEqual(name1, name2) self.assertEqual(name2, 'name2')
def test_reserve_name_function_arg_disallowed(self): scope = codegen.Scope() scope.reserve_name('name') self.assertRaises(AssertionError, scope.reserve_name, 'name', function_arg=True)
def test_reserve_name_function_arg(self): scope = codegen.Scope() scope.reserve_function_arg_name('arg_name') scope.reserve_name('myfunc') func = codegen.Function('myfunc', args=['arg_name'], parent_scope=scope) self.assertNotIn('arg_name2', func.all_reserved_names())
def test_function_call_unknown(self): scope = codegen.Scope() self.assertRaises(AssertionError, codegen.FunctionCall, 'a_function', [], {}, scope)
def test_scope_variable_helper(self): # Scope.variable is more convenient than using VariableReference # manually, we use that from now on. scope = codegen.Scope() name = scope.reserve_name('name') ref1 = codegen.VariableReference(name, scope) ref2 = scope.variable(name) self.assertEqual(ref1, ref2)
def test_reserve_name_nested(self): parent = codegen.Scope() parent_name = parent.reserve_name('name') self.assertEqual(parent_name, 'name') child1 = codegen.Scope(parent_scope=parent) child2 = codegen.Scope(parent_scope=parent) child1_name = child1.reserve_name('name') self.assertNotEqual(child1_name, parent_name) child2_name = child2.reserve_name('name') self.assertNotEqual(child2_name, parent_name) # But children can have same names, they don't shadow each other. # To be deterministic, we expect the same name self.assertEqual(child1_name, child2_name)
def test_string_join_collapse_strings(self): scope = codegen.Scope() scope.reserve_name('tmp', properties={codegen.PROPERTY_TYPE: text_type}) var = scope.variable('tmp') join1 = codegen.ConcatJoin.build([ codegen.String('hello '), codegen.String('there '), var, codegen.String(' how'), codegen.String(' are you?'), ]) self.assertCodeEqual(as_source_code(join1), "'hello there ' + tmp + ' how are you?'")
def test_try_catch_has_assignment_for_name_2(self): scope = codegen.Scope() try_ = codegen.Try([], scope) name = scope.reserve_name('foo') # Add to 'except' try_.except_block.add_assignment(name, codegen.String('x')) self.assertFalse(try_.has_assignment_for_name(name)) # Add to 'else' try_.else_block.add_assignment(name, codegen.String('x'), allow_multiple=True) self.assertTrue(try_.has_assignment_for_name(name))
def test_try_catch_multiple_exceptions(self): scope = codegen.Scope() scope.reserve_name('MyError') scope.reserve_name('OtherError') try_ = codegen.Try([scope.variable('MyError'), scope.variable('OtherError')], scope) self.assertCodeEqual(as_source_code(try_), """ try: pass except (MyError, OtherError): pass """)
def test_variable_reference_function_arg_check(self): scope = codegen.Scope() func_name = scope.reserve_name('myfunc') func = codegen.Function(func_name, args=['my_arg'], parent_scope=scope) # Can't use undefined 'some_name' self.assertRaises(AssertionError, codegen.VariableReference, 'some_name', func) # But can use function argument 'my_arg' ref = codegen.VariableReference('my_arg', func) self.assertCodeEqual(as_source_code(ref), 'my_arg')
def test_try_catch_has_assignment_for_name_1(self): scope = codegen.Scope() try_ = codegen.Try([], scope) name = scope.reserve_name('foo') self.assertFalse(try_.has_assignment_for_name(name)) # Just add to 'try' block try_.try_block.add_assignment(name, codegen.String('x')) # Not all branches define name, so overall can't trust the name # to be defined at the end. self.assertFalse(try_.has_assignment_for_name(name)) # Now add to 'except' block as well try_.except_block.add_assignment(name, codegen.String('x'), allow_multiple=True) self.assertTrue(try_.has_assignment_for_name(name))
def test_multiple_add_assignment_in_inherited_scope(self): # try/if etc inherit their scope from function scope = codegen.Scope() scope.reserve_name('myfunc') func = codegen.Function('myfunc', args=[], parent_scope=scope) try_ = codegen.Try([], func) name = func.reserve_name('name') # We'd really like to ensure no multiple assignments ever, # but the way that if/try etc. work make that hard. # Instead, we add a keyword argument to allow the second assignment. try_.try_block.add_assignment(name, codegen.Number(1)) self.assertRaises(AssertionError, try_.try_block.add_assignment, name, codegen.Number(2)) self.assertRaises(AssertionError, try_.except_block.add_assignment, name, codegen.Number(2)) try_.except_block.add_assignment(name, codegen.Number(2), allow_multiple=True)
def test_try_catch(self): scope = codegen.Scope() scope.reserve_name('MyError') try_ = codegen.Try([scope.variable('MyError')], scope) self.assertCodeEqual(as_source_code(try_), """ try: pass except MyError: pass """) scope.reserve_name('x') scope.reserve_name('y') scope.reserve_name('z') try_.try_block.add_assignment('x', codegen.String("x")) try_.except_block.add_assignment('y', codegen.String("y")) try_.else_block.add_assignment('z', codegen.String("z")) self.assertCodeEqual(as_source_code(try_), """ try: x = 'x' except MyError: y = 'y' else: z = 'z' """)
def test_reserve_name_after_reserve_function_arg(self): scope = codegen.Scope() scope.reserve_function_arg_name('my_arg') name = scope.reserve_name('my_arg') self.assertEqual(name, 'my_arg2')
def test_dict_lookup(self): scope = codegen.Scope() scope.reserve_name('tmp') var = scope.variable('tmp') lookup = codegen.DictLookup(var, codegen.String('x')) self.assertCodeEqual(as_source_code(lookup), "tmp['x']")
def test_variable_reference_check(self): scope = codegen.Scope() self.assertRaises(AssertionError, codegen.VariableReference, 'name', scope)
def test_variable_reference(self): scope = codegen.Scope() name = scope.reserve_name('name') ref = codegen.VariableReference(name, scope) self.assertEqual(as_source_code(ref), 'name')
def test_name_properties(self): scope = codegen.Scope() scope.reserve_name('name', properties={'FOO': True}) self.assertEqual(scope.get_name_properties('name'), {'FOO': True})
def test_reserve_function_arg_after_reserve_name(self): scope = codegen.Scope() scope.reserve_name('my_arg') self.assertRaises(AssertionError, scope.reserve_function_arg_name, 'my_arg')