make_class(): Add "__annotations_" to generated class (#1285)

* make_class(): Add "__annotations_" to generated class

Fixes: #1271

* Fix PR#

* Flip

---------

Co-authored-by: Hynek Schlawack <hs@ox.cx>
This commit is contained in:
Stefan Scherfke 2024-07-13 12:52:46 +02:00 committed by GitHub
parent c83de6ae90
commit edcaf04a4d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 35 additions and 1 deletions

View File

@ -0,0 +1 @@
`attrs.make_class()` now populates the `__annotations__` dict of the generated class, so that `attrs.resolve_types()` can resolve them.

View File

@ -3056,7 +3056,12 @@ def make_class(
True,
)
return _attrs(these=cls_dict, **attributes_arguments)(type_)
cls = _attrs(these=cls_dict, **attributes_arguments)(type_)
# Only add type annotations now or "_attrs()" will complain:
cls.__annotations__ = {
k: v.type for k, v in cls_dict.items() if v.type is not None
}
return cls
# These are required by within this module so we define them here and merely

View File

@ -1164,6 +1164,34 @@ class TestMakeClass:
attr.make_class("test", {"id": attr.ib(type=str)}, (MyParent[int],))
def test_annotations(self):
"""
make_class fills the __annotations__ dict for attributes with a known
type.
"""
a = attr.ib(type=bool)
b = attr.ib(
type=None
) # Won't be added to ann. b/c of unfavorable default
c = attr.ib()
C = attr.make_class("C", {"a": a, "b": b, "c": c})
C = attr.resolve_types(C)
assert {"a": bool} == C.__annotations__
def test_annotations_resolve(self):
"""
resolve_types() resolves the annotations added by make_class().
"""
a = attr.ib(type="bool")
C = attr.make_class("C", {"a": a})
C = attr.resolve_types(C)
assert attr.fields(C).a.type is bool
assert {"a": "bool"} == C.__annotations__
class TestFields:
"""