def test_list_iteration(ut):    
    s = '''
l1 = [1, 2, 3]

def iter_over_list():
    for e in l1:
        return e

r = iter_over_list()


def iter_over_list2():
    for e in list(l1):
        return e


r2 = iter_over_list2()
    '''
    ps.checkString(s)
    r = find_in_history('r', ps)
    ut.assertNums([1, 2, 3], r[0:3])
    ut.assertCont(r[3])

    r = find_in_history('r2', ps)
    # unknown type due to unknown list function
    ut._assertType(TypeError, r[0])
def test_bound_method_call_and_obj_new_attr_creation(ut):
    # exercise
    s = '''
class B:
    def x(self, p):
        self.p = p
        return self
        
new_b = B().x(2)
    '''
    ps.checkString(s)

    # verify
    class_types = find_in_history('B', ps)
    ut.assertEqual(1, len(class_types))
    class_type = class_types[0]
    ut.assertEqual('B', class_type.name)
    ut.assertEqual(1, len(class_type.attrs))
    
    clo = class_type.attrs.get('x')
    ut.assertTrue(isinstance(clo, list))
    ut.assertTrue(len(clo))
    ut.assertTrue(isinstance(clo[0], ps.Closure))
    ut.assertEqual([], clo[0].defaults)
    
    # assert new instance
    values = find_in_history("new_b", ps)
    ut.assertEqual(1, len(values))
    new_b = values[0]
    ut.assertTrue(isinstance(new_b, ps.ObjType))
    ut.assertEqual(2, new_b.attrs.get("p")[0].n)
def test_object_initialized_by_calling_class_obj_as_attribute(ut):
    s = '''
class B:
    pass
 
b = B()
b.x = B
 
b_inst = b.x()
    '''
    ps.checkString(s)

    b_insts = find_in_history('b_inst', ps)
    ut.assertEqual(1, len(b_insts))
    b_inst = b_insts[0]
    
    # check count of attributes on new instance of B, must be x

    # assert type of new instance
    ut.assertTrue(isinstance(b_inst, ps.ObjType))
    
    # assert class of new instance
    b_cls = find_in_history('B', ps)
    ut.assertEqual(1, len(b_cls))
    B = b_cls[0]
    
    # assert class type 
    ut.assertEqual(B, b_inst.classtype)
def test_tuple_unpack():
    # exercise
    ps.checkString('''a = {1: 2, 3: 4}
for key, value in a.iteritems():
    b = key
    c = value''')

    # verify
    r = find_in_history('key', ps)
    ut.assertEqual(2, len(r))
    ut.assertNums([1, 3], r)

    r = find_in_history('value', ps)
    ut.assertEqual(2, len(r))
    ut.assertNums([2, 4], r)
def test_simple_init_call_where_self_arg_required(ut):
    s = '''
 
class WithInit:
     
    def __init__(self, p, p2):
        self.p = p
        self.p1 = p2
         
    def z(self):
        return WithInit(3, 42);
        
    def knows_about_fn_from_module(self):
        y = module_fn()
        return y
        
 
with_init = WithInit(1, 2)
with_init.z()

def module_fn():
    return 20
    
result_from_module_fn = with_init.knows_about_fn_from_module()
'''
    ps.checkString(s)
 
    with_inits = find_in_history('with_init', ps)
    ut.assertEqual(1, len(with_inits))
    with_init = with_inits[0]
    # assert type of new instance
    ut.assertTrue(isinstance(with_init, ps.ObjType))
    ut.assertEqual(5, len(with_init.attrs))
    ut.assertEqual(1, with_init.attrs.get("p")[0].n)
    ut.assertEqual(2, with_init.attrs.get("p1")[0].n)
    # assert class type
    cls = find_in_history('WithInit', ps)
    ut.assertEqual(1, len(cls))
    Cls = cls[0]
    # assert class type 
    ut.assertEqual(Cls, with_init.classtype)
    
    
    results = find_in_history('result_from_module_fn', ps)
    ut.assertEqual(1, len(results))
    result = results[0]
    # assert class type 
    ut.assertEqual(20, result.n)
def test_dict_iteration_by_keys_using_explicit_call_to_keys_method(ut):
    '''
    Support the simplest case - one iteration over dictionary using explicit keys() call

    For(target=Name(id='k', ctx=Store()),
        iter=Call(func=Attribute(value=Name(id='dict_', ctx=Load()),
                  attr='keys', ctx=Load()), args=[], keywords=[], starargs=None, kwargs=None),
                  body=[...], orelse=[]) 
    '''
    s = '''
dict_ = {1: 2, 3: 4}

def iter_over_dict_keys():
    for k in dict_.keys():
        # which element returned is undefined
        # (actually, it is defined by the order in which keys are iterated,
        #  which in turn is defined by the hash function, but it's
        #  too complicated)
        # we'll assume that any value can be returned
        return dict_.get(k)

new_values = iter_over_dict_keys()
    '''

    ps.checkString(s)
    r = find_in_history('new_values', ps)
    ut.assertEqual(3, len(r))
    ut.assertNums([2, 4], r[0:2])
    ut.assertCont(r[2])  # represents implicitly returned None
def test_dict_default_value():
    # exercise
    ps.checkString('a = {"a": 1}; b = a.get("b", 2);')

    # verify
    r = find_in_history('b', ps)
    ut.assertEqual(2, len(r))
    ut.assertNums([1, 2], r)
def test_obj_initialized_without_explicit_init_call(ut):
    s = '''
class B:
    pass
 
b = B()
'''
    ps.checkString(s)
    class_types = find_in_history('B', ps)
    ut.assertEqual(1, len(class_types))
    class_type = class_types[0]
    ut.assertEqual('B', class_type.name)
    ut.assertEqual(0, len(class_type.attrs))
def test_bound_call_with_actual_keywords_returned(ut):
    c = '''
class A:
    def m(self, default_x=100, y=200):
        return default_x, y
 
a = A()
result = a.m(100, 200)
result2 = a.m(100, y=200)
result3 = a.m(default_x=100)
    '''
    ps.checkString(c)
    results = find_in_history('result', ps)
def test_bound_call_with_actual_kwargs_returned(ut):
    c = '''
class A:
    def m(self, **kwargs):
        return kwargs
 
a = A()
result = a.m(keyarg='100', keyarg2='200')
    '''
    ps.checkString(c)
    results = find_in_history('result', ps)

    ut.assertEqual(1, len(results))
    result_as_pair = results[0].dict
    ut.assertDict({'keyarg': '100', 'keyarg2': '200'}, results[0])
    result_as_pair.fst