backports.datetime_fromisoformat icon indicating copy to clipboard operation
backports.datetime_fromisoformat copied to clipboard

use ctypes.pythonapi in flush_mro_cache

Open ejd opened this issue 7 months ago • 0 comments

What are you trying to accomplish?

I would like to be able to use this library on Android via Chaquopy. When I tried using a "stock" build of this library on Android, my program crashed in flush_mro_cache because the value returned by c.PyDLL(None) didn't have a PyType_Modified symbol.

Here's a traceback to show where the error was raised within backports.datetime_fromisoformat:

com.chaquo.python.PyException: AttributeError: undefined symbol: PyType_Modified
    at <python>.ctypes.__getitem__(__init__.py:391)
    at <python>.ctypes.__getattr__(__init__.py:386)
    at <python>.backports.datetime_fromisoformat.flush_mro_cache(__init__.py:22)
    at <python>.backports.datetime_fromisoformat.patch_fromisoformat(__init__.py:40)

I'm using backports.datetime_fromisoformat 2.0.3 under Python 3.8.20.

I'm not entirely sure why this doesn't work on Android. I'm assuming it's related to how Python is configured/built for Android. The copy of Python that the Chaquopy Gradle plugin bundles with my library is built and distributed by the Chaquopy project. If you feel this PR is misdirected and reject it, my next stop will be to ask Chaquopy why this project's flush_mro_cache doesn't work on Android. That said, I think there's value in eliminating platform-specific code paths from backports.datetime_fromisoformat.

What approach did you choose and why?

In the current implementation, flush_mro_cache obtains a C Python API handle by calling ctypes.PyDLL() with the appropriate arguments for a given platform. The object returned should be a handle to a the C Python API loaded from elsewhere. However, at least on Android, this handle seems to be missing a symbol for PyType_Modified.

I found that ctypes has a pythonapi. The docs introduce it as, "For accessing the C Python api directly, a ready-to-use Python shared library object is available: ctypes.pythonapi." In this PR, I replaced the use of a runtime-loaded PyDLL with ctypes.pythonapi.

What should reviewers focus on?

I believe the comment in flush_mro_cache linking to the SO post is still relevant so I left it in place.

The impact of these changes

This change eliminates the need to have platform-specific execution paths. It should work anywhere ctypes is available.

Testing

The project's test suite passed when I ran the tests locally.

ejd avatar Jul 29 '25 16:07 ejd