Inheritance for native types is not supported
Default load_attr implementation (as used for all native types) doesn't take type inheritance (->bases_tuple) into account. I'm working on OrderedDict implementation, and it inherits most of its methods from dict, but adds few (well, 1) new method. Of course, this new method can be ignored, and old trick of putting the same .locals_dict to both types can be used. But I wanted to look into making truly inheritable methods, which requires setting custom .load_attr type method. And we already have implementation of this method which takes inheritance into account - for user classes/instances. But trying to use it, it assumes that object whose attr is being looked up is instance, so making it work with native objects means adding even more conditions to existing bunch of those (and which are already pretty mind-boggling). Another alternative is to make clean, "optimized" inheritance-friendly .load_attr for native types, but that means code duplication (and refactoring of existing code paths, factoring out functions, which means more stack usage, etc.)
Any thoughts?
Lookup of operator builtins can fail with multiple inheritance
When looking up a method that implements an operator (such as __int__() or __lshift__()) on an object who's class uses multiple inheritance, and an earlier base classes is a native type that does not implement that operator, then an implementation of the required method will not be found in a later base class that does implement it.
Take for instance the following example:
class Foo:
def __int__(self):
return 123
class Bar(Foo, list):
pass
class Baz(list, Foo):
pass
print(int(Bar([])))
print(int(Baz([])))
On C Python this prints the expected:
123
123
On Micropython the second call raises a TypeError:
123
Traceback (most recent call last):
File "<stdin>", line 12, in <module>
TypeError: can't convert list to int
This is because mp_obj_class_lookup() checks to see if a native type has the necessary unary_op or binary_op function pointer but does not check to see if the specific operator code is implemented. If a native type is found that has the required operator function pointer the search for an implementation stops there, even if it doesn't implement the desired operator code, preventing a later, usable implementation from being found.