Bug report
annotationlib.type_repr() (a public, documented helper, exported in
__all__) returns a string that names a nonexistent module None for bound
built-in methods:
>>> from annotationlib import type_repr
>>> type_repr([].append)
'None.list.append'
>>> type_repr(dict.fromkeys)
'None.dict.fromkeys'
>>> import random; type_repr(random.random)
'None.Random.random'
Bound built-in methods (and C-accelerator functions) are BuiltinFunctionType
with __module__ set to None, so f"{value.__module__}.{value.__qualname__}"
interpolates the literal None. Every other object in this family produces a
resolvable name -- len -> 'len', os.getpid -> 'posix.getpid';
this is the only one that emits a None. prefix. 'None.list.append' is
also an active hazard: a STRING-format consumer that resolves it gets
AttributeError on the literal None.
annotations_to_string() and get_annotations(obj, format=Format.STRING)
propagate it when an annotation value is such a method.
Note for completeness: this is reached when a live method object is passed to
type_repr (its documented purpose), not from natural annotation source
syntax -- def f(x: [].append) is stringified correctly via the AST path.
The defect is the public-API output of type_repr itself.
Fix
Return __qualname__ ('list.append') when __module__ is None,
exactly as already done for the "builtins" module. repr() is not a
usable fallback: it embeds a non-deterministic heap address and is not
re-parseable.
Linked PRs
Bug report
annotationlib.type_repr()(a public, documented helper, exported in__all__) returns a string that names a nonexistent moduleNonefor boundbuilt-in methods:
Bound built-in methods (and C-accelerator functions) are
BuiltinFunctionTypewith
__module__set toNone, sof"{value.__module__}.{value.__qualname__}"interpolates the literal
None. Every other object in this family produces aresolvable name --
len->'len',os.getpid->'posix.getpid';this is the only one that emits a
None.prefix.'None.list.append'isalso an active hazard: a STRING-format consumer that resolves it gets
AttributeErroron the literalNone.annotations_to_string()andget_annotations(obj, format=Format.STRING)propagate it when an annotation value is such a method.
Note for completeness: this is reached when a live method object is passed to
type_repr(its documented purpose), not from natural annotation sourcesyntax --
def f(x: [].append)is stringified correctly via the AST path.The defect is the public-API output of
type_repritself.Fix
Return
__qualname__('list.append') when__module__isNone,exactly as already done for the
"builtins"module.repr()is not ausable fallback: it embeds a non-deterministic heap address and is not
re-parseable.
Linked PRs