Skip to content

Calling PyDateTime_IMPORT can lead to an unhandled exception #81

@ngoldbaum

Description

@ngoldbaum

The PyDateTime_IMPORT macro doesn't do error checking and isn't documented to return anything, so I think to fix this there would need to be a new function or macro that can fail that people can migrate too.

c.f. python/cpython#122184 (comment)

The PyDateTime_IMPORT macro is defined like this:

#define PyDateTime_IMPORT \
    PyDateTimeAPI = (PyDateTime_CAPI *)PyCapsule_Import(PyDateTime_CAPSULE_NAME, 0)

This is problematic because PyCapsule_Import can fail. And indeed if I create a C extension with the following content:

Details
#include "Python.h"
#include "datetime.h"

PyModuleDef test_module = {
    .m_base=PyModuleDef_HEAD_INIT,
    .m_name="test_datetimebug",
    .m_doc=NULL,
    .m_size=-1,
    .m_methods=NULL,
    .m_slots=NULL,
    .m_traverse=NULL,
    .m_clear=NULL,
    .m_free=NULL
};


PyMODINIT_FUNC
PyInit_test_datetime(void)
{
  PyDateTime_IMPORT;
  return PyModule_Create(&test_module);
}

build it with the following meson.build:

project(
  'test_datetime',
  'c',
)

py_mod = import('python')
py = py_mod.find_installation()

srcs = [
  'test_datetime/test.c'
]

py.extension_module(
  'test_datetime',
  srcs,
  install: true,
  subdir: 'test_datetime',
)

and pyproject.toml:

[build-system]
requires = [
    "meson>=0.63.0",
    "meson-python",
]
build-backend = "mesonpy"

[project]
name = "test_datetime"
requires-python = ">=3.9.0"
version = "0.0.1"%

and then if I put a file named datetime.py somewhere in my import path (e.g. next to the C extension), I get the following error about an unhandled exception:

$ touch datetime.py
$ python
Python 3.13.0 experimental free-threading build (main, Oct 10 2024, 10:28:54) [Clang 16.0.0 (clang-1600.0.26.3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import test_datetime
AttributeError: module 'datetime' has no attribute 'datetime_CAPI' (consider renaming '/Users/goldbaum/Documents/test-datetime/build/datetime.py' since it has the same name as the standard library module named 'datetime' and the import system gives it precedence)

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<python-input-0>", line 1, in <module>
    import test_datetime
SystemError: initialization of test_datetime raised unreported exception

It looks like the same trick doesn't work on CPython itself if I create a datetime.py file and do import zoneinfo, it's only problematic for extensions.

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