fix problem with TypeVar bound to Model passed as a parameter

This commit is contained in:
Maxim Kurnikov
2019-01-24 18:59:41 +03:00
parent cff5ab463c
commit 5a0f00dde1
6 changed files with 43 additions and 21 deletions

View File

@@ -21,12 +21,6 @@ class Permission(models.Model):
name: str = ...
content_type: Any = ...
codename: str = ...
objects: Any = ...
class Meta:
verbose_name: Any = ...
verbose_name_plural: Any = ...
unique_together: Any = ...
ordering: Any = ...
def natural_key(self) -> Tuple[str, str, str]: ...
class GroupManager(models.Manager):
@@ -40,10 +34,6 @@ class Group(models.Model):
id: None
name: str = ...
permissions: Any = ...
objects: Any = ...
class Meta:
verbose_name: Any = ...
verbose_name_plural: Any = ...
def natural_key(self): ...
class UserManager(BaseUserManager):
@@ -77,7 +67,6 @@ class AbstractUser(AbstractBaseUser, PermissionsMixin):
email: str = ...
is_staff: bool = ...
date_joined: datetime.datetime = ...
objects: Any = ...
EMAIL_FIELD: str = ...
USERNAME_FIELD: str = ...
def clean(self) -> None: ...
@@ -85,9 +74,7 @@ class AbstractUser(AbstractBaseUser, PermissionsMixin):
def get_short_name(self) -> str: ...
def email_user(self, subject: str, message: str, from_email: str = ..., **kwargs: Any) -> None: ...
class User(AbstractUser):
class Meta(AbstractUser.Meta):
swappable: str = ...
class User(AbstractUser): ...
class AnonymousUser:
id: Any = ...

View File

@@ -1,12 +1,14 @@
from typing import Any, List, Optional, Set, Tuple, Dict
class ModelBase(type):
pass
from django.db.models.manager import Manager
class ModelBase(type): ...
class Model(metaclass=ModelBase):
class DoesNotExist(Exception):
pass
pk: Any = ...
objects: Manager[Model]
def __init__(self, **kwargs) -> None: ...
def delete(self, using: Any = ..., keep_parents: bool = ...) -> Tuple[int, Dict[str, int]]: ...
def full_clean(self, exclude: Optional[List[str]] = ..., validate_unique: bool = ...) -> None: ...

View File

@@ -3,7 +3,7 @@ from typing import Any, Dict, List, Optional, Tuple, Type, TypeVar
from django.db.models.base import Model
from django.db.models.query import QuerySet
_T = TypeVar("_T", bound=Model)
_T = TypeVar("_T", bound=Model, covariant=True)
class BaseManager(QuerySet[_T]):
creation_counter: int = ...
@@ -24,7 +24,7 @@ class BaseManager(QuerySet[_T]):
class Manager(BaseManager[_T]): ...
class RelatedManager(Manager[_T]):
def add(self, *objs: _T, bulk: bool = ...) -> None: ...
def add(self, *objs: Model, bulk: bool = ...) -> None: ...
def clear(self) -> None: ...
class ManagerDescriptor:

View File

@@ -6,7 +6,7 @@ from django.db import models
from django.db.models import Manager
from django.db.models.sql.query import Query, RawQuery
_T = TypeVar("_T", bound=models.Model)
_T = TypeVar("_T", bound=models.Model, covariant=True)
class QuerySet(Iterable[_T], Sized):
def __init__(

View File

@@ -93,8 +93,13 @@ class InjectAnyAsBaseForNestedMeta(ModelClassInitializer):
class AddDefaultObjectsManager(ModelClassInitializer):
def is_default_objects_attr(self, sym: SymbolTableNode) -> bool:
return sym.fullname == helpers.MODEL_CLASS_FULLNAME + '.' + 'objects'
def run(self) -> None:
if 'objects' in self.model_classdef.info.names:
existing_objects_sym = self.model_classdef.info.get('objects')
if (existing_objects_sym is not None
and not self.is_default_objects_attr(existing_objects_sym)):
return None
if self.is_abstract_model():

View File

@@ -8,7 +8,7 @@ reveal_type(User.objects.get()) # E: Revealed type is 'main.User*'
[CASE test_leave_as_is_if_objects_is_set_and_fill_typevars_with_outer_class]
from django.db import models
class UserManager(models.Manager):
class UserManager(models.Manager[User]):
def get_or_404(self) -> User:
pass
@@ -19,3 +19,31 @@ reveal_type(User.objects) # E: Revealed type is 'main.UserManager'
reveal_type(User.objects.get()) # E: Revealed type is 'main.User*'
reveal_type(User.objects.get_or_404()) # E: Revealed type is 'main.User'
[CASE test_model_objects_attribute_present_in_case_of_model_cls_passed_as_parameter]
from typing import Type
from django.db import models
class Base:
def __init__(self, model_cls: Type[models.Model]):
self.model_cls = model_cls
class MyModel(models.Model):
pass
reveal_type(Base(MyModel).model_cls.objects) # E: Revealed type is 'django.db.models.manager.Manager[django.db.models.base.Model]'
[CASE test_model_objects_attribute_present_in_case_of_model_cls_passed_as_generic_parameter]
from typing import TypeVar, Generic, Type
from django.db import models
_T = TypeVar('_T', bound=models.Model)
class Base(Generic[_T]):
def __init__(self, model_cls: Type[_T]):
self.model_cls = model_cls
reveal_type(self.model_cls.objects) # E: Revealed type is 'django.db.models.manager.Manager[django.db.models.base.Model]'
class MyModel(models.Model):
pass
base_instance = Base(MyModel)
reveal_type(base_instance.model_cls.objects) # E: Revealed type is 'django.db.models.manager.Manager[main.MyModel]'
class Child(Base[MyModel]):
def method(self) -> None:
reveal_type(self.model_cls.objects) # E: Revealed type is 'django.db.models.manager.Manager[main.MyModel]'