Recover after #909 (#925)

* Fix stubs related to `(Async)RequestFactory` and `(Async)Client`

* Revert incorrect removal.

* Allow set as `unique_together`, use shared type alias.

* Revert `Q.__init__` to use only `*args, **kwargs` to remove false-positive with `Q(**{...})`

* Add abstract methods to `HttpResponseBase` to create common interface.

* Remove monkey-patched attributes from `HttpResponseBase` subclasses.

* Add QueryDict mutability checks (+ plugin support)

* Fix lint

* Return back GenericForeignKey to `Options.get_fields`

* Minor fixup

* Make plugin code typecheck with `--warn-unreachable`, minor performance increase.

* Better types for `{unique, index}_together` and Options.

* Fix odd type of `URLResolver.urlconf_name` which isn't a str actually.

* Better types for field migration operations.

* Revert form.files to `MultiValueDict[str, UploadedFile]`

* Compatibility fix (#916)

* Do not assume that `Annotated` is always related to django-stubs (fixes #893)

* Restrict `FormView.get_form` return type to `_FormT` (class type argument). Now it is resolved to `form_class` argument if present, but also errors if it is not subclass of _FormT

* Fix CI (make test runnable on 3.8)

* Fix CI (make test runnable on 3.8 _again_)
This commit is contained in:
sterliakov
2022-04-28 13:01:37 +03:00
committed by GitHub
parent 16499a22ab
commit 6226381484
29 changed files with 380 additions and 138 deletions

View File

@@ -0,0 +1,33 @@
- case: client_methods
main: |
from django.test.client import Client
client = Client()
response = client.get('foo')
reveal_type(response.wsgi_request) # N: Revealed type is "django.core.handlers.wsgi.WSGIRequest"
reveal_type(response.request) # N: Revealed type is "builtins.dict[builtins.str, Any]"
reveal_type(response.templates) # N: Revealed type is "builtins.list[django.template.base.Template]"
reveal_type(response.client) # N: Revealed type is "django.test.client.Client"
reveal_type(response.context) # N: Revealed type is "builtins.list[builtins.dict[builtins.str, Any]]"
response.json()
- case: async_client_methods
main: |
from django.test.client import AsyncClient
async def main():
client = AsyncClient()
response = await client.get('foo')
reveal_type(response.asgi_request) # N: Revealed type is "django.core.handlers.asgi.ASGIRequest"
reveal_type(response.request) # N: Revealed type is "builtins.dict[builtins.str, Any]"
reveal_type(response.templates) # N: Revealed type is "builtins.list[django.template.base.Template]"
reveal_type(response.client) # N: Revealed type is "django.test.client.AsyncClient"
reveal_type(response.context) # N: Revealed type is "builtins.list[builtins.dict[builtins.str, Any]]"
response.json()
- case: request_factories
main: |
from django.test.client import RequestFactory, AsyncRequestFactory
factory = RequestFactory()
request = factory.get('foo')
reveal_type(request) # N: Revealed type is "django.core.handlers.wsgi.WSGIRequest*"
async_factory = AsyncRequestFactory()
async_request = async_factory.get('foo')
reveal_type(async_request) # N: Revealed type is "django.core.handlers.asgi.ASGIRequest*"

View File

@@ -9,4 +9,4 @@
reveal_type(resp.status_code) # N: Revealed type is "builtins.int"
# Attributes monkey-patched by test Client class:
resp.json()
reveal_type(resp.wsgi_request) # N: Revealed type is "django.core.handlers.wsgi.WSGIRequest*"
reveal_type(resp.wsgi_request) # N: Revealed type is "django.core.handlers.wsgi.WSGIRequest"

View File

@@ -0,0 +1,17 @@
# Regression test for #893
- case: annotated_should_not_iterfere
main: |
from dataclasses import dataclass
import sys
if sys.version_info < (3, 9):
from typing_extensions import Annotated
else:
from typing import Annotated
class IntegerType:
def __init__(self, min_value: int, max_value: int) -> None:
pass
@dataclass(unsafe_hash=True)
class RatingComposite:
max_value: Annotated[int, IntegerType(min_value=1, max_value=10)] = 5

View File

@@ -69,3 +69,41 @@
reveal_type(request.user) # N: Revealed type is "django.contrib.auth.models.User"
custom_settings: |
INSTALLED_APPS = ('django.contrib.contenttypes', 'django.contrib.auth')
- case: request_get_post
main: |
from django.http.request import HttpRequest
request = HttpRequest()
reveal_type(request) # N: Revealed type is "django.http.request._MutableHttpRequest"
reveal_type(request.GET) # N: Revealed type is "django.http.request.QueryDict"
request.GET['foo'] = 'bar'
def mk_request() -> HttpRequest:
return HttpRequest()
req = mk_request()
reveal_type(req) # N: Revealed type is "django.http.request.HttpRequest"
reveal_type(req.GET) # N: Revealed type is "django.http.request._ImmutableQueryDict"
req.GET.setdefault('foo', 'bar') # E: This QueryDict is immutable.
x = 1 # E: Statement is unreachable
# Will work after merging https://github.com/python/mypy/pull/12572
- case: request_get_post_unreachable
main: |
from django.http.request import HttpRequest
request = HttpRequest()
reveal_type(request) # N: Revealed type is "django.http.request._MutableHttpRequest"
reveal_type(request.GET) # N: Revealed type is "django.http.request.QueryDict"
request.GET['foo'] = 'bar'
def mk_request() -> HttpRequest:
return HttpRequest()
req = mk_request()
reveal_type(req) # N: Revealed type is "django.http.request.HttpRequest"
reveal_type(req.GET) # N: Revealed type is "django.http.request._ImmutableQueryDict"
req.GET['foo'] = 'bar' # E: This QueryDict is immutable.
x = 1 # E: Statement is unreachable
expect_fail: true

View File

@@ -61,3 +61,34 @@
class Article(models.Model):
pass
- case: generic_form_views_different_form_classes
main: |
from django.views.generic.edit import CreateView
from django import forms
from myapp.models import Article
class ArticleModelForm(forms.ModelForm[Article]):
class Meta:
model = Article
class SubArticleModelForm(ArticleModelForm):
pass
class AnotherArticleModelForm(forms.ModelForm[Article]):
class Meta:
model = Article
class MyCreateView(CreateView[Article, ArticleModelForm]):
def some(self) -> None:
reveal_type(self.get_form()) # N: Revealed type is "main.ArticleModelForm*"
reveal_type(self.get_form(SubArticleModelForm)) # N: Revealed type is "main.SubArticleModelForm"
reveal_type(self.get_form(AnotherArticleModelForm)) # N: Revealed type is "main.AnotherArticleModelForm" # E: Argument 1 to "get_form" of "FormMixin" has incompatible type "Type[AnotherArticleModelForm]"; expected "Optional[Type[ArticleModelForm]]"
installed_apps:
- myapp
files:
- path: myapp/__init__.py
- path: myapp/models.py
content: |
from django.db import models
class Article(models.Model):
pass