various fixes

This commit is contained in:
Maxim Kurnikov
2019-07-20 20:28:43 +03:00
parent fee4aad3d0
commit 248504c25a
22 changed files with 204 additions and 299 deletions

View File

@@ -54,29 +54,16 @@ class GenericForeignKey(FieldCacheMixin):
class GenericRel(ForeignObjectRel): class GenericRel(ForeignObjectRel):
field: GenericRelation field: GenericRelation
limit_choices_to: Optional[Union[Dict[str, Any], Callable[[], Any]]]
model: Type[Model]
multiple: bool
on_delete: Callable
parent_link: bool
related_name: str
related_query_name: None
symmetrical: bool
def __init__( def __init__(
self, self,
field: GenericRelation, field: GenericRelation,
to: Union[Type[Model], str], to: Union[Type[Model], str],
related_name: None = ..., related_name: Optional[str] = ...,
related_query_name: Optional[str] = ..., related_query_name: Optional[str] = ...,
limit_choices_to: Optional[Union[Dict[str, Any], Callable[[], Any]]] = ..., limit_choices_to: Optional[Union[Dict[str, Any], Callable[[], Any]]] = ...,
) -> None: ... ) -> None: ...
class GenericRelation(ForeignObject): class GenericRelation(ForeignObject):
auto_created: bool = ...
many_to_many: bool = ...
many_to_one: bool = ...
one_to_many: bool = ...
one_to_one: bool = ...
rel_class: Any = ... rel_class: Any = ...
mti_inherited: bool = ... mti_inherited: bool = ...
object_id_field_name: Any = ... object_id_field_name: Any = ...
@@ -93,23 +80,16 @@ class GenericRelation(ForeignObject):
limit_choices_to: Optional[Union[Dict[str, Any], Callable[[], Any]]] = ..., limit_choices_to: Optional[Union[Dict[str, Any], Callable[[], Any]]] = ...,
**kwargs: Any **kwargs: Any
) -> None: ... ) -> None: ...
def check(self, **kwargs: Any) -> List[Error]: ...
def resolve_related_fields(self) -> List[Tuple[PositiveIntegerField, Field]]: ... def resolve_related_fields(self) -> List[Tuple[PositiveIntegerField, Field]]: ...
def get_path_info(self, filtered_relation: Optional[FilteredRelation] = ...) -> List[PathInfo]: ... def get_path_info(self, filtered_relation: Optional[FilteredRelation] = ...) -> List[PathInfo]: ...
def get_reverse_path_info(self, filtered_relation: None = ...) -> List[PathInfo]: ... def get_reverse_path_info(self, filtered_relation: None = ...) -> List[PathInfo]: ...
def value_to_string(self, obj: Model) -> str: ... def value_to_string(self, obj: Model) -> str: ...
model: Any = ...
def set_attributes_from_rel(self) -> None: ...
def get_internal_type(self) -> str: ...
def get_content_type(self) -> ContentType: ... def get_content_type(self) -> ContentType: ...
def get_extra_restriction( def get_extra_restriction(
self, where_class: Type[WhereNode], alias: Optional[str], remote_alias: str self, where_class: Type[WhereNode], alias: Optional[str], remote_alias: str
) -> WhereNode: ... ) -> WhereNode: ...
def bulk_related_objects(self, objs: List[Model], using: str = ...) -> QuerySet: ... def bulk_related_objects(self, objs: List[Model], using: str = ...) -> QuerySet: ...
class ReverseGenericManyToOneDescriptor(ReverseManyToOneDescriptor): class ReverseGenericManyToOneDescriptor(ReverseManyToOneDescriptor): ...
field: GenericRelation
rel: GenericRel
def related_manager_cls(self): ...
def create_generic_related_manager(superclass: Any, rel: Any): ... def create_generic_related_manager(superclass: Any, rel: Any): ...

View File

@@ -1,15 +1,6 @@
from typing import Any, List, Optional from typing import Optional
from django.core.checks.messages import Error
from django.db.models.query import QuerySet
from django.db import models from django.db import models
class CurrentSiteManager(models.Manager): class CurrentSiteManager(models.Manager):
creation_counter: int
model: None
name: None
use_in_migrations: bool = ...
def __init__(self, field_name: Optional[str] = ...) -> None: ... def __init__(self, field_name: Optional[str] = ...) -> None: ...
def check(self, **kwargs: Any) -> List[Error]: ...
def get_queryset(self) -> QuerySet: ...

View File

@@ -52,7 +52,6 @@ class BaseExpression:
is_summary: bool = ... is_summary: bool = ...
filterable: bool = ... filterable: bool = ...
window_compatible: bool = ... window_compatible: bool = ...
output_field: Field
def __init__(self, output_field: Optional[_OutputField] = ...) -> None: ... def __init__(self, output_field: Optional[_OutputField] = ...) -> None: ...
def get_db_converters(self, connection: Any) -> List[Callable]: ... def get_db_converters(self, connection: Any) -> List[Callable]: ...
def get_source_expressions(self) -> List[Any]: ... def get_source_expressions(self) -> List[Any]: ...
@@ -74,6 +73,8 @@ class BaseExpression:
@property @property
def field(self) -> Field: ... def field(self) -> Field: ...
@property @property
def output_field(self) -> Field: ...
@property
def convert_value(self) -> Callable: ... def convert_value(self) -> Callable: ...
def get_lookup(self, lookup: str) -> Optional[Type[Lookup]]: ... def get_lookup(self, lookup: str) -> Optional[Type[Lookup]]: ...
def get_transform(self, name: str) -> Optional[Type[Expression]]: ... def get_transform(self, name: str) -> Optional[Type[Expression]]: ...

View File

@@ -1,13 +1,27 @@
import decimal import decimal
import uuid import uuid
from datetime import date, datetime, time, timedelta from datetime import date, datetime, time, timedelta
from typing import Any, Callable, Dict, Generic, Iterable, Optional, Tuple, Type, TypeVar, Union, Sequence, List from typing import (
Any,
Callable,
Dict,
Generic,
Iterable,
Optional,
Tuple,
Type,
TypeVar,
Union,
Sequence,
List,
overload,
)
from django.core import checks from django.core import checks
from django.db.models import Model from django.db.models import Model
from django.core.exceptions import FieldDoesNotExist as FieldDoesNotExist from django.core.exceptions import FieldDoesNotExist as FieldDoesNotExist
from django.db.models.expressions import Combinable from django.db.models.expressions import Combinable, Col
from django.db.models.query_utils import RegisterLookupMixin from django.db.models.query_utils import RegisterLookupMixin
from django.forms import Field as FormField, Widget from django.forms import Field as FormField, Widget
@@ -20,6 +34,7 @@ _FieldChoices = Iterable[Union[_Choice, _ChoiceNamedGroup]]
_ValidatorCallable = Callable[..., None] _ValidatorCallable = Callable[..., None]
_ErrorMessagesToOverride = Dict[str, Any] _ErrorMessagesToOverride = Dict[str, Any]
_T = TypeVar("_T", bound="Field")
# __set__ value type # __set__ value type
_ST = TypeVar("_ST") _ST = TypeVar("_ST")
# __get__ return type # __get__ return type
@@ -36,7 +51,7 @@ class Field(RegisterLookupMixin, Generic[_ST, _GT]):
auto_created: bool auto_created: bool
primary_key: bool primary_key: bool
remote_field: Field remote_field: Field
max_length: Optional[int] max_length: int
model: Type[Model] model: Type[Model]
name: str name: str
verbose_name: str verbose_name: str
@@ -72,6 +87,11 @@ class Field(RegisterLookupMixin, Generic[_ST, _GT]):
error_messages: Optional[_ErrorMessagesToOverride] = ..., error_messages: Optional[_ErrorMessagesToOverride] = ...,
): ... ): ...
def __set__(self, instance, value: _ST) -> None: ... def __set__(self, instance, value: _ST) -> None: ...
# class access
@overload
def __get__(self: _T, instance: None, owner) -> _T: ...
# instance access
@overload
def __get__(self, instance, owner) -> _GT: ... def __get__(self, instance, owner) -> _GT: ...
def deconstruct(self) -> Any: ... def deconstruct(self) -> Any: ...
def set_attributes_from_name(self, name: str) -> None: ... def set_attributes_from_name(self, name: str) -> None: ...
@@ -96,6 +116,10 @@ class Field(RegisterLookupMixin, Generic[_ST, _GT]):
def check(self, **kwargs: Any) -> List[checks.Error]: ... def check(self, **kwargs: Any) -> List[checks.Error]: ...
@property @property
def validators(self) -> List[_ValidatorCallable]: ... def validators(self) -> List[_ValidatorCallable]: ...
def get_col(self, alias: str, output_field: Optional[Field] = ...) -> Col: ...
@property
def cached_col(self) -> Col: ...
def value_from_object(self, obj: Model) -> _GT: ...
class IntegerField(Field[_ST, _GT]): class IntegerField(Field[_ST, _GT]):
_pyi_private_set_type: Union[float, int, str, Combinable] _pyi_private_set_type: Union[float, int, str, Combinable]

