Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"DeprecationWarning: builtin type has no __module__ attribute" when using PyStructSequence_NewType from a module method #124182

Open
ffelixg opened this issue Sep 17, 2024 · 9 comments
Labels
topic-C-API type-bug An unexpected behavior, bug, or error

Comments

@ffelixg
Copy link

ffelixg commented Sep 17, 2024

Bug report

Bug description:

Below is an example producing the warning. This warning does not occur when the type is created in the module's init function.
When using PyStructSequence_InitType2, the resulting type gets "builtin" as the __module__ attribute and there is no deprecation warning.
It's also possible to add a field named __module__ to prevent the warning. Setting the __module__ attribute after creating the type does not help, the warning gets raised inside the PyStructSequence_NewType function.

I couldn't find anything indicating that I'm not supposed to use PyStructSequence_NewType in this way.

#include <Python.h>

// the type is usable, but we get: <string>:1: DeprecationWarning: builtin type TypeName has no __module__ attribute
// python3 -c "import c_ext; c_ext.create_type()"

static PyObject* create_type(PyObject* self) {
    PyStructSequence_Field fields[] = {
        { "FieldName", "docs" },
        { NULL, NULL },
    };
    PyStructSequence_Desc desc = {"TypeName", "docs", fields, 1};
    return (PyObject*)PyStructSequence_NewType(&desc);
}

static struct PyMethodDef methods[] = {
    {"create_type", (PyCFunction)create_type, METH_NOARGS},
    {NULL, NULL}
};

static struct PyModuleDef module = {
    PyModuleDef_HEAD_INIT, "c_ext", NULL, -1, methods
};

PyMODINIT_FUNC PyInit_c_ext(void) {
    return PyModule_Create(&module);
}

CPython versions tested on:

3.10, 3.11, 3.12, 3.13

Operating systems tested on:

Linux

@ffelixg ffelixg added the type-bug An unexpected behavior, bug, or error label Sep 17, 2024
@rruuaanng
Copy link

I'm following this issue,maybe you can awaiting message for me.

@rruuaanng
Copy link

rruuaanng commented Sep 19, 2024

I'm not totally sure if this was the original intention, but it seems like PyStructSequence_Field was meant to let users define module attributes, which in turn would help determine the name of the user-extended modules."

@rruuaanng
Copy link

If that's not how it's supposed to work, I can totally put together a PR to sort it out.

@rruuaanng
Copy link

rruuaanng commented Sep 19, 2024

The warning is triggered by r = PyDict_Contains(dict, &_Py_ID(__module__))

r = PyDict_Contains(dict, &_Py_ID(__module__));
When r == 0 and there’s no secondary reference, it raises this warning. To get rid of the warning, you could add a __module__ entry when it’s zero, but the value for that key-value pair seems uncertain and makes the rest of the logic pointless.

cpython/Objects/typeobject.c

Lines 5069 to 5092 in 4420cf4

if (r < 0) {
goto finally;
}
if (r == 0) {
s = strrchr(spec->name, '.');
if (s != NULL) {
PyObject *modname = PyUnicode_FromStringAndSize(
spec->name, (Py_ssize_t)(s - spec->name));
if (modname == NULL) {
goto finally;
}
r = PyDict_SetItem(dict, &_Py_ID(__module__), modname);
Py_DECREF(modname);
if (r != 0) {
goto finally;
}
}
else {
if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
"builtin type %.200s has no __module__ attribute",
spec->name))
goto finally;
}
}
I think this is normal behavior, and maybe I should ask a core developer about it.

@rruuaanng
Copy link

cc: @brettcannon @vstinner

@vstinner
Copy link
Member

DeprecationWarning: builtin type has no module attribute" when using PyStructSequence_NewType from a module method

It's an issue in your extension. The warning means that the type name has no module name. You should replace:

    PyStructSequence_Desc desc = {"TypeName", "docs", fields, 1};

with:

    PyStructSequence_Desc desc = {"c_ext.TypeName", "docs", fields, 1};

where c_ext is your extension name.

@rruuaanng

This comment was marked as duplicate.

@hugovk
Copy link
Member

hugovk commented Sep 19, 2024

Hi @rruuaanng, please could you try and make fewer comments where they don't add much to the discussion? For example, there's no need to quote Victor's last comment and only ping the OP - it's safe to assume they're subscribed to their own issue. Thanks.

@ffelixg
Copy link
Author

ffelixg commented Sep 19, 2024

Fair enough, thanks. I did not think that the type name was more than aesthetics. The only question that remains then is why InitType behaves differently (better?) with it defaulting to builtins (although still not including it in the type's repr).

It might also be helpful to mention that the module name must be included in the documentation for the name field.

If you think it's fine the way it is then this can be closed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic-C-API type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

No branches or pull requests

5 participants