py: Don't try to "bind" types store as attributes of objects.
This was hit when trying to make urlparse.py from stdlib run. Took quite some time to debug. TODO: Reconsile bound method creation process better, maybe callable is to generic type to bind at all?
This commit is contained in:
parent
69f3eb2c96
commit
9511f60f01
@ -333,6 +333,9 @@ STATIC void instance_convert_return_attr(mp_obj_t self, mp_obj_t member, mp_obj_
|
||||
// return a bound method, with self being the type of this object
|
||||
dest[0] = ((mp_obj_static_class_method_t*)member)->fun;
|
||||
dest[1] = mp_obj_get_type(self);
|
||||
} else if (MP_OBJ_IS_TYPE(member, &mp_type_type)) {
|
||||
// Don't try to bind types
|
||||
dest[0] = member;
|
||||
} else if (mp_obj_is_callable(member)) {
|
||||
// return a bound method, with self being this object
|
||||
dest[0] = member;
|
||||
|
@ -840,6 +840,9 @@ void mp_load_method_maybe(mp_obj_t base, qstr attr, mp_obj_t *dest) {
|
||||
// return a bound method, with self being the type of this object
|
||||
dest[0] = ((mp_obj_static_class_method_t*)elem->value)->fun;
|
||||
dest[1] = mp_obj_get_type(base);
|
||||
} else if (MP_OBJ_IS_TYPE(elem->value, &mp_type_type)) {
|
||||
// Don't try to bind types
|
||||
dest[0] = elem->value;
|
||||
} else if (mp_obj_is_callable(elem->value)) {
|
||||
// return a bound method, with self being this object
|
||||
dest[0] = elem->value;
|
||||
|
44
tests/basics/class_store_class.py
Normal file
44
tests/basics/class_store_class.py
Normal file
@ -0,0 +1,44 @@
|
||||
# Inspired by urlparse.py from CPython 3.3 stdlib
|
||||
# There was a bug in MicroPython that under some conditions class stored
|
||||
# in instance attribute later was returned "bound" as if it was a method,
|
||||
# which caused class constructor to receive extra argument.
|
||||
from collections import namedtuple
|
||||
|
||||
_DefragResultBase = namedtuple('DefragResult', 'foo bar')
|
||||
|
||||
class _ResultMixinStr(object):
|
||||
def encode(self):
|
||||
return self._encoded_counterpart(*(x.encode() for x in self))
|
||||
|
||||
class _ResultMixinBytes(object):
|
||||
def decode(self):
|
||||
return self._decoded_counterpart(*(x.decode() for x in self))
|
||||
|
||||
class DefragResult(_DefragResultBase, _ResultMixinStr):
|
||||
pass
|
||||
|
||||
class DefragResultBytes(_DefragResultBase, _ResultMixinBytes):
|
||||
pass
|
||||
|
||||
|
||||
DefragResult._encoded_counterpart = DefragResultBytes
|
||||
DefragResultBytes._decoded_counterpart = DefragResult
|
||||
|
||||
# Due to differences in type and native subclass printing,
|
||||
# the best thing we can do here is to just test that no exceptions
|
||||
# happen
|
||||
|
||||
#print(DefragResult, DefragResult._encoded_counterpart)
|
||||
#print(DefragResultBytes, DefragResultBytes._decoded_counterpart)
|
||||
|
||||
o1 = DefragResult("a", "b")
|
||||
#print(o1, type(o1))
|
||||
o2 = DefragResultBytes("a", "b")
|
||||
#print(o2, type(o2))
|
||||
|
||||
#print(o1._encoded_counterpart)
|
||||
_o1 = o1.encode()
|
||||
print(_o1[0], _o1[1])
|
||||
#print(_o1, type(_o1))
|
||||
|
||||
print("All's ok")
|
Loading…
Reference in New Issue
Block a user