View File

@@ -1,39 +1,25 @@
from typing import ( from typing import Any, Callable, Dict, Iterable, List, Optional, Sequence, TYPE_CHECKING, Tuple, Type, TypeVar, Union
Type,
Union,
TypeVar,
Any,
Generic,
List,
Optional,
Dict,
Callable,
Tuple,
Sequence,
TYPE_CHECKING,
Iterable,
)
from uuid import UUID from uuid import UUID
from django.db import models from django.db.models.expressions import Combinable
from django.db.models import Field, Model, QuerySet
from django.db.models.fields.mixins import FieldCacheMixin from django.db.models.fields.mixins import FieldCacheMixin
from django.db.models.query_utils import PathInfo, Q
from django.db import models
from django.db.models import Field, Model
from django.db.models.fields.related_descriptors import ( from django.db.models.fields.related_descriptors import (
ReverseManyToOneDescriptor as ReverseManyToOneDescriptor,
ReverseOneToOneDescriptor as ReverseOneToOneDescriptor,
ForwardManyToOneDescriptor as ForwardManyToOneDescriptor,
ForwardOneToOneDescriptor as ForwardOneToOneDescriptor, ForwardOneToOneDescriptor as ForwardOneToOneDescriptor,
ForwardManyToOneDescriptor as ForwardManyToOneDescriptor,
ManyToManyDescriptor as ManyToManyDescriptor, ManyToManyDescriptor as ManyToManyDescriptor,
ReverseOneToOneDescriptor as ReverseOneToOneDescriptor,
ReverseManyToOneDescriptor as ReverseManyToOneDescriptor,
) )
from django.db.models.fields.reverse_related import ( from django.db.models.fields.reverse_related import (
ForeignObjectRel as ForeignObjectRel, ForeignObjectRel as ForeignObjectRel,
ManyToManyRel as ManyToManyRel,
ManyToOneRel as ManyToOneRel,
OneToOneRel as OneToOneRel, OneToOneRel as OneToOneRel,
ManyToOneRel as ManyToOneRel,
ManyToManyRel as ManyToManyRel,
) )
from django.db.models.query_utils import PathInfo, Q
from django.db.models.expressions import Combinable
if TYPE_CHECKING: if TYPE_CHECKING:
from django.db.models.manager import RelatedManager from django.db.models.manager import RelatedManager
@@ -61,14 +47,11 @@ class RelatedField(FieldCacheMixin, Field[_ST, _GT]):
many_to_one: bool = ... many_to_one: bool = ...
@property @property
def related_model(self) -> Union[Type[Model], str]: ... def related_model(self) -> Union[Type[Model], str]: ...
def check(self, **kwargs: Any) -> List[Any]: ...
opts: Any = ... opts: Any = ...
def get_forward_related_filter(self, obj: Model) -> Dict[str, Union[int, UUID]]: ... def get_forward_related_filter(self, obj: Model) -> Dict[str, Union[int, UUID]]: ...
def get_reverse_related_filter(self, obj: Model) -> Q: ... def get_reverse_related_filter(self, obj: Model) -> Q: ...
@property @property
def swappable_setting(self) -> Optional[str]: ... def swappable_setting(self) -> Optional[str]: ...
name: Any = ...
verbose_name: Any = ...
def set_attributes_from_rel(self) -> None: ... def set_attributes_from_rel(self) -> None: ...
def do_related_class(self, other: Type[Model], cls: Type[Model]) -> None: ... def do_related_class(self, other: Type[Model], cls: Type[Model]) -> None: ...
def get_limit_choices_to(self) -> Dict[str, int]: ... def get_limit_choices_to(self) -> Dict[str, int]: ...
@@ -188,7 +171,14 @@ class ManyToManyField(RelatedField[_ST, _GT]):
rel_class: Any = ... rel_class: Any = ...
description: Any = ... description: Any = ...
has_null_arg: Any = ... has_null_arg: Any = ...
swappable: Any = ... swappable: bool = ...
m2m_db_table: str = ...
m2m_column_name: str = ...
m2m_reverse_name: str = ...
m2m_field_name: str = ...
m2m_reverse_field_name: str = ...
m2m_target_field_name: str = ...
m2m_reverse_target_field_name: str = ...
def __init__( def __init__(
self, self,
to: Union[Type[_T], str], to: Union[Type[_T], str],
@@ -223,19 +213,9 @@ class ManyToManyField(RelatedField[_ST, _GT]):
validators: Iterable[_ValidatorCallable] = ..., validators: Iterable[_ValidatorCallable] = ...,
error_messages: Optional[_ErrorMessagesToOverride] = ..., error_messages: Optional[_ErrorMessagesToOverride] = ...,
) -> None: ... ) -> None: ...
def check(self, **kwargs: Any) -> List[Any]: ... def __get__(self, instance, owner) -> _GT: ... # type: ignore
def get_path_info(self, filtered_relation: None = ...) -> List[PathInfo]: ... def get_path_info(self, filtered_relation: None = ...) -> List[PathInfo]: ...
def get_reverse_path_info(self, filtered_relation: None = ...) -> List[PathInfo]: ... def get_reverse_path_info(self, filtered_relation: None = ...) -> List[PathInfo]: ...
m2m_db_table: Any = ...
m2m_column_name: Any = ...
m2m_reverse_name: Any = ...
m2m_field_name: Any = ...
m2m_reverse_field_name: Any = ...
m2m_target_field_name: Any = ...
m2m_reverse_target_field_name: Any = ...
def contribute_to_related_class(self, cls: Type[Model], related: RelatedField) -> None: ... def contribute_to_related_class(self, cls: Type[Model], related: RelatedField) -> None: ...
def set_attributes_from_rel(self) -> None: ...
def value_from_object(self, obj: Model) -> List[Model]: ...
def save_form_data(self, instance: Model, data: QuerySet) -> None: ...
def create_many_to_many_intermediary_model(field: Type[Field], klass: Type[Model]) -> Type[Model]: ... def create_many_to_many_intermediary_model(field: Type[Field], klass: Type[Model]) -> Type[Model]: ...

View File

