Skip to content

Update mypy to 1.17.0 #2744

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jul 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions django-stubs/core/management/commands/loaddata.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ class SingleZipReader(zipfile.ZipFile):
# Incompatible override
# zipfile.ZipFile.read(
# self,
# name: typing.Union[typing.Text, zipfile.ZipInfo],
# pwd: Optional[bytes] = ...,
# name: typing.Text | zipfile.ZipInfo,
# pwd: bytes | None = ...,
# ) -> bytes: ...
def read(self) -> bytes: ... # type: ignore[override]

Expand Down
2 changes: 1 addition & 1 deletion django-stubs/db/models/query_utils.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class Q(tree.Node):
conditional: bool
def __init__(self, *args: Any, **kwargs: Any) -> None: ...
# Fake signature, the real is
# def __init__(self, *args: Any, _connector: Optional[Any] = ..., _negated: bool = ..., **kwargs: Any) -> None: ...
# def __init__(self, *args: Any, _connector: Any | None = ..., _negated: bool = ..., **kwargs: Any) -> None: ...
def __or__(self, other: Q) -> Q: ...
def __and__(self, other: Q) -> Q: ...
def __xor__(self, other: Q) -> Q: ...
Expand Down
4 changes: 0 additions & 4 deletions mypy.ini
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,6 @@ strict_bytes = true
local_partial_types = true
warn_unreachable = true

# TODO: update our output assertions to match a new syntax
force_uppercase_builtins = true
force_union_syntax = true

disable_error_code = empty-body
enable_error_code = deprecated

Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ dependencies = [
]

[project.optional-dependencies]
compatible-mypy = ["mypy>=1.13,<1.17"]
compatible-mypy = ["mypy>=1.13,<1.18"]
oracle = ["oracledb"]
redis = ["redis", "types-redis"]

Expand All @@ -59,7 +59,7 @@ tests = [
"jinja2==3.1.6",
"pyyaml==6.0.2",
# typing:
"mypy==1.16.0",
"mypy==1.17.0",
"django-stubs[compatible-mypy,oracle,redis]",
]
pyright = ["pyright==1.1.401"]
Expand Down
6 changes: 3 additions & 3 deletions tests/typecheck/contrib/admin/test_options.yml
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@

