Large update (#909)

* Make module declaration precise.

* Make settings match real file.

* Replace `include` with import.

* Make types more specific.

* Replace `WSGIRequest` with `HttpRequest` where possible.

* Replace all `OrderedDict` occurrences with plain `Dict` (it is not used in Django 3.2 and later)

* Add fake datastructures for convenience: _PropertyDescriptor and _ListOrTuple now can live here. Added _IndexableCollection (often useful as alias for 'sequence or queryset')

* Actualize other datastructures.

* Rework MultiValueDict to reflect the fact that some methods can return empty list instead of value.

* Deprecate SafeText in favor of SafeString.

* Minor improvements to utils

* Disallow using str in TimeFormat and DateFormat, drop removed fmt `B`

* Do not let classproperty expect classmethod, make return value covariant.

* Sync with real file.

* Improve types for timezone.

* Sync deprecated, new and removed features in translation utils.

* Drop removed files, sync huge deprecations.

* Fix incompatible decorators (properties, contextmanagers)

* Rework pagination.

* Sync validators with real code. Add _ValidatorCallable for any external use (field validation etc.)

* Add shared type definitions (for fields of both forms and models). Actualize model fields. Mark keyword-only args explicitly in stubs (where code uses **kwargs). Disallow bytes for verbose_name.

* Make all checks return Sequence[CheckMessage] or subclass to be covariant.

* Add bidirectional references between backend.base and other files. Replace some Any's with specific types.

* Actualize db.migrations: remove removed methods, replace "None" annotations in wrong places, improve some wrong annotations.

* Actualize db.utils to match real file.

* Replace FileResponse and TemplateResponse with HttpResponse(Base) where needed: at least HttpResponseNotModified/HttpResponseRedirect can be returned instead of it, so annotation was wrong.

* Replace Any in forms where possible. Actualize class bases and method arguments.

* Improve typing of serializers.

* Actualize views, rename variable bound to Model to _M for consistency.

* Make types of file-related code consistent. Disallow using bytes as path, because many methods expect str-only paths. Make File inherit from IO[AnyStr] instead of IO[Any]: it makes impossible to instantiate file of union type, but allows precise types for some methods.

* Minor improvements: stop using None as annotation in wrong places, replace obvious Any's with precise types, actualize methods (missing/renamed/signature changed).

* Allow less specific containers, replace Any's with specific types.

* Improve types for requests and responses.

* Use AbstractBaseUser instead of User in auth.

* Use broader type for permission_required

* Use wider container types. Add 'type: ignore' to avoid issues with mypy.stubtest.

* Disallow using backend class as argument (it is passed to import_string).

* Add required methods to PasseordValidator.

* Allow using Path instance as argument.

* Actualize methods.

* Add 'type: ignore' to avoid issues with mypy.stubtest.

* Replace Any's with specific types and BaseForm with ModelForm.

* Actualize contrib.postgres

* Remove render_to_response, add 'get_absolute_url' to corresponding protocol.

* Actualize signers.

* Use precise types for handlers. Disallow str as stream type for LimitedStream.

* Exact types for ValidationError

* Replace wrong used Union with Sequence.

* Actualize static handlers.

* More specific types for admin. Fixes #874.

* Improve types and replace 'Tags' with str (it isn't Enum, so annotation was wrong).

* Replace Any with specific types, actualize signatures.

* Add async variants of handlers and clients. Use fake class to distinguish between request types in RequestFactory and AsyncRequestFactory.

* Fix signature, minor improvements.

* Actualize signatures and class names, replace Any with more specific types.

* Fix signature.

* Add some missing methods to Collector

* Combinable rarely returns Self type: almost always it's CombinedExpression.

* No Random in source anymore.

* Drop removed SimpleCol.

* Replace _OutputField with Field: nothing in docs about strings.

* Introduce reusable types, add missing methods. Remove strange types (probably created by stubgen). Remove RawQuery from Compiler: it obviously doesn't work with RawQuery.

* Use literal constants.

* Actualize base classes.

* Callable is not accepted by get_field.

* Add precise types.

* Use property and broader containers where possible. Add missing methods.

* Actualize indexes.

* More specific types for signals.

* Fix signatures, drop missing methods.

* Actualize window functions to match source.

* Actualize text functions, add missing methods, use type aliases for consistency.

* Add missing property decorators, methods and attributes. Use type aliases. Remove absent YearComparisonLookup and any SafeText references (they aren't related to lookups at all).

* Use bound TypeVar, mark all BuiltinLookup descendants as generic explicitly. Remove strange Union from Lookup.__init__

* Apply type alias, fix base class and argument name.

* Actualize BaseExpression methods.

* Fix imports.

* Add missing class and fix incompatible bases.

* Use same types in __init__ and attribute.

* OrderBy accepts F or Expression.

* Non-expressions are converted to Values.

* Add missing attributes.

* Add missing methods, fix 'None' argument type.

* Define properties where possible, remove 'None' argument annotations, remove inadequate type in make_immutable_fields_list.

* Remove absent QueryWrapper. Replace some Any with precise types.

* Fix wrong types and actualize signatures. Deny ManagerDescriptor.__get__ on model instances.

* Use more specific types.

* Arity can be None in subclasses.

* Reformat with black

* Make DeletionMixin generic.

* Fix wrong type variable in _RequestFactory.

* Fix variable name in signature.

* Disallow returning None from Form.clean()

* Allow again returning None from Form.clean

* Drop some unused imports.

* Add tests for MultiValueDict.

* Add tests for utils.timezone.

* Fix #834.

* Add more files to import_all test

* Allow None for `context_object_name`

* Fix CI

* Fix test to work on python 3.8
This commit is contained in:
sterliakov
2022-04-04 00:41:41 +03:00
committed by GitHub
parent dc4c0d9ee4
commit f69e0639c7
322 changed files with 5740 additions and 3465 deletions

View File

@@ -3,7 +3,7 @@
- case: test_full_admin
main: |
from django.contrib import admin
from django.forms import Form, Textarea
from django.forms import Form, ModelForm, Textarea
from django.db import models
from django.core.paginator import Paginator
from django.contrib.admin.sites import AdminSite
@@ -30,7 +30,7 @@
(None, {"fields": ["a", "b"]}),
("group", {"fields": ("c",), "classes": ("a",), "description": "foo"}),
]
form = Form
form = ModelForm
filter_vertical = ("fields",)
filter_horizontal = ("plenty", "of", "fields")
radio_fields = {
@@ -48,7 +48,7 @@
# ModelAdmin
list_display = ("pk",)
list_display_links = ("str",)
list_filter = ("str", admin.SimpleListFilter, ("str", admin.SimpleListFilter))
list_filter = ("str", admin.SimpleListFilter, ("str", admin.FieldListFilter))
list_select_related = True
list_per_page = 1
list_max_show_all = 2

View File

@@ -2,38 +2,38 @@
main: |
from django.contrib.staticfiles import finders
reveal_type(finders.find("filepath")) # N: Revealed type is "Union[builtins.str, builtins.bytes, os.PathLike[Any], None]"
reveal_type(finders.find("filepath")) # N: Revealed type is "Union[builtins.str, os.PathLike[builtins.str], None]"
for finder in finders.get_finders():
reveal_type(finder.find("filepath")) # N: Revealed type is "Union[builtins.str, builtins.bytes, os.PathLike[Any], None]"
reveal_type(finder.find("filepath")) # N: Revealed type is "Union[builtins.str, os.PathLike[builtins.str], None]"
reveal_type(finders.FileSystemFinder().find("filepath")) # N: Revealed type is "Union[builtins.str, builtins.bytes, os.PathLike[Any], None]"
reveal_type(finders.AppDirectoriesFinder().find("filepath")) # N: Revealed type is "Union[builtins.str, builtins.bytes, os.PathLike[Any], None]"
reveal_type(finders.DefaultStorageFinder().find("filepath")) # N: Revealed type is "Union[builtins.str, builtins.bytes, os.PathLike[Any], None]"
reveal_type(finders.FileSystemFinder().find("filepath")) # N: Revealed type is "Union[builtins.str, os.PathLike[builtins.str], None]"
reveal_type(finders.AppDirectoriesFinder().find("filepath")) # N: Revealed type is "Union[builtins.str, os.PathLike[builtins.str], None]"
reveal_type(finders.DefaultStorageFinder().find("filepath")) # N: Revealed type is "Union[builtins.str, os.PathLike[builtins.str], None]"
- case: test_find_all
main: |
from django.contrib.staticfiles import finders
reveal_type(finders.find("filepath", all=True)) # N: Revealed type is "builtins.list[Union[builtins.str, builtins.bytes, os.PathLike[Any]]]"
reveal_type(finders.find("filepath", all=True)) # N: Revealed type is "builtins.list[Union[builtins.str, os.PathLike[builtins.str]]]"
for finder in finders.get_finders():
reveal_type(finder.find("filepath", all=True)) # N: Revealed type is "builtins.list[Union[builtins.str, builtins.bytes, os.PathLike[Any]]]"
reveal_type(finder.find("filepath", all=True)) # N: Revealed type is "builtins.list[Union[builtins.str, os.PathLike[builtins.str]]]"
reveal_type(finders.FileSystemFinder().find("filepath", all=True)) # N: Revealed type is "builtins.list[Union[builtins.str, builtins.bytes, os.PathLike[Any]]]"
reveal_type(finders.AppDirectoriesFinder().find("filepath", all=True)) # N: Revealed type is "builtins.list[Union[builtins.str, builtins.bytes, os.PathLike[Any]]]"
reveal_type(finders.DefaultStorageFinder().find("filepath", all=True)) # N: Revealed type is "builtins.list[Union[builtins.str, builtins.bytes, os.PathLike[Any]]]"
reveal_type(finders.FileSystemFinder().find("filepath", all=True)) # N: Revealed type is "builtins.list[Union[builtins.str, os.PathLike[builtins.str]]]"
reveal_type(finders.AppDirectoriesFinder().find("filepath", all=True)) # N: Revealed type is "builtins.list[Union[builtins.str, os.PathLike[builtins.str]]]"
reveal_type(finders.DefaultStorageFinder().find("filepath", all=True)) # N: Revealed type is "builtins.list[Union[builtins.str, os.PathLike[builtins.str]]]"
- case: test_file_system_finder # test methods *only* on FileSystemFinder
main: |
from django.contrib.staticfiles.finders import FileSystemFinder
finder = FileSystemFinder()
reveal_type(finder.find_location(".", "filepath")) # N: Revealed type is "Union[builtins.str, builtins.bytes, os.PathLike[Any], None]"
reveal_type(finder.find_location(".", "filepath")) # N: Revealed type is "Union[builtins.str, os.PathLike[builtins.str], None]"
- case: test_app_directories_finder # test methods *only* on AppDirectoriesFinder
main: |
from django.contrib.staticfiles.finders import AppDirectoriesFinder
finder = AppDirectoriesFinder()
reveal_type(finder.find_in_app("app", "filepath")) # N: Revealed type is "Union[builtins.str, builtins.bytes, os.PathLike[Any], None]"
reveal_type(finder.find_in_app("app", "filepath")) # N: Revealed type is "Union[builtins.str, os.PathLike[builtins.str], None]"

View File

@@ -7,7 +7,7 @@
- case: raw_connections
main: |
from django.db import connections
reveal_type(connections["test"]) # N: Revealed type is "django.db.backends.base.base.BaseDatabaseWrapper"
reveal_type(connections["test"]) # N: Revealed type is "django.db.backends.base.base.BaseDatabaseWrapper*"
for connection in connections.all():
with connection.cursor() as cursor:
reveal_type(cursor) # N: Revealed type is "django.db.backends.utils.CursorWrapper"

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

@@ -48,15 +48,15 @@
main: |
from django.utils.safestring import mark_safe
s = 'hello'
reveal_type(mark_safe(s)) # N: Revealed type is "django.utils.safestring.SafeText"
reveal_type(mark_safe(s) + mark_safe(s)) # N: Revealed type is "django.utils.safestring.SafeText"
reveal_type(mark_safe(s)) # N: Revealed type is "django.utils.safestring.SafeString"
reveal_type(mark_safe(s) + mark_safe(s)) # N: Revealed type is "django.utils.safestring.SafeString"
reveal_type(s + mark_safe(s)) # N: Revealed type is "builtins.str"
s += mark_safe(s)
reveal_type(s) # N: Revealed type is "builtins.str"
ms = mark_safe(s)
ms += mark_safe(s)
reveal_type(ms) # N: Revealed type is "django.utils.safestring.SafeText"
reveal_type(ms) # N: Revealed type is "django.utils.safestring.SafeString"
@mark_safe
def func(s: str) -> str:

View File

@@ -104,12 +104,20 @@
import django.contrib.postgres.fields.jsonb
import django.contrib.postgres.fields.mixins
import django.contrib.postgres.fields.ranges
import django.contrib.postgres.fields.utils
import django.contrib.postgres.forms
import django.contrib.postgres.forms.array
import django.contrib.postgres.forms.hstore
import django.contrib.postgres.forms.jsonb
import django.contrib.postgres.forms.ranges
import django.contrib.postgres.constraints
import django.contrib.postgres.functions
import django.contrib.postgres.indexes
import django.contrib.postgres.lookups
import django.contrib.postgres.operations
import django.contrib.postgres.search
import django.contrib.postgres.signals
import django.contrib.postgres.utils
import django.contrib.postgres.validators
import django.contrib.redirects
import django.contrib.redirects.middleware
@@ -157,6 +165,7 @@
import django.contrib.syndication
import django.contrib.syndication.views
import django.core.cache.backends
import django.core.asgi
import django.core.cache.backends.base
import django.core.cache.backends.db
import django.core.cache.backends.dummy
@@ -188,6 +197,7 @@
import django.core.files.uploadhandler
import django.core.files.utils
import django.core.handlers
import django.core.handlers.asgi
import django.core.handlers.base
import django.core.handlers.exception
import django.core.handlers.wsgi
@@ -210,7 +220,10 @@
import django.core.serializers
import django.core.serializers.base
import django.core.serializers.json
import django.core.serializers.jsonl
import django.core.serializers.python
import django.core.serializers.pyyaml
import django.core.serializers.xml_serializer
import django.core.servers
import django.core.servers.basehttp
import django.core.signals
@@ -379,9 +392,11 @@
import django.urls.utils
import django.utils._os
import django.utils.archive
import django.utils.asyncio
import django.utils.autoreload
import django.utils.baseconv
import django.utils.cache
import django.utils.connection
import django.utils.crypto
import django.utils.datastructures
import django.utils.dateformat
@@ -409,7 +424,6 @@
import django.utils.numberformat
import django.utils.regex_helper
import django.utils.safestring
import django.utils.six
import django.utils.termcolors
import django.utils.text
import django.utils.timesince

View File

@@ -0,0 +1,48 @@
- case: multivaluedict
main: |
from django.utils.datastructures import MultiValueDict
from typing import Dict, List, Tuple, Union
# check constructors
var1 = MultiValueDict() # E: Need type annotation for "var1"
d2: Dict[str, List[Union[str, int]]] = {'foo': ['Foo'], 'bar': [2, 3]}
var2 = MultiValueDict(d2)
d3: Tuple[Tuple[str, List[Union[str, int]]], ...] = (('foo', ['Foo']), ('bar', [2, 3]))
var3 = MultiValueDict(d3)
reveal_type(var1) # N: Revealed type is "django.utils.datastructures.MultiValueDict[Any, Any]"
reveal_type(var2) # N: Revealed type is "django.utils.datastructures.MultiValueDict[builtins.str*, Union[builtins.str, builtins.int]]"
reveal_type(var3) # N: Revealed type is "django.utils.datastructures.MultiValueDict[builtins.str*, Union[builtins.str, builtins.int]]"
# __getitem__, get, getlist (with proofs)
d = MultiValueDict({'foo': ['Foo']})
d.setlist('bar', [])
# actually 'Foo'
reveal_type(d['foo']) # N: Revealed type is "Union[builtins.str*, builtins.list[builtins.object]]"
# actually []
reveal_type(d['bar']) # N: Revealed type is "Union[builtins.str*, builtins.list[builtins.object]]"
# actually None
reveal_type(d.get('bar')) # N: Revealed type is "Union[builtins.str*, None]"
# actually 1
reveal_type(d.get('bar', 1)) # N: Revealed type is "Union[builtins.str, builtins.int*]"
# actually []
reveal_type(d.getlist('bar')) # N: Revealed type is "builtins.list[builtins.str]"
# actually []
reveal_type(d.getlist('bar', [1])) # N: Revealed type is "Union[builtins.list[builtins.str], builtins.list*[builtins.int*]]"
# actually True (note that default can be not a list)
reveal_type(d.getlist('baz', True)) # N: Revealed type is "Union[builtins.list[builtins.str], builtins.bool*]"
# setters
reveal_type(d.setlistdefault('baz')) # N: Revealed type is "builtins.list[builtins.str*]"
d.setlistdefault('baz', [1]) # E: List item 0 has incompatible type "int"; expected "str"
reveal_type(d.setlistdefault('baz', [])) # N: Revealed type is "builtins.list[builtins.str*]"
d.appendlist('baz', 'Baz')
d.appendlist('baz', 1) # E: Argument 2 to "appendlist" of "MultiValueDict" has incompatible type "int"; expected "str"
# iterators
# actually [('foo', 'Foo'), ('bar', [])]
reveal_type(list(d.items())) # N: Revealed type is "builtins.list[Tuple[builtins.str*, Union[builtins.str*, builtins.list[builtins.object]]]]"
reveal_type(list(d.keys())) # N: Revealed type is "builtins.list[builtins.str*]"
# actually ['Foo', []]
reveal_type(list(d.values())) # N: Revealed type is "builtins.list[Union[builtins.str*, builtins.list[builtins.object]]]"
# actually {'foo': 'Foo', 'bar': []}
reveal_type(d.dict()) # N: Revealed type is "builtins.dict[builtins.str*, Union[builtins.str*, builtins.list[builtins.object]]]"

View File

@@ -0,0 +1,14 @@
- case: force_bytes_or_str
main: |
from django.utils.encoding import force_bytes, force_str
class S(str):
pass
reveal_type(force_bytes(123)) # N: Revealed type is "builtins.bytes"
reveal_type(force_bytes(123, strings_only=True)) # N: Revealed type is "builtins.int*"
reveal_type(force_str(123)) # N: Revealed type is "builtins.str"
reveal_type(force_str(123, strings_only=True)) # N: Revealed type is "builtins.int*"
reveal_type(force_str('foo')) # N: Revealed type is "builtins.str*"
reveal_type(force_str('foo', strings_only=True)) # N: Revealed type is "builtins.str*"
reveal_type(force_str(S('foo'), strings_only=True)) # N: Revealed type is "main.S*"

View File

@@ -0,0 +1,30 @@
- case: is_naive_correct
main: |
from django.utils.timezone import is_naive
from datetime import date, time, datetime
reveal_type(is_naive(date(2020, 1, 1)))
reveal_type(is_naive(datetime(2020, 1, 1)))
reveal_type(is_naive(time()))
out: |
main:3: error: No overload variant of "is_naive" matches argument type "date"
main:3: note: Possible overload variants:
main:3: note: def is_naive(value: time) -> Literal[True]
main:3: note: def is_naive(value: datetime) -> bool
main:3: note: Revealed type is "Any"
main:4: note: Revealed type is "builtins.bool"
main:5: note: Revealed type is "Literal[True]"
- case: is_aware_correct
main: |
from django.utils.timezone import is_aware
from datetime import date, time, datetime
reveal_type(is_aware(date(2020, 1, 1)))
reveal_type(is_aware(datetime(2020, 1, 1)))
reveal_type(is_aware(time()))
out: |
main:3: error: No overload variant of "is_aware" matches argument type "date"
main:3: note: Possible overload variants:
main:3: note: def is_aware(value: time) -> Literal[False]
main:3: note: def is_aware(value: datetime) -> bool
main:3: note: Revealed type is "Any"
main:4: note: Revealed type is "builtins.bool"
main:5: note: Revealed type is "Literal[False]"

View File

@@ -50,6 +50,6 @@
...
out: |
main:7: error: Incompatible types in assignment (expression has type "Type[MyModel]", base class "SingleObjectMixin" defined the type as "Type[Other]")
main:8: error: Incompatible types in assignment (expression has type "_QuerySet[MyModel, MyModel]", base class "SingleObjectMixin" defined the type as "_QuerySet[Other, Other]")
main:8: error: Incompatible types in assignment (expression has type "_QuerySet[MyModel, MyModel]", base class "SingleObjectMixin" defined the type as "Optional[_QuerySet[Other, Other]]")
main:10: error: Return type "_QuerySet[MyModel, MyModel]" of "get_queryset" incompatible with return type "_QuerySet[Other, Other]" in supertype "SingleObjectMixin"
main:12: error: Incompatible return value type (got "_QuerySet[Other, Other]", expected "_QuerySet[MyModel, MyModel]")

View File

@@ -48,5 +48,5 @@
...
out: |
main:7: error: Incompatible types in assignment (expression has type "Type[MyModel]", base class "MultipleObjectMixin" defined the type as "Optional[Type[Other]]")
main:8: error: Incompatible types in assignment (expression has type "_QuerySet[MyModel, MyModel]", base class "MultipleObjectMixin" defined the type as "Optional[_QuerySet[Other, Other]]")
main:10: error: Return type "_QuerySet[MyModel, MyModel]" of "get_queryset" incompatible with return type "_QuerySet[Other, Other]" in supertype "MultipleObjectMixin"
main:8: error: Incompatible types in assignment (expression has type "_QuerySet[MyModel, MyModel]", base class "MultipleObjectMixin" defined the type as "Optional[_SupportsPagination[Other]]")
main:10: error: Return type "_QuerySet[MyModel, MyModel]" of "get_queryset" incompatible with return type "_SupportsPagination[Other]" in supertype "MultipleObjectMixin"