@@ -10,13 +10,10 @@ from django.db.models.sql.where import WhereNode
from .mixins import FieldCacheMixin from .mixins import FieldCacheMixin
class ForeignObjectRel(FieldCacheMixin): class ForeignObjectRel(FieldCacheMixin):
hidden: bool
many_to_many: bool many_to_many: bool
many_to_one: bool many_to_one: bool
name: str
one_to_many: bool one_to_many: bool
one_to_one: bool one_to_one: bool
related_model: Type[Model]
auto_created: bool = ... auto_created: bool = ...
concrete: bool = ... concrete: bool = ...
editable: bool = ... editable: bool = ...
@@ -43,6 +40,12 @@ class ForeignObjectRel(FieldCacheMixin):
on_delete: Optional[Callable] = ..., on_delete: Optional[Callable] = ...,
) -> None: ... ) -> None: ...
@property @property
def hidden(self) -> bool: ...
@property
def name(self) -> str: ...
@property
def related_model(self) -> Type[Model]: ...
@property
def remote_field(self) -> RelatedField: ... def remote_field(self) -> RelatedField: ...
@property @property
def target_field(self) -> AutoField: ... def target_field(self) -> AutoField: ...
@@ -63,22 +66,6 @@ class ForeignObjectRel(FieldCacheMixin):
def get_path_info(self, filtered_relation: Optional[FilteredRelation] = ...) -> List[PathInfo]: ... def get_path_info(self, filtered_relation: Optional[FilteredRelation] = ...) -> List[PathInfo]: ...
class ManyToOneRel(ForeignObjectRel): class ManyToOneRel(ForeignObjectRel):
field: RelatedField
hidden: bool
limit_choices_to: Any
many_to_many: bool
many_to_one: bool
model: Union[Type[Model], str]
multiple: bool
name: str
on_delete: Callable
one_to_many: bool
one_to_one: bool
parent_link: bool
related_model: Type[Model]
related_name: Optional[str]
related_query_name: Optional[str]
symmetrical: bool
def __init__( def __init__(
self, self,
field: ForeignKey, field: ForeignKey,
@@ -91,25 +78,8 @@ class ManyToOneRel(ForeignObjectRel):
on_delete: Callable = ..., on_delete: Callable = ...,
) -> None: ... ) -> None: ...
def get_related_field(self) -> Field: ... def get_related_field(self) -> Field: ...
def set_field_name(self) -> None: ...
class OneToOneRel(ManyToOneRel): class OneToOneRel(ManyToOneRel):
field_name: Optional[str]
hidden: bool
limit_choices_to: Dict[str, str]
many_to_many: bool
many_to_one: bool
model: Union[Type[Model], str]
name: str
on_delete: Callable
one_to_many: bool
one_to_one: bool
parent_link: bool
related_model: Type[Model]
related_name: Optional[str]
related_query_name: Optional[str]
symmetrical: bool
multiple: bool = ...
def __init__( def __init__(
self, self,
field: OneToOneField, field: OneToOneField,
@@ -123,14 +93,8 @@ class OneToOneRel(ManyToOneRel):
) -> None: ... ) -> None: ...
class ManyToManyRel(ForeignObjectRel): class ManyToManyRel(ForeignObjectRel):
field_name: None
multiple: bool
name: str
parent_link: bool
related_model: Type[Model]
through: Optional[Union[Type[Model], str]] = ... through: Optional[Union[Type[Model], str]] = ...
through_fields: Optional[Tuple[str, str]] = ... through_fields: Optional[Tuple[str, str]] = ...
symmetrical: bool = ...
db_constraint: bool = ... db_constraint: bool = ...
def __init__( def __init__(
self, self,

View File

@@ -1,6 +1,6 @@
from collections import OrderedDict from collections import OrderedDict
from datetime import datetime from datetime import datetime
from typing import Any, Dict, List, Optional, Tuple, Type, Union, Iterable from typing import Any, Dict, Iterable, List, Optional, Tuple, Type, Union, Mapping
from django.db.backends.sqlite3.base import DatabaseWrapper from django.db.backends.sqlite3.base import DatabaseWrapper
from django.db.models.expressions import Combinable, Expression, Func from django.db.models.expressions import Combinable, Expression, Func
@@ -10,22 +10,21 @@ from django.db.models.sql.query import Query
from django.utils.datastructures import OrderedSet from django.utils.datastructures import OrderedSet
from django.utils.safestring import SafeText from django.utils.safestring import SafeText
from django.db.models import lookups from django.db.models.fields import TextField, related_lookups
from django.db.models.fields import TextField, related_lookups, Field
class Lookup: class Lookup:
lookup_name: Any = ... lookup_name: str = ...
prepare_rhs: bool = ... prepare_rhs: bool = ...
can_use_none_as_rhs: bool = ... can_use_none_as_rhs: bool = ...
lhs: Any = ...
rhs: Any = ... rhs: Any = ...
bilateral_transforms: Any = ... bilateral_transforms: List[Type[Transform]] = ...
def __init__(self, lhs: Union[Expression, TextField, related_lookups.MultiColSource], rhs: Any) -> None: ... def __init__(self, lhs: Union[Expression, TextField, related_lookups.MultiColSource], rhs: Any) -> None: ...
def apply_bilateral_transforms(self, value: Expression) -> Transform: ... def apply_bilateral_transforms(self, value: Expression) -> Transform: ...
def batch_process_rhs( def batch_process_rhs(
self, compiler: SQLCompiler, connection: DatabaseWrapper, rhs: Optional[OrderedSet] = ... self, compiler: SQLCompiler, connection: DatabaseWrapper, rhs: Optional[OrderedSet] = ...
) -> Tuple[List[str], List[str]]: ... ) -> Tuple[List[str], List[str]]: ...
def get_source_expressions(self) -> List[Expression]: ... def get_source_expressions(self) -> List[Expression]: ...
lhs: Any = ...
def set_source_expressions(self, new_exprs: List[Expression]) -> None: ... def set_source_expressions(self, new_exprs: List[Expression]) -> None: ...
def get_prep_lookup(self) -> Any: ... def get_prep_lookup(self) -> Any: ...
def get_db_prep_lookup(self, value: Union[int, str], connection: DatabaseWrapper) -> Tuple[str, List[SafeText]]: ... def get_db_prep_lookup(self, value: Union[int, str], connection: DatabaseWrapper) -> Tuple[str, List[SafeText]]: ...
@@ -36,20 +35,16 @@ class Lookup:
self, compiler: SQLCompiler, connection: DatabaseWrapper self, compiler: SQLCompiler, connection: DatabaseWrapper
) -> Tuple[str, Union[List[Union[int, str]], Tuple[int, int]]]: ... ) -> Tuple[str, Union[List[Union[int, str]], Tuple[int, int]]]: ...
def rhs_is_direct_value(self) -> bool: ... def rhs_is_direct_value(self) -> bool: ...
def relabeled_clone( def relabeled_clone(self, relabels: Mapping[str, str]) -> Union[BuiltinLookup, FieldGetDbPrepValueMixin]: ...
self, relabels: Union[Dict[Optional[str], str], OrderedDict]
) -> Union[BuiltinLookup, FieldGetDbPrepValueMixin]: ...
def get_group_by_cols(self) -> List[Expression]: ... def get_group_by_cols(self) -> List[Expression]: ...
def as_sql(self, compiler: Any, connection: Any) -> None: ... def as_sql(self, compiler: Any, connection: Any) -> Any: ...
def contains_aggregate(self) -> bool: ... def contains_aggregate(self) -> bool: ...
def contains_over_clause(self) -> bool: ... def contains_over_clause(self) -> bool: ...
@property @property
def is_summary(self): ... def is_summary(self) -> bool: ...
class Transform(RegisterLookupMixin, Func): class Transform(RegisterLookupMixin, Func):
bilateral: bool = ... bilateral: bool = ...
arity: int = ...
output_field: Field
@property @property
def lhs(self) -> Expression: ... def lhs(self) -> Expression: ...
def get_bilateral_transforms(self) -> List[Type[Transform]]: ... def get_bilateral_transforms(self) -> List[Type[Transform]]: ...
@@ -61,122 +56,51 @@ class FieldGetDbPrepValueMixin:
get_db_prep_lookup_value_is_iterable: bool = ... get_db_prep_lookup_value_is_iterable: bool = ...
class FieldGetDbPrepValueIterableMixin(FieldGetDbPrepValueMixin): class FieldGetDbPrepValueIterableMixin(FieldGetDbPrepValueMixin):
get_db_prep_lookup_value_is_iterable: bool = ...
def get_prep_lookup(self) -> Iterable[Any]: ... def get_prep_lookup(self) -> Iterable[Any]: ...
def resolve_expression_parameter( def resolve_expression_parameter(
self, compiler: SQLCompiler, connection: DatabaseWrapper, sql: str, param: Optional[Union[Combinable, int, str]] self, compiler: SQLCompiler, connection: DatabaseWrapper, sql: str, param: Any
) -> Tuple[str, List[None]]: ... ) -> Any: ...
class Exact(FieldGetDbPrepValueMixin, BuiltinLookup): class Exact(FieldGetDbPrepValueMixin, BuiltinLookup): ...
bilateral_transforms: List[Type[lookups.Transform]] class IExact(BuiltinLookup): ...
lookup_name: str = ... class GreaterThan(FieldGetDbPrepValueMixin, BuiltinLookup): ...
class GreaterThanOrEqual(FieldGetDbPrepValueMixin, BuiltinLookup): ...
class IExact(BuiltinLookup): class LessThan(FieldGetDbPrepValueMixin, BuiltinLookup): ...
bilateral_transforms: List[Any] class LessThanOrEqual(FieldGetDbPrepValueMixin, BuiltinLookup): ...
lookup_name: str = ...
class GreaterThan(FieldGetDbPrepValueMixin, BuiltinLookup):
bilateral_transforms: List[Any]
lookup_name: str = ...
class GreaterThanOrEqual(FieldGetDbPrepValueMixin, BuiltinLookup):
bilateral_transforms: List[Any]
lookup_name: str = ...
class LessThan(FieldGetDbPrepValueMixin, BuiltinLookup):
bilateral_transforms: List[Any]
lookup_name: str = ...
class LessThanOrEqual(FieldGetDbPrepValueMixin, BuiltinLookup):
bilateral_transforms: List[Type[lookups.Transform]]
lookup_name: str = ...
class IntegerFieldFloatRounding: class IntegerFieldFloatRounding:
rhs: Any = ... rhs: Any = ...
def get_prep_lookup(self) -> Union[Combinable, Query, int]: ... def get_prep_lookup(self) -> Any: ...
class IntegerGreaterThanOrEqual(IntegerFieldFloatRounding, GreaterThanOrEqual): ... class IntegerGreaterThanOrEqual(IntegerFieldFloatRounding, GreaterThanOrEqual): ...
class IntegerLessThan(IntegerFieldFloatRounding, LessThan): ... class IntegerLessThan(IntegerFieldFloatRounding, LessThan): ...
class In(FieldGetDbPrepValueIterableMixin, BuiltinLookup): class In(FieldGetDbPrepValueIterableMixin, BuiltinLookup):
bilateral_transforms: List[Type[lookups.Transform]]
lookup_name: str = ...
def get_rhs_op(self, connection: DatabaseWrapper, rhs: str) -> str: ...
def split_parameter_list_as_sql(self, compiler: Any, connection: Any): ... def split_parameter_list_as_sql(self, compiler: Any, connection: Any): ...
class PatternLookup(BuiltinLookup): class PatternLookup(BuiltinLookup):
param_pattern: str = ... param_pattern: str = ...
prepare_rhs: bool = ...
def get_rhs_op(self, connection: DatabaseWrapper, rhs: str) -> str: ...
class Contains(PatternLookup): class Contains(PatternLookup): ...
bilateral_transforms: List[Type[lookups.Transform]] class IContains(Contains): ...
lookup_name: str = ... class StartsWith(PatternLookup): ...
class IStartsWith(StartsWith): ...
class IContains(Contains): class EndsWith(PatternLookup): ...
bilateral_transforms: List[Any] class IEndsWith(EndsWith): ...
lookup_name: str = ... class Range(FieldGetDbPrepValueIterableMixin, BuiltinLookup): ...
class IsNull(BuiltinLookup): ...
class StartsWith(PatternLookup): class Regex(BuiltinLookup): ...
bilateral_transforms: List[Any] class IRegex(Regex): ...
lookup_name: str = ...
param_pattern: str = ...
class IStartsWith(StartsWith):
bilateral_transforms: List[Any]
lookup_name: str = ...
class EndsWith(PatternLookup):
bilateral_transforms: List[Any]
lookup_name: str = ...
param_pattern: str = ...
class IEndsWith(EndsWith):
bilateral_transforms: List[Any]
lookup_name: str = ...
class Range(FieldGetDbPrepValueIterableMixin, BuiltinLookup):
bilateral_transforms: List[Type[lookups.Transform]]
lookup_name: str = ...
class IsNull(BuiltinLookup):
bilateral_transforms: List[Any]
lookup_name: str = ...
prepare_rhs: bool = ...
class Regex(BuiltinLookup):
bilateral_transforms: List[Any]
lookup_name: str = ...
prepare_rhs: bool = ...
class IRegex(Regex):
bilateral_transforms: List[Any]
lookup_name: str = ...
class YearLookup(Lookup): class YearLookup(Lookup):
def year_lookup_bounds(self, connection: DatabaseWrapper, year: int) -> List[str]: ... def year_lookup_bounds(self, connection: DatabaseWrapper, year: int) -> List[str]: ...
class YearComparisonLookup(YearLookup): class YearComparisonLookup(YearLookup):
bilateral_transforms: List[Any]
def get_rhs_op(self, connection: DatabaseWrapper, rhs: str) -> str: ... def get_rhs_op(self, connection: DatabaseWrapper, rhs: str) -> str: ...
def get_bound(self, start: datetime, finish: datetime) -> Any: ... def get_bound(self, start: datetime, finish: datetime) -> Any: ...
class YearExact(YearLookup, Exact): class YearExact(YearLookup, Exact): ...
bilateral_transforms: List[Any] class YearGt(YearComparisonLookup): ...
lookup_name: str = ... class YearGte(YearComparisonLookup): ...
class YearLt(YearComparisonLookup): ...
class YearGt(YearComparisonLookup): class YearLte(YearComparisonLookup): ...
bilateral_transforms: List[Any]
lookup_name: str = ...
class YearGte(YearComparisonLookup):
bilateral_transforms: List[Any]
lookup_name: str = ...
class YearLt(YearComparisonLookup):
bilateral_transforms: List[Any]
lookup_name: str = ...
class YearLte(YearComparisonLookup):
bilateral_transforms: List[Any]
lookup_name: str = ...

