Classvars (#455)

* Support specialized ClassVars, e. g. ClassVar[int] now works in a model, fix #435

* Use apostrophes and pass the test also on python 3.6, where ClassVar[int] is a ClassVar, not a _GenericAlias. Note that the == operator gives False in this case, so we must really compare the classes directly.

* Another attempt at the ClassVar check.

* Ran make format.

* Make mypy happy.

* add HISTORY
This commit is contained in:
Samuel Colvin
2019-04-03 11:58:28 +01:00
committed by GitHub
parent 085fc84818
commit bbbc8987a8
4 changed files with 13 additions and 4 deletions
+1
View File
@@ -9,6 +9,7 @@ v0.23 (unreleased)
* improve README.rst to include essential information about the package, #446 by @pilosus
* ``IntEnum`` support, #444 by @potykion
* fix ``ForwardRef`` collection bug, #450 by @tigerwings
* Support specialized ``ClassVars``, #455 by @tyrylu
v0.22 (2019-03-29)
....................
+2 -2
View File
@@ -11,7 +11,6 @@ from typing import (
TYPE_CHECKING,
Any,
Callable,
ClassVar,
Dict,
Generator,
List,
@@ -38,6 +37,7 @@ from .utils import (
AnyType,
ForwardRef,
change_exception,
is_classvar,
resolve_annotations,
truncate,
validate_field_name,
@@ -167,7 +167,7 @@ class MetaModel(ABCMeta):
class_vars = set()
# annotation only fields need to come first in fields
for ann_name, ann_type in annotations.items():
if ann_type == ClassVar:
if is_classvar(ann_type):
class_vars.add(ann_name)
elif not ann_name.startswith('_') and ann_name not in namespace:
validate_field_name(bases, ann_name)
+9 -1
View File
@@ -7,7 +7,7 @@ from functools import lru_cache
from importlib import import_module
from textwrap import dedent
from typing import _eval_type # type: ignore
from typing import TYPE_CHECKING, Any, Dict, Generator, List, Optional, Pattern, Tuple, Type, Union
from typing import TYPE_CHECKING, Any, ClassVar, Dict, Generator, List, Optional, Pattern, Tuple, Type, Union
from . import errors
@@ -268,3 +268,11 @@ def resolve_annotations(raw_annotations: Dict[str, AnyType], module_name: Option
def is_callable_type(type_: AnyType) -> bool:
return type_ is Callable or getattr(type_, '__origin__', None) is Callable
def _check_classvar(v: AnyType) -> bool:
return type(v) == type(ClassVar) and (sys.version_info < (3, 7) or getattr(v, '_name', None) == 'ClassVar')
def is_classvar(ann_type: AnyType) -> bool:
return _check_classvar(ann_type) or _check_classvar(getattr(ann_type, '__origin__', None))
+1 -1
View File
@@ -516,7 +516,7 @@ def test_value_field_name_shadows_attribute():
def test_class_var():
class MyModel(BaseModel):
a: ClassVar
b: ClassVar = 1
b: ClassVar[int] = 1
c: int = 2
assert list(MyModel.__fields__.keys()) == ['c']