Skip to content

Commit d724355

Browse files
committed
Use __class_getitem__ instead of metaclass
1 parent 4b9ba9e commit d724355

File tree

3 files changed

+40
-42
lines changed

3 files changed

+40
-42
lines changed

pydantic_collections/_v1.py

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from pydantic.fields import ModelField, Undefined
99

1010
# noinspection PyProtectedMember
11-
from pydantic.main import ModelMetaclass, Extra
11+
from pydantic.main import Extra
1212

1313

1414
class CollectionModelConfig(BaseConfig):
@@ -32,9 +32,22 @@ def inner(*args, **kwargs):
3232
return inner
3333

3434

35-
class BaseCollectionModelMeta(ModelMetaclass):
35+
TElement = TypeVar('TElement')
36+
37+
38+
class BaseCollectionModel(BaseModel, MutableSequence[TElement]):
39+
if TYPE_CHECKING: # pragma: no cover
40+
__el_field__: ModelField
41+
__config__: Type[CollectionModelConfig]
42+
__root__: List[TElement]
43+
44+
class Config(CollectionModelConfig):
45+
extra = Extra.forbid
46+
validate_assignment = True
47+
validate_assignment_strict = True
48+
3649
@tp_cache
37-
def __getitem__(cls: Type['BaseCollectionModel'], el_type):
50+
def __class_getitem__(cls, el_type):
3851
if not issubclass(cls, BaseCollectionModel):
3952
raise TypeError('{!r} is not a BaseCollectionModel'.format(cls)) # pragma: no cover
4053

@@ -54,21 +67,6 @@ def __getitem__(cls: Type['BaseCollectionModel'], el_type):
5467
},
5568
)
5669

57-
58-
T = TypeVar('T')
59-
60-
61-
class BaseCollectionModel(BaseModel, MutableSequence[T], metaclass=BaseCollectionModelMeta):
62-
if TYPE_CHECKING: # pragma: no cover
63-
__el_field__: ModelField
64-
__config__: Type[CollectionModelConfig]
65-
__root__: List[T]
66-
67-
class Config(CollectionModelConfig):
68-
extra = Extra.forbid
69-
validate_assignment = True
70-
validate_assignment_strict = True
71-
7270
def __init__(self, data: list = None, **kwargs):
7371
__root__ = kwargs.get('__root__')
7472
if __root__ is None:
@@ -138,7 +136,7 @@ def __setitem__(self, index, value):
138136
def __delitem__(self, index):
139137
del self.__root__[index]
140138

141-
def __iter__(self) -> List[T]:
139+
def __iter__(self) -> List[TElement]:
142140
yield from self.__root__
143141

144142
def __repr__(self):
@@ -167,7 +165,7 @@ def dict(
167165
exclude_defaults: bool = False,
168166
exclude_none: bool = False,
169167
**kwargs,
170-
) -> List[T]:
168+
) -> List[TElement]:
171169
data = super().dict(
172170
by_alias=by_alias,
173171
skip_defaults=skip_defaults,

pydantic_collections/_v2.py

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
1-
import collections.abc
21
import functools
32
import types
43
from dataclasses import dataclass
54
from typing import (
6-
Type,
75
List,
86
TYPE_CHECKING,
97
Any,
108
Tuple,
119
Union,
1210
Dict,
11+
TypeVar,
12+
MutableSequence,
1313
)
1414

15-
from pydantic import BaseModel, RootModel, TypeAdapter, ConfigDict, ValidationError
15+
from pydantic import RootModel, TypeAdapter, ConfigDict, ValidationError
1616
from pydantic_core import PydanticUndefined, ErrorDetails
1717
from typing_extensions import get_origin, get_args
1818

@@ -65,9 +65,21 @@ class Element:
6565
adapter: TypeAdapter
6666

6767

68-
class BaseCollectionModelMeta(BaseModel.__class__):
68+
TElement = TypeVar("TElement")
69+
70+
71+
class BaseCollectionModel(MutableSequence[TElement], RootModel[List[TElement]]):
72+
if TYPE_CHECKING: # pragma: no cover
73+
__element__: Element
74+
75+
# noinspection Pydantic
76+
model_config = CollectionModelConfig(
77+
validate_assignment=True,
78+
validate_assignment_strict=True,
79+
)
80+
6981
@tp_cache
70-
def __getitem__(cls: Type['BaseCollectionModel'], el_type):
82+
def __class_getitem__(cls, el_type):
7183
if not issubclass(cls, BaseCollectionModel):
7284
raise TypeError('{!r} is not a BaseCollectionModel'.format(cls)) # pragma: no cover
7385

@@ -81,20 +93,6 @@ def __getitem__(cls: Type['BaseCollectionModel'], el_type):
8193
},
8294
)
8395

84-
85-
class BaseCollectionModel(
86-
RootModel,
87-
collections.abc.MutableSequence,
88-
metaclass=BaseCollectionModelMeta,
89-
):
90-
if TYPE_CHECKING: # pragma: no cover
91-
__element__: Element
92-
93-
model_config = CollectionModelConfig(
94-
validate_assignment=True,
95-
validate_assignment_strict=True,
96-
)
97-
9896
def __init__(self, data: list = None, root=PydanticUndefined, **kwargs):
9997
if root is PydanticUndefined:
10098
if data is None:

requirements-dev.txt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# pydantic>=1.8.2,<2.0
22
typing_extensions>=4.7.1
3-
flake8==3.9.1
4-
pytest==7.0.1
5-
pytest-cov==3.0.0
3+
flake8>=3.9.1
4+
pytest==7.0.1; python_version < "3.8"
5+
pytest-cov==3.0.0; python_version < "3.8"
6+
pytest==8.0.2; python_version >= "3.8"
7+
pytest-cov==4.1.0; python_version >= "3.8"

0 commit comments

Comments
 (0)