View File

@@ -11,7 +11,6 @@ class BaseManager(QuerySet[_T, _T]):
use_in_migrations: bool = ... use_in_migrations: bool = ...
model: Optional[Any] = ... model: Optional[Any] = ...
name: Optional[Any] = ... name: Optional[Any] = ...
def __new__(cls: Type[BaseManager], *args: Any, **kwargs: Any) -> BaseManager: ...
def __init__(self) -> None: ... def __init__(self) -> None: ...
def deconstruct(self) -> Tuple[bool, str, None, Tuple, Dict[str, int]]: ... def deconstruct(self) -> Tuple[bool, str, None, Tuple, Dict[str, int]]: ...
def check(self, **kwargs: Any) -> List[Any]: ... def check(self, **kwargs: Any) -> List[Any]: ...

View File

@@ -29,7 +29,7 @@ def make_immutable_fields_list(
name: str, data: Union[Iterator[Any], List[Union[ArrayField, CIText]], List[Union[Field, FieldCacheMixin]]] name: str, data: Union[Iterator[Any], List[Union[ArrayField, CIText]], List[Union[Field, FieldCacheMixin]]]
) -> ImmutableList: ... ) -> ImmutableList: ...
_M = TypeVar('_M', bound=Model) _M = TypeVar("_M", bound=Model)
class Options(Generic[_M]): class Options(Generic[_M]):
base_manager: Manager base_manager: Manager
@@ -81,6 +81,8 @@ class Options(Generic[_M]):
related_fkey_lookups: List[Any] = ... related_fkey_lookups: List[Any] = ...
apps: Apps = ... apps: Apps = ...
default_related_name: None = ... default_related_name: None = ...
model: Type[Model] = ...
original_attrs: Dict[str, Any] = ...
def __init__(self, meta: Optional[type], app_label: Optional[str] = ...) -> None: ... def __init__(self, meta: Optional[type], app_label: Optional[str] = ...) -> None: ...
@property @property
def label(self) -> str: ... def label(self) -> str: ...
@@ -90,8 +92,6 @@ class Options(Generic[_M]):
def app_config(self) -> AppConfig: ... def app_config(self) -> AppConfig: ...
@property @property
def installed(self): ... def installed(self): ...
model: Type[Model] = ...
original_attrs: Dict[str, Union[List[str], Apps, str]] = ...
def contribute_to_class(self, cls: Type[Model], name: str) -> None: ... def contribute_to_class(self, cls: Type[Model], name: str) -> None: ...
def add_manager(self, manager: Manager) -> None: ... def add_manager(self, manager: Manager) -> None: ...
def add_field(self, field: Union[GenericForeignKey, Field], private: bool = ...) -> None: ... def add_field(self, field: Union[GenericForeignKey, Field], private: bool = ...) -> None: ...
@@ -102,8 +102,10 @@ class Options(Generic[_M]):
def verbose_name_raw(self) -> Any: ... def verbose_name_raw(self) -> Any: ...
@property @property
def swapped(self) -> Optional[str]: ... def swapped(self) -> Optional[str]: ...
def many_to_many(self) -> ImmutableList: ... @property
def fields_map(self) -> Dict[str, ForeignObjectRel]: ... def many_to_many(self) -> List[ManyToManyField]: ...
@property
def fields_map(self) -> Dict[str, Union[Field, ForeignObjectRel]]: ...
def get_field(self, field_name: Union[Callable, str]) -> Field: ... def get_field(self, field_name: Union[Callable, str]) -> Field: ...
def get_base_chain(self, model: Type[Model]) -> List[Type[Model]]: ... def get_base_chain(self, model: Type[Model]) -> List[Type[Model]]: ...
def get_parent_list(self) -> List[Type[Model]]: ... def get_parent_list(self) -> List[Type[Model]]: ...

