Support `from typing import ClassVar` (#367)
* Support `from typing import ClassVar` Also updated the docstring to reflect why exactly we're doing what we're doing. The previous comment was incorrect (`typing` is already imported in applications using annotations). I added `t.ClassVar` as well which is the only third alternative import I found in use for typing-related classes. Fixes #361 * Tests, docstrings, et al.
This commit is contained in:
parent
57817b2c0e
commit
7cb8c82762
|
@ -23,6 +23,8 @@ _obj_setattr = object.__setattr__
|
|||
_init_converter_pat = "__attr_converter_{}"
|
||||
_init_factory_pat = "__attr_factory_{}"
|
||||
_tuple_property_pat = " {attr_name} = property(itemgetter({index}))"
|
||||
_classvar_prefixes = ("typing.ClassVar", "t.ClassVar", "ClassVar")
|
||||
|
||||
_empty_metadata_singleton = metadata_proxy({})
|
||||
|
||||
|
||||
|
@ -232,10 +234,11 @@ def _is_class_var(annot):
|
|||
"""
|
||||
Check whether *annot* is a typing.ClassVar.
|
||||
|
||||
The implementation is gross but importing `typing` is slow and there are
|
||||
discussions to remove it from the stdlib alltogether.
|
||||
The string comparison hack is used to avoid evaluating all string
|
||||
annotations which would put attrs-based classes at a performance
|
||||
disadvantage compared to plain old classes.
|
||||
"""
|
||||
return str(annot).startswith("typing.ClassVar")
|
||||
return str(annot).startswith(_classvar_prefixes)
|
||||
|
||||
|
||||
def _get_annotations(cls):
|
||||
|
|
|
@ -11,6 +11,7 @@ import pytest
|
|||
|
||||
import attr
|
||||
|
||||
from attr._make import _classvar_prefixes
|
||||
from attr.exceptions import UnannotatedAttributeError
|
||||
|
||||
|
||||
|
@ -204,13 +205,14 @@ class TestAnnotations:
|
|||
assert A.__init__.__annotations__ == {'return': None}
|
||||
|
||||
@pytest.mark.parametrize("slots", [True, False])
|
||||
def test_annotations_strings(self, slots):
|
||||
@pytest.mark.parametrize("classvar", _classvar_prefixes)
|
||||
def test_annotations_strings(self, slots, classvar):
|
||||
"""
|
||||
String annotations are passed into __init__ as is.
|
||||
"""
|
||||
@attr.s(auto_attribs=True, slots=slots)
|
||||
class C:
|
||||
cls_var: 'typing.ClassVar[int]' = 23
|
||||
cls_var: classvar + '[int]' = 23
|
||||
a: 'int'
|
||||
x: 'typing.List[int]' = attr.Factory(list)
|
||||
y: 'int' = 2
|
||||
|
|
Loading…
Reference in New Issue