class A(admin.ModelAdmin):
formfield_overrides = {
"not a field": { # E: Dict entry 0 has incompatible type "str": "Dict[str, Any]"; expected "Type[Field[Any, Any]]": "Mapping[str, Any]" [dict-item]
"not a field": { # E: Dict entry 0 has incompatible type "str": "dict[str, Any]"; expected "type[Field[Any, Any]]": "Mapping[str, Any]" [dict-item]
"widget": Textarea
}
}
Expand All @@ -152,7 +152,7 @@
pass

class A(admin.ModelAdmin[MyModel]):
actions = [an_action] # E: List item 0 has incompatible type "Callable[[None], None]"; expected "Union[Callable[[A, HttpRequest, QuerySet[MyModel, MyModel]], Optional[HttpResponseBase]], str]" [list-item]
actions = [an_action] # E: List item 0 has incompatible type "Callable[[None], None]"; expected "Callable[[A, HttpRequest, QuerySet[MyModel, MyModel]], HttpResponseBase | None] | str" [list-item]
- case: errors_for_invalid_model_admin_generic
main: |
from django.contrib.admin import ModelAdmin
Expand All @@ -162,4 +162,4 @@
pass

class A(ModelAdmin[TestModel]):
model = int # E: Incompatible types in assignment (expression has type "Type[int]", base class "ModelAdmin" defined the type as "Type[TestModel]") [assignment]
model = int # E: Incompatible types in assignment (expression has type "type[int]", base class "ModelAdmin" defined the type as "type[TestModel]") [assignment]
45 changes: 21 additions & 24 deletions tests/typecheck/contrib/auth/test_auth.yml
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
- case: test_objects_using_auth_user_model_picks_up_configured_type
main: |
from typing import Union
from django.contrib.auth import authenticate, aauthenticate, get_user, get_user_model, login
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth.decorators import user_passes_test
from django.contrib.auth.models import AnonymousUser
from django.http import HttpRequest, HttpResponse
from myapp.models import MyUser

reveal_type(authenticate()) # N: Revealed type is "Union[myapp.models.MyUser, None]"
reveal_type(authenticate()) # N: Revealed type is "myapp.models.MyUser | None"
async def f() -> None:
reveal_type(await aauthenticate()) # N: Revealed type is "Union[myapp.models.MyUser, None]"
reveal_type(get_user_model()) # N: Revealed type is "Type[myapp.models.MyUser]"
reveal_type(login) # N: Revealed type is "def (request: django.http.request.HttpRequest, user: Union[myapp.models.MyUser, None], backend: Union[Type[django.contrib.auth.backends.BaseBackend], builtins.str, None] =)"
reveal_type(get_user) # N: Revealed type is "def (request: Union[django.http.request.HttpRequest, django.test.client.Client]) -> Union[myapp.models.MyUser, django.contrib.auth.models.AnonymousUser]"
reveal_type(ModelBackend().authenticate(None)) # N: Revealed type is "Union[myapp.models.MyUser, None]"
reveal_type(await aauthenticate()) # N: Revealed type is "myapp.models.MyUser | None"
reveal_type(get_user_model()) # N: Revealed type is "type[myapp.models.MyUser]"
reveal_type(login) # N: Revealed type is "def (request: django.http.request.HttpRequest, user: myapp.models.MyUser | None, backend: type[django.contrib.auth.backends.BaseBackend] | builtins.str | None =)"
reveal_type(get_user) # N: Revealed type is "def (request: django.http.request.HttpRequest | django.test.client.Client) -> myapp.models.MyUser | django.contrib.auth.models.AnonymousUser"
reveal_type(ModelBackend().authenticate(None)) # N: Revealed type is "myapp.models.MyUser | None"

def check_user(user: Union[MyUser, AnonymousUser]) -> bool: return True
def check_user(user: MyUser | AnonymousUser) -> bool: return True
@user_passes_test(check_user)
def view(request: HttpRequest) -> HttpResponse: ...
custom_settings: |
Expand All @@ -33,22 +32,21 @@

- case: test_objects_using_auth_user_model_uses_builtin_auth_user_per_default
main: |
from typing import Union
from django.contrib.auth import authenticate, aauthenticate, get_user, get_user_model, login
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth.decorators import user_passes_test
from django.contrib.auth.models import AnonymousUser, User
from django.http import HttpRequest, HttpResponse

reveal_type(authenticate()) # N: Revealed type is "Union[django.contrib.auth.models.User, None]"
reveal_type(authenticate()) # N: Revealed type is "django.contrib.auth.models.User | None"
async def f() -> None:
reveal_type(await aauthenticate()) # N: Revealed type is "Union[django.contrib.auth.models.User, None]"
reveal_type(get_user_model()) # N: Revealed type is "Type[django.contrib.auth.models.User]"
reveal_type(login) # N: Revealed type is "def (request: django.http.request.HttpRequest, user: Union[django.contrib.auth.models.User, None], backend: Union[Type[django.contrib.auth.backends.BaseBackend], builtins.str, None] =)"
reveal_type(get_user) # N: Revealed type is "def (request: Union[django.http.request.HttpRequest, django.test.client.Client]) -> Union[django.contrib.auth.models.User, django.contrib.auth.models.AnonymousUser]"
reveal_type(ModelBackend().authenticate(None)) # N: Revealed type is "Union[django.contrib.auth.models.User, None]"
reveal_type(await aauthenticate()) # N: Revealed type is "django.contrib.auth.models.User | None"
reveal_type(get_user_model()) # N: Revealed type is "type[django.contrib.auth.models.User]"
reveal_type(login) # N: Revealed type is "def (request: django.http.request.HttpRequest, user: django.contrib.auth.models.User | None, backend: type[django.contrib.auth.backends.BaseBackend] | builtins.str | None =)"
reveal_type(get_user) # N: Revealed type is "def (request: django.http.request.HttpRequest | django.test.client.Client) -> django.contrib.auth.models.User | django.contrib.auth.models.AnonymousUser"
reveal_type(ModelBackend().authenticate(None)) # N: Revealed type is "django.contrib.auth.models.User | None"

def check_user(user: Union[User, AnonymousUser]) -> bool: return True
def check_user(user: User | AnonymousUser) -> bool: return True
@user_passes_test(check_user)
def view(request: HttpRequest) -> HttpResponse: ...
custom_settings: |
Expand All @@ -64,23 +62,22 @@

- case: test_objects_for_auth_user_model_returns_stub_types_when_contrib_auth_is_not_installed
main: |
from typing import Union
from django.contrib.auth import authenticate, aauthenticate, get_user, get_user_model, login
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth.base_user import AbstractBaseUser
from django.contrib.auth.decorators import user_passes_test
from django.contrib.auth.models import AnonymousUser
from django.http import HttpRequest, HttpResponse

reveal_type(authenticate()) # N: Revealed type is "Union[django.contrib.auth.base_user.AbstractBaseUser, None]"
reveal_type(authenticate()) # N: Revealed type is "django.contrib.auth.base_user.AbstractBaseUser | None"
async def f() -> None:
reveal_type(await aauthenticate()) # N: Revealed type is "Union[django.contrib.auth.base_user.AbstractBaseUser, None]"
reveal_type(get_user_model()) # N: Revealed type is "Type[django.contrib.auth.base_user.AbstractBaseUser]"
reveal_type(login) # N: Revealed type is "def (request: django.http.request.HttpRequest, user: Union[django.contrib.auth.base_user.AbstractBaseUser, None], backend: Union[Type[django.contrib.auth.backends.BaseBackend], builtins.str, None] =)"
reveal_type(get_user) # N: Revealed type is "def (request: Union[django.http.request.HttpRequest, django.test.client.Client]) -> Union[django.contrib.auth.base_user.AbstractBaseUser, django.contrib.auth.models.AnonymousUser]"
reveal_type(ModelBackend().authenticate(None)) # N: Revealed type is "Union[django.contrib.auth.base_user.AbstractBaseUser, None]"
reveal_type(await aauthenticate()) # N: Revealed type is "django.contrib.auth.base_user.AbstractBaseUser | None"
reveal_type(get_user_model()) # N: Revealed type is "type[django.contrib.auth.base_user.AbstractBaseUser]"
reveal_type(login) # N: Revealed type is "def (request: django.http.request.HttpRequest, user: django.contrib.auth.base_user.AbstractBaseUser | None, backend: type[django.contrib.auth.backends.BaseBackend] | builtins.str | None =)"
reveal_type(get_user) # N: Revealed type is "def (request: django.http.request.HttpRequest | django.test.client.Client) -> django.contrib.auth.base_user.AbstractBaseUser | django.contrib.auth.models.AnonymousUser"
reveal_type(ModelBackend().authenticate(None)) # N: Revealed type is "django.contrib.auth.base_user.AbstractBaseUser | None"

def check_user(user: Union[AbstractBaseUser, AnonymousUser]) -> bool: return True
def check_user(user: AbstractBaseUser | AnonymousUser) -> bool: return True
@user_passes_test(check_user)
def view(request: HttpRequest) -> HttpResponse: ...
custom_settings: |
Expand Down
2 changes: 1 addition & 1 deletion tests/typecheck/contrib/auth/test_decorators.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
main: |
from django.http import HttpRequest, HttpResponse
from django.contrib.auth.decorators import user_passes_test
@user_passes_test # E: Argument 1 to "user_passes_test" has incompatible type "Callable[[HttpRequest], HttpResponse]"; expected "Callable[[Union[AbstractBaseUser, AnonymousUser]], bool]" [arg-type]
@user_passes_test # E: Argument 1 to "user_passes_test" has incompatible type "Callable[[HttpRequest], HttpResponse]"; expected "Callable[[AbstractBaseUser | AnonymousUser], bool]" [arg-type]
def view_func(request: HttpRequest) -> HttpResponse: ...
- case: permission_required
main: |
Expand Down
3 changes: 1 addition & 2 deletions tests/typecheck/contrib/auth/test_misc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
get_user(Client())
- case: test_user_fields
main: |
from typing import Union
from django.contrib.auth.models import AnonymousUser, User

anonymous: AnonymousUser
Expand All @@ -33,7 +32,7 @@
user_is_superuser: bool = user.is_superuser
user_is_authenticated: bool = user.is_authenticated

union: Union[User, AnonymousUser]
union: User | AnonymousUser
union_is_staff: bool = union.is_staff
union_is_active: bool = union.is_active
union_is_superuser: bool = union.is_superuser
Expand Down
2 changes: 1 addition & 1 deletion tests/typecheck/contrib/contenttypes/test_models.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
reveal_type(c.app_label) # N: Revealed type is "builtins.str"
reveal_type(c.model) # N: Revealed type is "builtins.str"

ContentType.objects.create(app_label=[]) # E: Incompatible type for "app_label" of "ContentType" (got "List[Any]", expected "Union[str, int, Combinable]") [misc]
ContentType.objects.create(app_label=[]) # E: Incompatible type for "app_label" of "ContentType" (got "list[Any]", expected "str | int | Combinable") [misc]

custom_settings: |
INSTALLED_APPS = ("django.contrib.contenttypes",)
7 changes: 3 additions & 4 deletions tests/typecheck/contrib/postgres/test_fields.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
- case: union_combinable_reduced_to_non_union
main: |
from typing import List
from myapp.models import MyModel
array_val: List[int] = [1]
MyModel(array=array_val) # E: Incompatible type for "array" of "MyModel" (got "List[int]", expected "Union[Sequence[str], Combinable]") [misc]
array_val: list[int] = [1]
MyModel(array=array_val) # E: Incompatible type for "array" of "MyModel" (got "list[int]", expected "Sequence[str] | Combinable") [misc]
non_init = MyModel()
non_init.array = array_val # E: Incompatible types in assignment (expression has type "List[int]", variable has type "Union[Sequence[str], Combinable]") [assignment]
non_init.array = array_val # E: Incompatible types in assignment (expression has type "list[int]", variable has type "Sequence[str] | Combinable") [assignment]
installed_apps:
- myapp
files:
Expand Down
11 changes: 5 additions & 6 deletions tests/typecheck/contrib/sitemaps/test_generic_sitemap.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,12 @@
),
]
out: |
main:24: error: Return type "str" of "items" incompatible with return type "Iterable[Offer]" in supertype "Sitemap" [override]
main:26: error: Return type "int" of "location" incompatible with return type "str" in supertype "Sitemap" [override]
main:26: error: Argument 1 of "location" is incompatible with supertype "Sitemap"; supertype defines the argument type as "Offer" [override]
main:24: error: Return type "str" of "items" incompatible with return type "Iterable[Offer]" in supertype "django.contrib.sitemaps.Sitemap" [override]
main:26: error: Return type "int" of "location" incompatible with return type "str" in supertype "django.contrib.sitemaps.Sitemap" [override]
main:26: error: Argument 1 of "location" is incompatible with supertype "django.contrib.sitemaps.Sitemap"; supertype defines the argument type as "Offer" [override]
main:26: note: This violates the Liskov substitution principle
main:26: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides
main:40: error: Argument 1 to "GenericSitemap" has incompatible type "Dict[str, List[int]]"; expected "Mapping[str, Union[datetime, QuerySet[Offer, Offer], str]]" [arg-type]
main:40: error: Argument 1 to "GenericSitemap" has incompatible type "dict[str, list[int]]"; expected "Mapping[str, datetime | QuerySet[Offer, Offer] | str]" [arg-type]

