Skip to content

__annotate__ Functions don't actually need to be functions#141388

@dr-carlos

Description

@dr-carlos

Bug report

Bug description:

According to the Python docs, annotate functions need to be actual functions. However, the C code doesn't enforce this, it enforces (using PyCallable_Check()) that the annotate 'function' is any callable:

staticint
function___annotate___set_impl(PyFunctionObject*self, PyObject*value)
/*[clinic end generated code: output=05b7dfc07ada66cd input=eb6225e358d97448]*/
{
if (value==NULL){
PyErr_SetString(PyExc_TypeError,
"__annotate__ cannot be deleted");
return-1;
}
if (Py_IsNone(value)){
Py_XSETREF(self->func_annotate, value);
return0;
}
elseif (PyCallable_Check(value)){
Py_XSETREF(self->func_annotate, Py_XNewRef(value));
Py_CLEAR(self->func_annotations);
return0;
}
else{
PyErr_SetString(PyExc_TypeError,
"__annotate__ must be callable or None");
return-1;
}
}

This initially seems fine, but leads to some weird bugs.

classC: def__call__(self, format, /): ifformat>2: raiseNotImplementedErrorreturn{'x': int} deff(x): ... f.__annotate__=C() fromannotationlibimportget_annotations, Formatget_annotations(f, format=Format.STRING) # AttributeError: 'C' object has no attribute '__closure__' ...

And similar for get_annotations(f, format=Format.FORWARDREF), trying to find the annotation function's __builtins__, which only exists on functions (not arbitrary callables).

I'm happy to make a PR to replace the PyCallable_Check() with PyFunction_Check() in the relevant C code for setting __annotate__, but I guess this might be a breaking change? I'm not sure, so I thought I'd check first before making it. The other option would be checking for the presence of __closure__/__builtins__/etc. before accessing them in annotationlib.

CPython versions tested on:

CPython main branch

Operating systems tested on:

Linux

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.14bugs and security fixes3.15new features, bugs and security fixesinterpreter-core(Objects, Python, Grammar, and Parser dirs)topic-typingtype-bugAn unexpected behavior, bug, or error

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions