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):
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__(
self,
field: GenericRelation,
to: Union[Type[Model], str],
related_name: None = ...,
related_name: Optional[str] = ...,
related_query_name: Optional[str] = ...,
limit_choices_to: Optional[Union[Dict[str, Any], Callable[[], Any]]] = ...,
) -> None: ...
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 = ...
mti_inherited: bool = ...
object_id_field_name: Any = ...
@@ -93,23 +80,16 @@ class GenericRelation(ForeignObject):
limit_choices_to: Optional[Union[Dict[str, Any], Callable[[], Any]]] = ...,
**kwargs: Any
) -> None: ...
def check(self, **kwargs: Any) -> List[Error]: ...
def resolve_related_fields(self) -> List[Tuple[PositiveIntegerField, Field]]: ...
def get_path_info(self, filtered_relation: Optional[FilteredRelation] = ...) -> List[PathInfo]: ...
def get_reverse_path_info(self, filtered_relation: None = ...) -> List[PathInfo]: ...
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_extra_restriction(
self, where_class: Type[WhereNode], alias: Optional[str], remote_alias: str
) -> WhereNode: ...
def bulk_related_objects(self, objs: List[Model], using: str = ...) -> QuerySet: ...
class ReverseGenericManyToOneDescriptor(ReverseManyToOneDescriptor):
field: GenericRelation
rel: GenericRel
def related_manager_cls(self): ...
class ReverseGenericManyToOneDescriptor(ReverseManyToOneDescriptor): ...
def create_generic_related_manager(superclass: Any, rel: Any): ...

View File

@@ -1,15 +1,6 @@
from typing import Any, List, Optional
from django.core.checks.messages import Error
from django.db.models.query import QuerySet
from typing import Optional
from django.db import models
class CurrentSiteManager(models.Manager):
creation_counter: int
model: None
name: None
use_in_migrations: bool = ...
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 = ...
filterable: bool = ...
window_compatible: bool = ...
output_field: Field
def __init__(self, output_field: Optional[_OutputField] = ...) -> None: ...
def get_db_converters(self, connection: Any) -> List[Callable]: ...
def get_source_expressions(self) -> List[Any]: ...
@@ -74,6 +73,8 @@ class BaseExpression:
@property
def field(self) -> Field: ...
@property
def output_field(self) -> Field: ...
@property
def convert_value(self) -> Callable: ...
def get_lookup(self, lookup: str) -> Optional[Type[Lookup]]: ...
def get_transform(self, name: str) -> Optional[Type[Expression]]: ...

View File

@@ -1,13 +1,27 @@
import decimal
import uuid
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.db.models import Model
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.forms import Field as FormField, Widget
@@ -20,6 +34,7 @@ _FieldChoices = Iterable[Union[_Choice, _ChoiceNamedGroup]]
_ValidatorCallable = Callable[..., None]
_ErrorMessagesToOverride = Dict[str, Any]
_T = TypeVar("_T", bound="Field")
# __set__ value type
_ST = TypeVar("_ST")
# __get__ return type
@@ -36,7 +51,7 @@ class Field(RegisterLookupMixin, Generic[_ST, _GT]):
auto_created: bool
primary_key: bool
remote_field: Field
max_length: Optional[int]
max_length: int
model: Type[Model]
name: str
verbose_name: str
@@ -72,6 +87,11 @@ class Field(RegisterLookupMixin, Generic[_ST, _GT]):
error_messages: Optional[_ErrorMessagesToOverride] = ...,
): ...
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 deconstruct(self) -> Any: ...
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]: ...
@property
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]):
_pyi_private_set_type: Union[float, int, str, Combinable]

View File

@@ -1,39 +1,25 @@
from typing import (
Type,
Union,
TypeVar,
Any,
Generic,
List,
Optional,
Dict,
Callable,
Tuple,
Sequence,
TYPE_CHECKING,
Iterable,
)
from typing import Any, Callable, Dict, Iterable, List, Optional, Sequence, TYPE_CHECKING, Tuple, Type, TypeVar, Union
from uuid import UUID
from django.db import models
from django.db.models import Field, Model, QuerySet
from django.db.models.expressions import Combinable
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 (
ReverseManyToOneDescriptor as ReverseManyToOneDescriptor,
ReverseOneToOneDescriptor as ReverseOneToOneDescriptor,
ForwardManyToOneDescriptor as ForwardManyToOneDescriptor,
ForwardOneToOneDescriptor as ForwardOneToOneDescriptor,
ForwardManyToOneDescriptor as ForwardManyToOneDescriptor,
ManyToManyDescriptor as ManyToManyDescriptor,
ReverseOneToOneDescriptor as ReverseOneToOneDescriptor,
ReverseManyToOneDescriptor as ReverseManyToOneDescriptor,
)
from django.db.models.fields.reverse_related import (
ForeignObjectRel as ForeignObjectRel,
ManyToManyRel as ManyToManyRel,
ManyToOneRel as ManyToOneRel,
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:
from django.db.models.manager import RelatedManager
@@ -61,14 +47,11 @@ class RelatedField(FieldCacheMixin, Field[_ST, _GT]):
many_to_one: bool = ...
@property
def related_model(self) -> Union[Type[Model], str]: ...
def check(self, **kwargs: Any) -> List[Any]: ...
opts: Any = ...
def get_forward_related_filter(self, obj: Model) -> Dict[str, Union[int, UUID]]: ...
def get_reverse_related_filter(self, obj: Model) -> Q: ...
@property
def swappable_setting(self) -> Optional[str]: ...
name: Any = ...
verbose_name: Any = ...
def set_attributes_from_rel(self) -> None: ...
def do_related_class(self, other: Type[Model], cls: Type[Model]) -> None: ...
def get_limit_choices_to(self) -> Dict[str, int]: ...
@@ -188,7 +171,14 @@ class ManyToManyField(RelatedField[_ST, _GT]):
rel_class: Any = ...
description: 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__(
self,
to: Union[Type[_T], str],
@@ -223,19 +213,9 @@ class ManyToManyField(RelatedField[_ST, _GT]):
validators: Iterable[_ValidatorCallable] = ...,
error_messages: Optional[_ErrorMessagesToOverride] = ...,
) -> 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_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 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]: ...

View File

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

View File

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

View File

@@ -11,7 +11,6 @@ class BaseManager(QuerySet[_T, _T]):
use_in_migrations: bool = ...
model: Optional[Any] = ...
name: Optional[Any] = ...
def __new__(cls: Type[BaseManager], *args: Any, **kwargs: Any) -> BaseManager: ...
def __init__(self) -> None: ...
def deconstruct(self) -> Tuple[bool, str, None, Tuple, Dict[str, int]]: ...
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]]]
) -> ImmutableList: ...
_M = TypeVar('_M', bound=Model)
_M = TypeVar("_M", bound=Model)
class Options(Generic[_M]):
base_manager: Manager
@@ -81,6 +81,8 @@ class Options(Generic[_M]):
related_fkey_lookups: List[Any] = ...
apps: Apps = ...
default_related_name: None = ...
model: Type[Model] = ...
original_attrs: Dict[str, Any] = ...
def __init__(self, meta: Optional[type], app_label: Optional[str] = ...) -> None: ...
@property
def label(self) -> str: ...
@@ -90,8 +92,6 @@ class Options(Generic[_M]):
def app_config(self) -> AppConfig: ...
@property
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 add_manager(self, manager: Manager) -> 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: ...
@property
def swapped(self) -> Optional[str]: ...
def many_to_many(self) -> ImmutableList: ...
def fields_map(self) -> Dict[str, ForeignObjectRel]: ...
@property
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_base_chain(self, model: Type[Model]) -> 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]: ...
def earliest(self, *fields: Any, field_name: Optional[Any] = ...) -> _Row: ...
def latest(self, *fields: Any, field_name: Optional[Any] = ...) -> _Row: ...
def first(self) -> Optional[_Row]: ...
def last(self) -> Optional[_Row]: ...
# technically it's Optional[_Row], but it creates a lot of false-positives (same for last())
def first(self) -> _Row: ...
def last(self) -> _Row: ...
def in_bulk(self, id_list: Iterable[Any] = ..., *, field_name: str = ...) -> Dict[Any, _T]: ...
def delete(self) -> Tuple[int, Dict[str, int]]: ...
def update(self, **kwargs: Any) -> int: ...
def _update(self, values: Any) -> Optional[Any]: ...
def exists(self) -> bool: ...
def explain(self, *, format: Optional[Any] = ..., **options: Any) -> str: ...
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: ...
# 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]]: ...

View File

@@ -20,7 +20,7 @@ class QueryWrapper:
contains_aggregate: bool = ...
data: Tuple[str, List[Any]] = ...
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):
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 clone(self) -> FilteredRelation: ...
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 count_active_tables(self) -> int: ...
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 solve_lookup_type(self, lookup: str) -> Tuple[Sequence[str], Sequence[str], bool]: ...
def build_filter(

View File

@@ -18,7 +18,7 @@ class WhereNode(tree.Node):
resolved: bool = ...
conditional: bool = ...
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 relabel_aliases(self, change_map: Union[Dict[Optional[str], str], OrderedDict]) -> None: ...
def clone(self) -> WhereNode: ...

View File

@@ -204,6 +204,12 @@ class NewSemanalDjangoPlugin(Plugin):
return partial(settings.get_type_of_settings_attribute,
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):
return NewSemanalDjangoPlugin

View File

@@ -1,6 +1,6 @@
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.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()
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 None
# if not outer_model_info or not outer_model_info.has_base(fullnames.MODEL_CLASS_FULLNAME):
# # not inside models.Model class
# return None
assert isinstance(outer_model_info, TypeInfo)
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
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):
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 typing import cast, Type
from typing import Type, cast
from django.db.models.base import Model
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
class ModelClassInitializer(metaclass=ABCMeta):
class ModelClassInitializer:
def __init__(self, ctx: ClassDefContext, django_context: DjangoContext):
self.api = cast(NewSemanticAnalyzer, ctx.api)
self.model_classdef = ctx.cls
@@ -52,7 +51,6 @@ class ModelClassInitializer(metaclass=ABCMeta):
return
self.run_with_model_cls(model_cls)
@abstractmethod
def run_with_model_cls(self, model_cls):
pass
@@ -70,7 +68,7 @@ class InjectAnyAsBaseForNestedMeta(ModelClassInitializer):
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)
if meta_node is None:
return None
@@ -78,7 +76,7 @@ class InjectAnyAsBaseForNestedMeta(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
if auto_field and not self.model_classdef.info.has_readable_member(auto_field.attname):
# autogenerated field
@@ -91,7 +89,7 @@ class AddDefaultPrimaryKey(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():
if isinstance(field, ForeignKey):
rel_primary_key_field = self.django_context.get_primary_key_field(field.related_model)
@@ -103,7 +101,7 @@ class AddRelatedModelsId(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():
if manager_name not in self.model_classdef.info.names:
manager_fullname = helpers.get_class_fullname(manager.__class__)
@@ -140,7 +138,7 @@ class AddManagers(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
for field in self.django_context.get_model_fields(model_cls):
if field.choices:
@@ -172,7 +170,7 @@ class AddExtraFieldMethods(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:
options_info = self.lookup_typeinfo_or_incomplete_defn_error(fullnames.OPTIONS_CLASS_FULLNAME)
self.add_new_node_to_model_class('_meta',

View File

@@ -1,9 +1,10 @@
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.db.models.base import Model
from django.db.models.fields.related import ForeignKey
from mypy.newsemanal.typeanal import TypeAnalyser
from mypy.nodes import NameExpr, Expression
from mypy.plugin import AnalyzeTypeContext, FunctionContext, MethodContext
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:
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:
try:
return ctx.api.named_type(fullname, [AnyType(TypeOfAny.explicit),
AnyType(TypeOfAny.explicit)])
except KeyError:
# really should never happen
return AnyType(TypeOfAny.explicit)
return Instance(info, [AnyType(TypeOfAny.explicit), AnyType(TypeOfAny.explicit)])
args = ctx.type.args
if len(args) == 1:
args = [args[0], args[0]]
analyzed_args = [ctx.api.analyze_type(arg) for arg in args]
ctx.api.analyze_type(ctx.type)
try:
return ctx.api.named_type(fullname, analyzed_args)
except KeyError:
return AnyType(TypeOfAny.explicit)
return Instance(info, analyzed_args)
def determine_proper_manager_type(ctx: FunctionContext) -> MypyType:

View File

@@ -77,23 +77,6 @@
class User(models.Model):
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
main: |
from myapp.models import MyModel
@@ -127,3 +110,17 @@
from django.db import models
class MyModel(models.Model):
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(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.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[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*]'

View File

@@ -212,10 +212,10 @@
main: |
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.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.first()) # N: Revealed type is 'Union[myapp.models.MyModel*, None]'
reveal_type(MyModel.objects.first()) # N: Revealed type is 'myapp.models.MyModel*'
installed_apps:
- myapp
files:
@@ -233,10 +233,10 @@
main: |
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.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.first()) # N: Revealed type is 'Union[myapp.models.MyModel2*, None]'
reveal_type(MyModel2.objects.first()) # N: Revealed type is 'myapp.models.MyModel2*'
installed_apps:
- myapp
files:
@@ -254,10 +254,10 @@
main: |
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.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.first()) # N: Revealed type is 'Union[myapp.models.MyModel3*, None]'
reveal_type(MyModel3.objects.first()) # N: Revealed type is 'myapp.models.MyModel3*'
installed_apps:
- myapp
files:
@@ -275,10 +275,10 @@
main: |
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.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.first()) # N: Revealed type is 'Union[myapp.models.MyModel4*, None]'
reveal_type(MyModel4.objects.first()) # N: Revealed type is 'myapp.models.MyModel4*'
installed_apps:
- myapp
files:
@@ -291,3 +291,30 @@
class MyModel4(ParentOfMyModel4):
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
main: |
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('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('to_user')) # N: Revealed type is 'django.db.models.fields.related.ForeignKey[Any, Any]'
out: |
main:4: note: Revealed type is 'Any'
main:4: error: MyUser has no field named 'unknown'
main:5: note: Revealed type is 'Any'
main:5: error: MyUser has no field named 'unknown'
installed_apps:
- myapp
files:
@@ -28,6 +30,9 @@
- path: myapp/models.py
content: |
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)
age = models.IntegerField()
to_user = models.ForeignKey('self', on_delete=models.SET_NULL)

View File

@@ -22,7 +22,7 @@
class MyModel(models.Model):
user = models.ForeignKey('auth.User', on_delete=models.CASCADE)
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
main: |