View File

@@ -88,16 +88,20 @@ class QuerySet(Generic[_T, _Row], Collection[_Row], Sized):
) -> Tuple[_T, bool]: ... ) -> Tuple[_T, bool]: ...
def earliest(self, *fields: Any, field_name: Optional[Any] = ...) -> _Row: ... def earliest(self, *fields: Any, field_name: Optional[Any] = ...) -> _Row: ...
def latest(self, *fields: Any, field_name: Optional[Any] = ...) -> _Row: ... def latest(self, *fields: Any, field_name: Optional[Any] = ...) -> _Row: ...
def first(self) -> Optional[_Row]: ... # technically it's Optional[_Row], but it creates a lot of false-positives (same for last())
def last(self) -> Optional[_Row]: ... def first(self) -> _Row: ...
def last(self) -> _Row: ...
def in_bulk(self, id_list: Iterable[Any] = ..., *, field_name: str = ...) -> Dict[Any, _T]: ... def in_bulk(self, id_list: Iterable[Any] = ..., *, field_name: str = ...) -> Dict[Any, _T]: ...
def delete(self) -> Tuple[int, Dict[str, int]]: ... def delete(self) -> Tuple[int, Dict[str, int]]: ...
def update(self, **kwargs: Any) -> int: ... def update(self, **kwargs: Any) -> int: ...
def _update(self, values: Any) -> Optional[Any]: ...
def exists(self) -> bool: ... def exists(self) -> bool: ...
def explain(self, *, format: Optional[Any] = ..., **options: Any) -> str: ... def explain(self, *, format: Optional[Any] = ..., **options: Any) -> str: ...
def raw( def raw(
self, raw_query: str, params: Any = ..., translations: Optional[Dict[str, str]] = ..., using: None = ... self,
raw_query: str,
params: Any = ...,
translations: Optional[Dict[str, str]] = ...,
using: Optional[str] = ...,
) -> RawQuerySet: ... ) -> RawQuerySet: ...
# The type of values may be overridden to be more specific in the mypy plugin, depending on the fields param # The type of values may be overridden to be more specific in the mypy plugin, depending on the fields param
def values(self, *fields: Union[str, Combinable], **expressions: Any) -> QuerySet[_T, Dict[str, Any]]: ... def values(self, *fields: Union[str, Combinable], **expressions: Any) -> QuerySet[_T, Dict[str, Any]]: ...

View File

@@ -20,7 +20,7 @@ class QueryWrapper:
contains_aggregate: bool = ... contains_aggregate: bool = ...
data: Tuple[str, List[Any]] = ... data: Tuple[str, List[Any]] = ...
def __init__(self, sql: str, params: List[Any]) -> None: ... def __init__(self, sql: str, params: List[Any]) -> None: ...
def as_sql(self, compiler: SQLCompiler = ..., connection: Any = ...) -> Tuple[str, List[Any]]: ... def as_sql(self, compiler: SQLCompiler = ..., connection: Any = ...) -> Any: ...
class Q(tree.Node): class Q(tree.Node):
children: Union[List[Dict[str, str]], List[Tuple[str, Any]], List[Q]] children: Union[List[Dict[str, str]], List[Tuple[str, Any]], List[Q]]
@@ -84,4 +84,4 @@ class FilteredRelation:
def __init__(self, relation_name: str, *, condition: Any = ...) -> None: ... def __init__(self, relation_name: str, *, condition: Any = ...) -> None: ...
def clone(self) -> FilteredRelation: ... def clone(self) -> FilteredRelation: ...
def resolve_expression(self, *args: Any, **kwargs: Any) -> None: ... def resolve_expression(self, *args: Any, **kwargs: Any) -> None: ...
def as_sql(self, compiler: SQLCompiler, connection: Any) -> Tuple[str, List[Union[int, str]]]: ... def as_sql(self, compiler: SQLCompiler, connection: Any) -> Any: ...

View File

