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

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

Comments

@ffelixg
Copy link
Contributor

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

Linked PRs

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

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

@rruuaanng
Copy link
Contributor

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
Contributor

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

@rruuaanng
Copy link
Contributor

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
Contributor

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
Contributor 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.

@vstinner
Copy link
Member

PyStructSequence_InitType() and PyStructSequence_InitType2() are legacy APIs for static types, you should use PyStructSequence_NewType() for heap types.

@vstinner
Copy link
Member

vstinner commented Sep 23, 2024

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

Does someone want to propose a PR for that? The function is documented in Doc/c-api/tuple.rst.

@ffelixg
Copy link
Contributor Author

ffelixg commented Sep 23, 2024

Does someone want to propose a PR for that? The function is documented in Doc/c-api/tuple.rst.

The rules seem to be similar to this, so I took that as a base, removed the parts that deal with types that don't belong to a module and mentioned that a dot must be included.

@vstinner
Copy link
Member

vstinner commented Oct 7, 2024

@ffelixg adjusted the doc in change 3287c83. I close the issue.

@vstinner vstinner closed this as completed Oct 7, 2024
vstinner pushed a commit that referenced this issue Oct 7, 2024
…124335) (#125056)

gh-124182: Explain naming rules for struct sequence types (GH-124335)
(cherry picked from commit 3287c83)

Co-authored-by: ffelixg <[email protected]>
vstinner pushed a commit that referenced this issue Oct 7, 2024
…124335) (#125057)

gh-124182: Explain naming rules for struct sequence types (GH-124335)
(cherry picked from commit 3287c83)

Co-authored-by: ffelixg <[email protected]>
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