installed_apps:
- myapp
Expand All @@ -66,14 +66,13 @@
- case: test_items_string_sequence
main: |
from django.contrib.sitemaps import Sitemap
from typing import List
from django.urls import reverse

class StaticViewSitemap(Sitemap[str]):
priority = 1
changefreq = "always"

def items(self) -> List[str]:
def items(self) -> list[str]:
return ["home", "about", "contact", "recommendations", "privacy-policy", "blog"]

def location(self, item: str) -> str:
Expand Down
14 changes: 7 additions & 7 deletions tests/typecheck/contrib/staticfiles/test_finders.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
main: |
from django.contrib.staticfiles import finders

reveal_type(finders.find("filepath")) # N: Revealed type is "Union[builtins.str, None]"
reveal_type(finders.find("filepath")) # N: Revealed type is "builtins.str | None"

for finder in finders.get_finders():
reveal_type(finder.find("filepath")) # N: Revealed type is "Union[builtins.str, None]"
reveal_type(finder.find("filepath")) # N: Revealed type is "builtins.str | None"

reveal_type(finders.FileSystemFinder().find("filepath")) # N: Revealed type is "Union[builtins.str, None]"
reveal_type(finders.AppDirectoriesFinder().find("filepath")) # N: Revealed type is "Union[builtins.str, None]"
reveal_type(finders.DefaultStorageFinder().find("filepath")) # N: Revealed type is "Union[builtins.str, None]"
reveal_type(finders.FileSystemFinder().find("filepath")) # N: Revealed type is "builtins.str | None"
reveal_type(finders.AppDirectoriesFinder().find("filepath")) # N: Revealed type is "builtins.str | None"
reveal_type(finders.DefaultStorageFinder().find("filepath")) # N: Revealed type is "builtins.str | None"

- case: test_find_all
main: |
Expand All @@ -29,11 +29,11 @@
from django.contrib.staticfiles.finders import FileSystemFinder

finder = FileSystemFinder()
reveal_type(finder.find_location(".", "filepath")) # N: Revealed type is "Union[builtins.str, None]"
reveal_type(finder.find_location(".", "filepath")) # N: Revealed type is "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, None]"
reveal_type(finder.find_in_app("app", "filepath")) # N: Revealed type is "builtins.str | None"
11 changes: 6 additions & 5 deletions tests/typecheck/core/test_checks.yml
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
- case: test_checks_register
main: |
from typing import Any, Sequence, Optional, Union, List
from collections.abc import Sequence
from typing import Any

from django.apps.config import AppConfig
from django.core.checks import register, Warning, CheckMessage


@register("foo", deploy=True)
def check_foo(app_configs: Union[Sequence[AppConfig], None], databases: Optional[Sequence[str]], **kwargs: Any) -> List[Warning]:
def check_foo(app_configs: Sequence[AppConfig] | None, databases: Sequence[str] | None, **kwargs: Any) -> list[Warning]:
if databases and 'databass' in databases:
return [Warning("Naughty list")]
return []

reveal_type(check_foo) # N: Revealed type is "django.core.checks.registry._ProcessedCheckCallable[def (app_configs: Union[typing.Sequence[django.apps.config.AppConfig], None], databases: Union[typing.Sequence[builtins.str], None], **kwargs: Any) -> builtins.list[django.core.checks.messages.Warning]]"
reveal_type(check_foo) # N: Revealed type is "django.core.checks.registry._ProcessedCheckCallable[def (app_configs: typing.Sequence[django.apps.config.AppConfig] | None, databases: typing.Sequence[builtins.str] | None, **kwargs: Any) -> builtins.list[django.core.checks.messages.Warning]]"
reveal_type(check_foo.tags) # N: Revealed type is "typing.Sequence[builtins.str]"

@register
def check_bar(*, app_configs: Union[Sequence[AppConfig], None], **kwargs: Any) -> Sequence[CheckMessage]: ...
def check_bar(*, app_configs: Sequence[AppConfig] | None, **kwargs: Any) -> Sequence[CheckMessage]: ...

reveal_type(check_bar) # N: Revealed type is "django.core.checks.registry._ProcessedCheckCallable[def (*, app_configs: Union[typing.Sequence[django.apps.config.AppConfig], None], **kwargs: Any) -> typing.Sequence[django.core.checks.messages.CheckMessage]]"
reveal_type(check_bar) # N: Revealed type is "django.core.checks.registry._ProcessedCheckCallable[def (*, app_configs: typing.Sequence[django.apps.config.AppConfig] | None, **kwargs: Any) -> typing.Sequence[django.core.checks.messages.CheckMessage]]"

@register
def check_baz(**kwargs: Any) -> Sequence[CheckMessage]: ...
Expand Down
Loading
Loading