@@ -98,7 +98,7 @@ class Query:
def get_initial_alias(self) -> str: ... def get_initial_alias(self) -> str: ...
def count_active_tables(self) -> int: ... def count_active_tables(self) -> int: ...
def resolve_expression(self, query: Query, *args: Any, **kwargs: Any) -> Query: ... def resolve_expression(self, query: Query, *args: Any, **kwargs: Any) -> Query: ...
def as_sql(self, compiler: SQLCompiler, connection: Any) -> Tuple[str, Tuple]: ... def as_sql(self, compiler: SQLCompiler, connection: Any) -> Any: ...
def resolve_lookup_value(self, value: Any, can_reuse: Optional[Set[str]], allow_joins: bool) -> Any: ... def resolve_lookup_value(self, value: Any, can_reuse: Optional[Set[str]], allow_joins: bool) -> Any: ...
def solve_lookup_type(self, lookup: str) -> Tuple[Sequence[str], Sequence[str], bool]: ... def solve_lookup_type(self, lookup: str) -> Tuple[Sequence[str], Sequence[str], bool]: ...
def build_filter( def build_filter(

View File

@@ -18,7 +18,7 @@ class WhereNode(tree.Node):
resolved: bool = ... resolved: bool = ...
conditional: bool = ... conditional: bool = ...
def split_having(self, negated: bool = ...) -> Tuple[Optional[WhereNode], Optional[WhereNode]]: ... def split_having(self, negated: bool = ...) -> Tuple[Optional[WhereNode], Optional[WhereNode]]: ...
def as_sql(self, compiler: SQLCompiler, connection: Any) -> Tuple[str, List[Union[int, str]]]: ... def as_sql(self, compiler: SQLCompiler, connection: Any) -> Any: ...
def get_group_by_cols(self) -> List[Expression]: ... def get_group_by_cols(self) -> List[Expression]: ...
def relabel_aliases(self, change_map: Union[Dict[Optional[str], str], OrderedDict]) -> None: ... def relabel_aliases(self, change_map: Union[Dict[Optional[str], str], OrderedDict]) -> None: ...
def clone(self) -> WhereNode: ... def clone(self) -> WhereNode: ...

View File

@@ -204,6 +204,12 @@ class NewSemanalDjangoPlugin(Plugin):
return partial(settings.get_type_of_settings_attribute, return partial(settings.get_type_of_settings_attribute,
django_context=self.django_context) django_context=self.django_context)
# def get_type_analyze_hook(self, fullname: str
# ( ):
# info = self._get_typeinfo_or_none(fullname)
# if info and info.has_base(fullnames.QUERYSET_CLASS_FULLNAME):
# return partial(querysets.set_first_generic_param_as_default_for_second, fullname=fullname)
def plugin(version): def plugin(version):
return NewSemanalDjangoPlugin return NewSemanalDjangoPlugin

View File

@@ -1,6 +1,6 @@
from typing import Optional, Tuple, cast from typing import Optional, Tuple, cast
from mypy.nodes import MypyFile, TypeInfo from mypy.nodes import MypyFile, TypeInfo, Var, AssignmentStmt, SymbolTableNode, MDEF
from mypy.plugin import FunctionContext from mypy.plugin import FunctionContext
from mypy.types import AnyType, CallableType, Instance, Type as MypyType, TypeOfAny from mypy.types import AnyType, CallableType, Instance, Type as MypyType, TypeOfAny
@@ -15,9 +15,9 @@ def get_referred_to_model_fullname(ctx: FunctionContext, django_context: DjangoC
return to_arg_type.ret_type.type.fullname() return to_arg_type.ret_type.type.fullname()
outer_model_info = ctx.api.scope.active_class() outer_model_info = ctx.api.scope.active_class()
if not outer_model_info or not outer_model_info.has_base(fullnames.MODEL_CLASS_FULLNAME): # if not outer_model_info or not outer_model_info.has_base(fullnames.MODEL_CLASS_FULLNAME):
# not inside models.Model class # # not inside models.Model class
return None # return None
assert isinstance(outer_model_info, TypeInfo) assert isinstance(outer_model_info, TypeInfo)
to_arg_expr = helpers.get_call_argument_by_name(ctx, 'to') to_arg_expr = helpers.get_call_argument_by_name(ctx, 'to')
@@ -101,6 +101,12 @@ def transform_into_proper_return_type(ctx: FunctionContext, django_context: Djan
default_return_type = ctx.default_return_type default_return_type = ctx.default_return_type
assert isinstance(default_return_type, Instance) assert isinstance(default_return_type, Instance)
outer_model_info = ctx.api.scope.active_class()
if not outer_model_info or not outer_model_info.has_base(fullnames.MODEL_CLASS_FULLNAME):
# not inside models.Model class
return ctx.default_return_type
assert isinstance(outer_model_info, TypeInfo)
if helpers.has_any_of_bases(default_return_type.type, fullnames.RELATED_FIELDS_CLASSES): if helpers.has_any_of_bases(default_return_type.type, fullnames.RELATED_FIELDS_CLASSES):
return fill_descriptor_types_for_related_field(ctx, django_context) return fill_descriptor_types_for_related_field(ctx, django_context)

View File

@@ -1,6 +1,5 @@
from abc import ABCMeta, abstractmethod from abc import ABCMeta, abstractmethod
from abc import ABCMeta, abstractmethod from typing import Type, cast
from typing import cast, Type
from django.db.models.base import Model from django.db.models.base import Model
from django.db.models.fields.related import ForeignKey from django.db.models.fields.related import ForeignKey
@@ -18,7 +17,7 @@ from mypy_django_plugin.transformers import fields
from mypy_django_plugin.transformers.fields import get_field_descriptor_types from mypy_django_plugin.transformers.fields import get_field_descriptor_types
class ModelClassInitializer(metaclass=ABCMeta): class ModelClassInitializer:
def __init__(self, ctx: ClassDefContext, django_context: DjangoContext): def __init__(self, ctx: ClassDefContext, django_context: DjangoContext):
self.api = cast(NewSemanticAnalyzer, ctx.api) self.api = cast(NewSemanticAnalyzer, ctx.api)
self.model_classdef = ctx.cls self.model_classdef = ctx.cls
@@ -52,7 +51,6 @@ class ModelClassInitializer(metaclass=ABCMeta):
return return
self.run_with_model_cls(model_cls) self.run_with_model_cls(model_cls)
@abstractmethod
def run_with_model_cls(self, model_cls): def run_with_model_cls(self, model_cls):
pass pass
@@ -70,7 +68,7 @@ class InjectAnyAsBaseForNestedMeta(ModelClassInitializer):
to get around incompatible Meta inner classes for different models. to get around incompatible Meta inner classes for different models.
""" """
def run_with_model_cls(self, model_cls: Type[Model])-> None: def run(self) -> None:
meta_node = helpers.get_nested_meta_node_for_current_class(self.model_classdef.info) meta_node = helpers.get_nested_meta_node_for_current_class(self.model_classdef.info)
if meta_node is None: if meta_node is None:
return None return None
@@ -78,7 +76,7 @@ class InjectAnyAsBaseForNestedMeta(ModelClassInitializer):
class AddDefaultPrimaryKey(ModelClassInitializer): class AddDefaultPrimaryKey(ModelClassInitializer):
def run_with_model_cls(self, model_cls: Type[Model])-> None: def run_with_model_cls(self, model_cls: Type[Model]) -> None:
auto_field = model_cls._meta.auto_field auto_field = model_cls._meta.auto_field
if auto_field and not self.model_classdef.info.has_readable_member(auto_field.attname): if auto_field and not self.model_classdef.info.has_readable_member(auto_field.attname):
# autogenerated field # autogenerated field
@@ -91,7 +89,7 @@ class AddDefaultPrimaryKey(ModelClassInitializer):
class AddRelatedModelsId(ModelClassInitializer): class AddRelatedModelsId(ModelClassInitializer):
def run_with_model_cls(self, model_cls: Type[Model])-> None: def run_with_model_cls(self, model_cls: Type[Model]) -> None:
for field in model_cls._meta.get_fields(): for field in model_cls._meta.get_fields():
if isinstance(field, ForeignKey): if isinstance(field, ForeignKey):
rel_primary_key_field = self.django_context.get_primary_key_field(field.related_model) rel_primary_key_field = self.django_context.get_primary_key_field(field.related_model)
@@ -103,7 +101,7 @@ class AddRelatedModelsId(ModelClassInitializer):
class AddManagers(ModelClassInitializer): class AddManagers(ModelClassInitializer):
def run_with_model_cls(self, model_cls: Type[Model])-> None: def run_with_model_cls(self, model_cls: Type[Model]) -> None:
for manager_name, manager in model_cls._meta.managers_map.items(): for manager_name, manager in model_cls._meta.managers_map.items():
if manager_name not in self.model_classdef.info.names: if manager_name not in self.model_classdef.info.names:
manager_fullname = helpers.get_class_fullname(manager.__class__) manager_fullname = helpers.get_class_fullname(manager.__class__)
@@ -140,7 +138,7 @@ class AddManagers(ModelClassInitializer):
class AddExtraFieldMethods(ModelClassInitializer): class AddExtraFieldMethods(ModelClassInitializer):
def run_with_model_cls(self, model_cls: Type[Model])-> None: def run_with_model_cls(self, model_cls: Type[Model]) -> None:
# get_FOO_display for choices # get_FOO_display for choices
for field in self.django_context.get_model_fields(model_cls): for field in self.django_context.get_model_fields(model_cls):
if field.choices: if field.choices:
@@ -172,7 +170,7 @@ class AddExtraFieldMethods(ModelClassInitializer):
class AddMetaOptionsAttribute(ModelClassInitializer): class AddMetaOptionsAttribute(ModelClassInitializer):
def run_with_model_cls(self, model_cls: Type[Model])-> None: def run_with_model_cls(self, model_cls: Type[Model]) -> None:
if '_meta' not in self.model_classdef.info.names: if '_meta' not in self.model_classdef.info.names:
options_info = self.lookup_typeinfo_or_incomplete_defn_error(fullnames.OPTIONS_CLASS_FULLNAME) options_info = self.lookup_typeinfo_or_incomplete_defn_error(fullnames.OPTIONS_CLASS_FULLNAME)
self.add_new_node_to_model_class('_meta', self.add_new_node_to_model_class('_meta',

View File

@@ -1,9 +1,10 @@
from collections import OrderedDict from collections import OrderedDict
from typing import Optional, Tuple, Type, Sequence, List, Union from typing import Optional, Tuple, Type, Sequence, List, Union, cast
from django.core.exceptions import FieldError from django.core.exceptions import FieldError
from django.db.models.base import Model from django.db.models.base import Model
from django.db.models.fields.related import ForeignKey from django.db.models.fields.related import ForeignKey
from mypy.newsemanal.typeanal import TypeAnalyser
from mypy.nodes import NameExpr, Expression from mypy.nodes import NameExpr, Expression
from mypy.plugin import AnalyzeTypeContext, FunctionContext, MethodContext from mypy.plugin import AnalyzeTypeContext, FunctionContext, MethodContext
from mypy.types import AnyType, Instance, Type as MypyType, TypeOfAny from mypy.types import AnyType, Instance, Type as MypyType, TypeOfAny
@@ -13,24 +14,20 @@ from mypy_django_plugin.lib import fullnames, helpers
def set_first_generic_param_as_default_for_second(ctx: AnalyzeTypeContext, fullname: str) -> MypyType: def set_first_generic_param_as_default_for_second(ctx: AnalyzeTypeContext, fullname: str) -> MypyType:
info = helpers.lookup_fully_qualified_typeinfo(ctx.api.api, fullname)
if info is None:
if not ctx.api.api.final_iteration:
ctx.api.api.defer()
if not ctx.type.args: if not ctx.type.args:
try: return Instance(info, [AnyType(TypeOfAny.explicit), AnyType(TypeOfAny.explicit)])
return ctx.api.named_type(fullname, [AnyType(TypeOfAny.explicit),
AnyType(TypeOfAny.explicit)])
except KeyError:
# really should never happen
return AnyType(TypeOfAny.explicit)
args = ctx.type.args args = ctx.type.args
if len(args) == 1: if len(args) == 1:
args = [args[0], args[0]] args = [args[0], args[0]]
analyzed_args = [ctx.api.analyze_type(arg) for arg in args] analyzed_args = [ctx.api.analyze_type(arg) for arg in args]
ctx.api.analyze_type(ctx.type) return Instance(info, analyzed_args)
try:
return ctx.api.named_type(fullname, analyzed_args)
except KeyError:
return AnyType(TypeOfAny.explicit)
def determine_proper_manager_type(ctx: FunctionContext) -> MypyType: def determine_proper_manager_type(ctx: FunctionContext) -> MypyType:
@@ -69,7 +66,7 @@ def get_values_list_row_type(ctx: MethodContext, django_context: DjangoContext,
if flat: if flat:
primary_key_field = django_context.get_primary_key_field(model_cls) primary_key_field = django_context.get_primary_key_field(model_cls)
_, column_type = get_lookup_field_get_type(ctx, django_context, model_cls, _, column_type = get_lookup_field_get_type(ctx, django_context, model_cls,
primary_key_field.attname, 'values_list') primary_key_field.attname, 'values_list')
return column_type return column_type
elif named: elif named:
column_types = OrderedDict() column_types = OrderedDict()

View File

@@ -77,23 +77,6 @@
class User(models.Model): class User(models.Model):
my_pk = models.IntegerField(primary_key=True) my_pk = models.IntegerField(primary_key=True)
- case: test_primary_key_on_optional_queryset_method
main: |
from myapp.models import User
reveal_type(User.objects.first().id)
out: |
main:2: note: Revealed type is 'Union[builtins.int*, Any]'
main:2: error: Item "None" of "Optional[User]" has no attribute "id"
installed_apps:
- myapp
files:
- path: myapp/__init__.py
- path: myapp/models.py
content: |
from django.db import models
class User(models.Model):
pass
- case: blank_and_null_char_field_allows_none - case: blank_and_null_char_field_allows_none
main: | main: |
from myapp.models import MyModel from myapp.models import MyModel
@@ -127,3 +110,17 @@
from django.db import models from django.db import models
class MyModel(models.Model): class MyModel(models.Model):
notnulltext=models.CharField(max_length=1, blank=True, null=False) notnulltext=models.CharField(max_length=1, blank=True, null=False)
- case: if_field_called_on_class_return_field_itself
main: |
from myapp.models import MyUser
reveal_type(MyUser.name) # N: Revealed type is 'django.db.models.fields.CharField[Union[builtins.str, builtins.int, django.db.models.expressions.Combinable], builtins.str]'
installed_apps:
- myapp
files:
- path: myapp/__init__.py
- path: myapp/models.py
content: |
from django.db import models
class MyUser(models.Model):
name = models.CharField(max_length=100)

View File

@@ -7,7 +7,7 @@
reveal_type(qs.get(id=1)) # N: Revealed type is 'myapp.models.Blog*' reveal_type(qs.get(id=1)) # N: Revealed type is 'myapp.models.Blog*'
reveal_type(iter(qs)) # N: Revealed type is 'typing.Iterator[myapp.models.Blog*]' reveal_type(iter(qs)) # N: Revealed type is 'typing.Iterator[myapp.models.Blog*]'
reveal_type(qs.iterator()) # N: Revealed type is 'typing.Iterator[myapp.models.Blog*]' reveal_type(qs.iterator()) # N: Revealed type is 'typing.Iterator[myapp.models.Blog*]'
reveal_type(qs.first()) # N: Revealed type is 'Union[myapp.models.Blog*, None]' reveal_type(qs.first()) # N: Revealed type is 'myapp.models.Blog*'
reveal_type(qs.earliest()) # N: Revealed type is 'myapp.models.Blog*' reveal_type(qs.earliest()) # N: Revealed type is 'myapp.models.Blog*'
reveal_type(qs[0]) # N: Revealed type is 'myapp.models.Blog*' reveal_type(qs[0]) # N: Revealed type is 'myapp.models.Blog*'
reveal_type(qs[:9]) # N: Revealed type is 'django.db.models.query.QuerySet[myapp.models.Blog*, myapp.models.Blog*]' reveal_type(qs[:9]) # N: Revealed type is 'django.db.models.query.QuerySet[myapp.models.Blog*, myapp.models.Blog*]'

View File

@@ -212,10 +212,10 @@
main: | main: |
from myapp.models import UnrelatedModel, MyModel from myapp.models import UnrelatedModel, MyModel
reveal_type(UnrelatedModel.objects) # N: Revealed type is 'django.db.models.manager.Manager[myapp.models.UnrelatedModel]' reveal_type(UnrelatedModel.objects) # N: Revealed type is 'django.db.models.manager.Manager[myapp.models.UnrelatedModel]'
reveal_type(UnrelatedModel.objects.first()) # N: Revealed type is 'Union[myapp.models.UnrelatedModel*, None]' reveal_type(UnrelatedModel.objects.first()) # N: Revealed type is 'myapp.models.UnrelatedModel*'
reveal_type(MyModel.objects) # N: Revealed type is 'django.db.models.manager.Manager[myapp.models.MyModel]' reveal_type(MyModel.objects) # N: Revealed type is 'django.db.models.manager.Manager[myapp.models.MyModel]'
reveal_type(MyModel.objects.first()) # N: Revealed type is 'Union[myapp.models.MyModel*, None]' reveal_type(MyModel.objects.first()) # N: Revealed type is 'myapp.models.MyModel*'
installed_apps: installed_apps:
- myapp - myapp
files: files:
@@ -233,10 +233,10 @@
main: | main: |
from myapp.models import UnrelatedModel2, MyModel2 from myapp.models import UnrelatedModel2, MyModel2
reveal_type(UnrelatedModel2.objects) # N: Revealed type is 'django.db.models.manager.Manager[myapp.models.UnrelatedModel2]' reveal_type(UnrelatedModel2.objects) # N: Revealed type is 'django.db.models.manager.Manager[myapp.models.UnrelatedModel2]'
reveal_type(UnrelatedModel2.objects.first()) # N: Revealed type is 'Union[myapp.models.UnrelatedModel2*, None]' reveal_type(UnrelatedModel2.objects.first()) # N: Revealed type is 'myapp.models.UnrelatedModel2*'
reveal_type(MyModel2.objects) # N: Revealed type is 'django.db.models.manager.Manager[myapp.models.MyModel2]' reveal_type(MyModel2.objects) # N: Revealed type is 'django.db.models.manager.Manager[myapp.models.MyModel2]'
reveal_type(MyModel2.objects.first()) # N: Revealed type is 'Union[myapp.models.MyModel2*, None]' reveal_type(MyModel2.objects.first()) # N: Revealed type is 'myapp.models.MyModel2*'
installed_apps: installed_apps:
- myapp - myapp
files: files:
@@ -254,10 +254,10 @@
main: | main: |
from myapp.models import ParentOfMyModel3, MyModel3 from myapp.models import ParentOfMyModel3, MyModel3
reveal_type(ParentOfMyModel3.objects) # N: Revealed type is 'django.db.models.manager.Manager[myapp.models.ParentOfMyModel3]' reveal_type(ParentOfMyModel3.objects) # N: Revealed type is 'django.db.models.manager.Manager[myapp.models.ParentOfMyModel3]'
reveal_type(ParentOfMyModel3.objects.first()) # N: Revealed type is 'Union[myapp.models.ParentOfMyModel3*, None]' reveal_type(ParentOfMyModel3.objects.first()) # N: Revealed type is 'myapp.models.ParentOfMyModel3*'
reveal_type(MyModel3.objects) # N: Revealed type is 'django.db.models.manager.Manager[myapp.models.MyModel3]' reveal_type(MyModel3.objects) # N: Revealed type is 'django.db.models.manager.Manager[myapp.models.MyModel3]'
reveal_type(MyModel3.objects.first()) # N: Revealed type is 'Union[myapp.models.MyModel3*, None]' reveal_type(MyModel3.objects.first()) # N: Revealed type is 'myapp.models.MyModel3*'
installed_apps: installed_apps:
- myapp - myapp
files: files:
@@ -275,10 +275,10 @@
main: | main: |
from myapp.models import ParentOfMyModel4, MyModel4 from myapp.models import ParentOfMyModel4, MyModel4
reveal_type(ParentOfMyModel4.objects) # N: Revealed type is 'django.db.models.manager.Manager[myapp.models.ParentOfMyModel4]' reveal_type(ParentOfMyModel4.objects) # N: Revealed type is 'django.db.models.manager.Manager[myapp.models.ParentOfMyModel4]'
reveal_type(ParentOfMyModel4.objects.first()) # N: Revealed type is 'Union[myapp.models.ParentOfMyModel4*, None]' reveal_type(ParentOfMyModel4.objects.first()) # N: Revealed type is 'myapp.models.ParentOfMyModel4*'
reveal_type(MyModel4.objects) # N: Revealed type is 'django.db.models.manager.Manager[myapp.models.MyModel4]' reveal_type(MyModel4.objects) # N: Revealed type is 'django.db.models.manager.Manager[myapp.models.MyModel4]'
reveal_type(MyModel4.objects.first()) # N: Revealed type is 'Union[myapp.models.MyModel4*, None]' reveal_type(MyModel4.objects.first()) # N: Revealed type is 'myapp.models.MyModel4*'
installed_apps: installed_apps:
- myapp - myapp
files: files:
@@ -291,3 +291,30 @@
class MyModel4(ParentOfMyModel4): class MyModel4(ParentOfMyModel4):
objects = models.Manager['MyModel4']() objects = models.Manager['MyModel4']()
# TODO: make it work someday
#- case: inheritance_of_two_models_with_custom_objects_manager
# main: |
# from myapp.models import MyBaseUser, MyUser
# reveal_type(MyBaseUser.objects) # N: Revealed type is 'myapp.models.MyBaseManager[myapp.models.MyBaseUser]'
# reveal_type(MyBaseUser.objects.get()) # N: Revealed type is 'myapp.models.MyBaseUser'
#
# reveal_type(MyUser.objects) # N: Revealed type is 'myapp.models.MyManager[myapp.models.MyUser]'
# reveal_type(MyUser.objects.get()) # N: Revealed type is 'myapp.models.MyUser'
# installed_apps:
# - myapp
# files:
# - path: myapp/__init__.py
# - path: myapp/models.py
# content: |
# from django.db import models
#
# class MyBaseManager(models.Manager):
# pass
# class MyBaseUser(models.Model):
# objects = MyBaseManager()
#
# class MyManager(models.Manager):
# pass
# class MyUser(MyBaseUser):
# objects = MyManager()

View File

@@ -15,12 +15,14 @@
- case: get_field_returns_proper_field_type - case: get_field_returns_proper_field_type
main: | main: |
from myapp.models import MyUser from myapp.models import MyUser
reveal_type(MyUser._meta.get_field('base_name')) # N: Revealed type is 'django.db.models.fields.CharField[Any, Any]'
reveal_type(MyUser._meta.get_field('name')) # N: Revealed type is 'django.db.models.fields.CharField[Any, Any]' reveal_type(MyUser._meta.get_field('name')) # N: Revealed type is 'django.db.models.fields.CharField[Any, Any]'
reveal_type(MyUser._meta.get_field('age')) # N: Revealed type is 'django.db.models.fields.IntegerField[Any, Any]' reveal_type(MyUser._meta.get_field('age')) # N: Revealed type is 'django.db.models.fields.IntegerField[Any, Any]'
reveal_type(MyUser._meta.get_field('unknown')) reveal_type(MyUser._meta.get_field('unknown'))
reveal_type(MyUser._meta.get_field('to_user')) # N: Revealed type is 'django.db.models.fields.related.ForeignKey[Any, Any]'
out: | out: |
main:4: note: Revealed type is 'Any' main:5: note: Revealed type is 'Any'
main:4: error: MyUser has no field named 'unknown' main:5: error: MyUser has no field named 'unknown'
installed_apps: installed_apps:
- myapp - myapp
files: files:
@@ -28,6 +30,9 @@
- path: myapp/models.py - path: myapp/models.py
content: | content: |
from django.db import models from django.db import models
class MyUser(models.Model): class MyBaseUser(models.Model):
base_name = models.CharField(max_length=100)
class MyUser(MyBaseUser):
name = models.CharField(max_length=100) name = models.CharField(max_length=100)
age = models.IntegerField() age = models.IntegerField()
to_user = models.ForeignKey('self', on_delete=models.SET_NULL)

View File

@@ -22,7 +22,7 @@
class MyModel(models.Model): class MyModel(models.Model):
user = models.ForeignKey('auth.User', on_delete=models.CASCADE) user = models.ForeignKey('auth.User', on_delete=models.CASCADE)
if TYPE_CHECKING: if TYPE_CHECKING:
reveal_type(MyModel.user) # N: Revealed type is 'django.contrib.auth.models.User*' reveal_type(MyModel().user) # N: Revealed type is 'django.contrib.auth.models.User*'
- case: generate_pyproject_toml_and_settings_file_from_installed_apps_key - case: generate_pyproject_toml_and_settings_file_from_installed_apps_key
main: | main: |