Skip to content

[feature] Port python-ldap to PEP 630 (Isolating Extension Modules) #540

Closed as not planned
@tiran

Description

@tiran

I propose to port python-ldap to PEP 630. Actually, I have already done the work and have a working prototype. PEP 630 is an informational PEP that covers three PEPs

  • PEP 384 – Defining a Stable ABI
  • PEP 489 – Multi-phase extension module initialization
  • PEP 573 – Module State Access from C Extension Methods

Isolated C extension module will give us two major benefits:

  • Stable ABI / limited API will allow us / our users to create abi3 binary wheels. My prototype implements cp36-abi3-linux_x86_64.whl support. The wheels is compatible with all Python versions from 3.6 to 3.12, as well as future versions of Python 3 with ABI3. For example @cgohlke won't need to create Windows binaries for each Python version.
  • It makes python-ldap compatible with PEP 684 Per-Interpreter GIL and safe to use with multiple subinterpreters.

Required changes

  • Port PyTypeObject LDAP_Type to heap type.
    • Replace static PyTypeObject LDAP_Type with PyType_Slot and PyType_Spec
    • Allocate object with PyObject_GC_New and free it with PyObject_GC_UnTrack / PyObject_GC_Del
    • Add GC protocol (traverse, clear) to track the heap reference to the type
    • Initialize type with PyType_FromSpec
  • Create _ldap C extension module with multi-phase initialization
    • Export module-level functions from functions.c and ldapcontrol.c. This also gets rid of LDAPadd_methods hack, LDAPinit_functions, and LDAPinit_control
    • Define PyModuleDef_Slot to init type, constants, and pkginfo
    • Make PyModuleDef global static
    • Initialize module with PyModuleDef_Init
  • Remove static globals LDAP_Type, LDAPexception_class, and errobjects in favor of module state struct.
    • Define LDAPModState and add it to PyModuleDef
    • Add state pointer to LDAPObject. PyType_GetModuleState() is not available in Python < 3.9 and became part of the stable ABI in 3.10.
    • Change all functions to get reference to type or exceptions from module state. This change is the largest diff and requires changes to several helper functions, especially error functions like LDAPerror.
  • Replace some macros with limited API functions, e.g. PySequence_Fast_GET_ITEM() with PySequence_GetItem(). We use unsafe macros in a few places. In theory the macros are a tiny bit faster. In practice it doesn't make a difference except for lots of calls in a hot path. I don't except a performance impact.
  • Build _ldap extension module with limited API and stable ABI parameters.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions