332d83343f
This commit fixes lookups of class members to make it so that built-in functions that are used as methods/functions of a class work correctly. The mp_convert_member_lookup() function is pretty much completely changed by this commit, but for the most part it's just reorganised and the indenting changed. The functional changes are: - staticmethod and classmethod checks moved to later in the if-logic, because they are less common and so should be checked after the more common cases. - The explicit mp_obj_is_type(member, &mp_type_type) check is removed because it's now subsumed by other, more general tests in this function. - MP_TYPE_FLAG_BINDS_SELF and MP_TYPE_FLAG_BUILTIN_FUN type flags added to make the checks in this function much simpler (now they just test this bit in type->flags). - An extra check is made for mp_obj_is_instance_type(type) to fix lookup of built-in functions. Fixes #1326 and #6198. Signed-off-by: Damien George <damien@micropython.org>
62 lines
1.3 KiB
Python
62 lines
1.3 KiB
Python
# test for correct binding of self when accessing attr of an instance
|
|
|
|
class A:
|
|
def __init__(self, arg):
|
|
self.val = arg
|
|
def __str__(self):
|
|
return 'A.__str__ ' + str(self.val)
|
|
def __call__(self, arg):
|
|
return 'A.__call__', arg
|
|
def foo(self, arg):
|
|
return 'A.foo', self.val, arg
|
|
|
|
def make_closure(x_in):
|
|
x = x_in
|
|
def closure(y):
|
|
return x, y is c
|
|
return closure
|
|
|
|
class C:
|
|
# these act like methods and bind self
|
|
|
|
def f1(self, arg):
|
|
return 'C.f1', self is c, arg
|
|
f2 = lambda self, arg: ('C.f2', self is c, arg)
|
|
f3 = make_closure('f3') # closure
|
|
def f4(self, arg): # generator
|
|
yield self is c, arg
|
|
|
|
# these act like simple variables and don't bind self
|
|
|
|
f5 = int # builtin type
|
|
f6 = abs # builtin function
|
|
f7 = A # user type
|
|
f8 = A(8) # user instance which is callable
|
|
f9 = A(9).foo # user bound method
|
|
|
|
c = C()
|
|
print(c.f1(1))
|
|
print(c.f2(2))
|
|
print(c.f3())
|
|
print(next(c.f4(4)))
|
|
print(c.f5(5))
|
|
print(c.f6(-6))
|
|
print(c.f7(7))
|
|
print(c.f8(8))
|
|
print(c.f9(9))
|
|
|
|
# test calling the functions accessed via the class itself
|
|
print(C.f5(10))
|
|
print(C.f6(-11))
|
|
print(C.f7(12))
|
|
print(C.f8(13))
|
|
print(C.f9(14))
|
|
|
|
# not working in uPy
|
|
#class C(list):
|
|
# # this acts like a method and binds self
|
|
# f1 = list.extend
|
|
#c = C()
|
|
#c.f1([3, 1, 2])
|
|
#print(c)
|