add support for _meta.get_field() typechecking

This commit is contained in:
Maxim Kurnikov
2019-07-19 16:27:13 +03:00
parent 5bb1bc250d
commit fc9843bea6
10 changed files with 124 additions and 27 deletions

View File

@@ -1,13 +1,13 @@
from collections import OrderedDict
from datetime import date
from io import BufferedReader, StringIO, TextIOWrapper
from typing import Any, Dict, Iterator, List, Optional, Tuple, Type, Union
from typing import Any, Dict, Iterable, List, Mapping, Optional, Type, Union
from uuid import UUID
from django.core.management.base import OutputWrapper
from django.db.models.base import Model
from django.db.models.fields.related import ForeignKey, ManyToManyField
from django.db.models.query import QuerySet
from django.db.models.fields import Field
class SerializerDoesNotExist(KeyError): ...
class SerializationError(Exception): ...
@@ -43,7 +43,7 @@ class Serializer:
first: bool = ...
def serialize(
self,
queryset: Union[Iterator[Any], List[Model], QuerySet],
queryset: Iterable[Model],
*,
stream: Optional[Any] = ...,
fields: Optional[Any] = ...,
@@ -52,7 +52,7 @@ class Serializer:
progress_output: Optional[Any] = ...,
object_count: int = ...,
**options: Any
) -> Optional[Union[List[OrderedDict], bytes, str]]: ...
) -> Any: ...
def start_serialization(self) -> None: ...
def end_serialization(self) -> None: ...
def start_object(self, obj: Any) -> None: ...
@@ -72,13 +72,16 @@ class Deserializer:
class DeserializedObject:
object: Any = ...
m2m_data: Dict[str, List[int]] = ...
def __init__(self, obj: Model, m2m_data: Optional[Dict[str, List[int]]] = ...) -> None: ...
deferred_fields: Mapping[Field, Any]
def __init__(
self,
obj: Model,
m2m_data: Optional[Dict[str, List[int]]] = ...,
deferred_fields: Optional[Mapping[Field, Any]] = ...,
) -> None: ...
def save(self, save_m2m: bool = ..., using: Optional[str] = ..., **kwargs: Any) -> None: ...
def save_deferred_fields(self, using: Optional[str] = ...) -> None: ...
def build_instance(Model: Type[Model], data: Dict[str, Optional[Union[date, int, str, UUID]]], db: str) -> Model: ...
def deserialize_m2m_values(
field: ManyToManyField, field_value: Union[List[List[str]], List[int]], using: str
) -> List[int]: ...
def deserialize_fk_value(
field: ForeignKey, field_value: Optional[Union[List[str], Tuple[str], int, str]], using: str
) -> Optional[Union[int, str, UUID]]: ...
def deserialize_m2m_values(field: ManyToManyField, field_value: Any, using: str) -> List[Any]: ...
def deserialize_fk_value(field: ForeignKey, field_value: Any, using: str) -> Any: ...

View File

@@ -1,4 +1,4 @@
from typing import Any, Dict, List, Optional, Sequence, Set, Tuple, TypeVar, Union, ClassVar
from typing import Any, Dict, List, Optional, Sequence, Set, Tuple, TypeVar, Union, ClassVar, Type
from django.db.models.manager import Manager
@@ -6,16 +6,16 @@ from django.core.checks.messages import CheckMessage
from django.db.models.options import Options
class ModelBase(type): ...
_Self = TypeVar("_Self", bound="Model")
class ModelBase(type): ...
class Model(metaclass=ModelBase):
class DoesNotExist(Exception): ...
class MultipleObjectsReturned(Exception): ...
class Meta: ...
_meta: Options
_default_manager: Manager[Model]
_meta: Options[Any]
pk: Any = ...
def __init__(self: _Self, *args, **kwargs) -> None: ...
def delete(self, using: Any = ..., keep_parents: bool = ...) -> Tuple[int, Dict[str, int]]: ...

View File

@@ -39,12 +39,14 @@ class Field(RegisterLookupMixin, Generic[_ST, _GT]):
max_length: Optional[int]
model: Type[Model]
name: str
verbose_name: str
blank: bool = ...
null: bool = ...
editable: bool = ...
choices: Optional[_FieldChoices] = ...
db_column: Optional[str]
column: str
error_messages: _ErrorMessagesToOverride
def __init__(
self,
verbose_name: Optional[Union[str, bytes]] = ...,
@@ -78,6 +80,7 @@ class Field(RegisterLookupMixin, Generic[_ST, _GT]):
def get_prep_value(self, value: Any) -> Any: ...
def get_internal_type(self) -> str: ...
def formfield(self, **kwargs) -> FormField: ...
def save_form_data(self, instance: Model, data: Any) -> None: ...
def contribute_to_class(self, cls: Type[Model], name: str, private_only: bool = ...) -> None: ...
def to_python(self, value: Any) -> Any: ...
def clean(self, value: Any, model_instance: Optional[Model]) -> Any: ...
@@ -91,6 +94,8 @@ class Field(RegisterLookupMixin, Generic[_ST, _GT]):
def has_default(self) -> bool: ...
def get_default(self) -> Any: ...
def check(self, **kwargs: Any) -> List[checks.Error]: ...
@property
def validators(self) -> List[_ValidatorCallable]: ...
class IntegerField(Field[_ST, _GT]):
_pyi_private_set_type: Union[float, int, str, Combinable]

View File

@@ -1,5 +1,5 @@
import collections
from typing import Any, Callable, Dict, Iterator, List, Optional, Set, Tuple, Type, Union
from typing import Any, Callable, Dict, Iterator, List, Optional, Set, Tuple, Type, Union, TypeVar, Generic
from django.apps.config import AppConfig
from django.apps.registry import Apps
@@ -29,7 +29,9 @@ def make_immutable_fields_list(
name: str, data: Union[Iterator[Any], List[Union[ArrayField, CIText]], List[Union[Field, FieldCacheMixin]]]
) -> ImmutableList: ...
class Options:
_M = TypeVar('_M', bound=Model)
class Options(Generic[_M]):
base_manager: Manager
concrete_fields: ImmutableList
default_manager: Manager

View File

@@ -78,7 +78,7 @@ class QuerySet(Generic[_T, _Row], Collection[_Row], Sized):
def iterator(self, chunk_size: int = ...) -> Iterator[_Row]: ...
def aggregate(self, *args: Any, **kwargs: Any) -> Dict[str, Any]: ...
def get(self, *args: Any, **kwargs: Any) -> _Row: ...
def create(self, **kwargs: Any) -> _T: ...
def create(self, *args: Any, **kwargs: Any) -> _T: ...
def bulk_create(
self, objs: Iterable[Model], batch_size: Optional[int] = ..., ignore_conflicts: bool = ...
) -> List[_T]: ...