chaquo / chaquopy

Chaquopy: the Python SDK for Android
https://chaquo.com/chaquopy/
MIT License
805 stars 132 forks source link

Remove requirement for dynamic_proxy to come first in the bases #659

Open mhsmith opened 2 years ago

mhsmith commented 2 years ago

I can't remember why I added this restriction: it might have had something to do with Python 2 metaclass compatibility. Of course, if the dynamic_proxy base doesn't come first, the user will have to make sure that its __init__ is still called, but that's a standard multiple inheritance issue, and it's already documented.

If possible, we might as well remove the restriction from static_proxy as well.

mhsmith commented 2 years ago

It should also be possible to further subclass a dynamic_proxy class, creating a new Proxy class on the Java side. At least we should support simple cases like Toga's MainWindow (https://github.com/beeware/toga/pull/1590), which apparently works with Rubicon but not with Chaquopy 12.0.1:

09-22 20:35:12.644  6622  6622 E AndroidRuntime: Caused by: com.chaquo.python.PyException: TypeError: dynamic_proxy must be used first in class bases
09-22 20:35:12.644  6622  6622 E AndroidRuntime:        at <python>.java.chaquopy.ProxyClass.__new__(proxy.pxi:13)
09-22 20:35:12.644  6622  6622 E AndroidRuntime:        at <python>.toga_android.app.<module>(app.py:14)
09-22 20:35:12.644  6622  6622 E AndroidRuntime:        at <python>.java.chaquopy.import_override(import.pxi:26)
09-22 20:35:12.644  6622  6622 E AndroidRuntime:        at <python>.toga_android.factory.<module>(factory.py:1)
09-22 20:35:12.644  6622  6622 E AndroidRuntime:        at <python>.java.chaquopy.import_override(import.pxi:26)
09-22 20:35:12.644  6622  6622 E AndroidRuntime:        at <python>.toga.platform.get_platform_factory(platform.py:32)
09-22 20:35:12.644  6622  6622 E AndroidRuntime:        at <python>.toga.app.__init__(app.py:278)
09-22 20:35:12.644  6622  6622 E AndroidRuntime:        at <python>.helloworld.app.main(app.py:64)
09-22 20:35:12.644  6622  6622 E AndroidRuntime:        at <python>.__main__.<module>(__main__.py:4)
09-22 20:35:12.644  6622  6622 E AndroidRuntime:        at <python>.runpy._run_code(runpy.py:87)
09-22 20:35:12.644  6622  6622 E AndroidRuntime:        at <python>.runpy._run_module_code(runpy.py:97)
09-22 20:35:12.644  6622  6622 E AndroidRuntime:        at <python>.runpy.run_module(runpy.py:207)
09-22 20:35:12.644  6622  6622 E AndroidRuntime:        at <python>.chaquopy_java.call(chaquopy_java.pyx:379)
09-22 20:35:12.644  6622  6622 E AndroidRuntime:        at <python>.chaquopy_java.Java_com_chaquo_python_PyObject_callAttrThrowsNative(chaquopy_java.pyx:351)
09-22 20:35:12.644  6622  6622 E AndroidRuntime:        at com.chaquo.python.PyObject.callAttrThrowsNative(Native Method)
09-22 20:35:12.644  6622  6622 E AndroidRuntime:        at com.chaquo.python.PyObject.callAttrThrows(PyObject.java:232)
09-22 20:35:12.644  6622  6622 E AndroidRuntime:        at com.chaquo.python.PyObject.callAttr(PyObject.java:221)
09-22 20:35:12.644  6622  6622 E AndroidRuntime:        at org.beeware.android.MainActivity.onCreate(MainActivity.java:64)

The cleanest way of solving all of this may be to just deprecate the dynamic_proxy syntax altogether, and allow interfaces to be subclassed using normal Python syntax.

But in any case, we should still update the documentation to be clear about exactly what further subclassing is possible for both dynamic and static proxy.

mhsmith commented 1 year ago

This was easy to work around in Toga (https://github.com/beeware/toga/pull/1590), so it's not urgent.