Skip to content
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

Fill remaining missing hints & disallow partial hints #480

Merged
merged 6 commits into from
Oct 5, 2023
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
22 changes: 19 additions & 3 deletions mypy.ini
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,8 @@ warn_unused_ignores = true
warn_redundant_casts = true
warn_unused_configs = true
warn_unreachable = true
# TODO: enable disallow_*_defs later
disallow_untyped_defs = false
disallow_incomplete_defs = false
disallow_untyped_defs = true
disallow_incomplete_defs = true
disable_error_code = empty-body
# TODO: update our test error messages to match new mypy output
show_error_codes = false
Expand All @@ -25,5 +24,22 @@ plugins =
[mypy.plugins.django-stubs]
django_settings_module = scripts.drf_tests_settings

# Suppress errors from site-packages due to https://github.com/typeddjango/pytest-mypy-plugins/issues/134
[mypy-uritemplate.*]
warn_unreachable = false

[mypy-yaml.*]
disallow_untyped_defs = false
disallow_incomplete_defs = false
Comment on lines +31 to +33
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these are necessary due to the way pytest-mypy-plugins works.

Mypy ordinarily ignores errors from site-packages imports, but they aren't ignored in tests.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be a new bug / feature request in pytest-mypy-plugins. Users should not see this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


[mypy-urllib3.*]
disallow_untyped_defs = false
disallow_incomplete_defs = false

[mypy-requests.*]
disallow_untyped_defs = false
disallow_incomplete_defs = false

[mypy-markdown.*]
disallow_untyped_defs = false
disallow_incomplete_defs = false
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ select = [

[tool.ruff.isort]
split-on-trailing-comma = false
extra-standard-library = ["_typeshed"]

[build-system]
requires = ["setuptools<64", "wheel"]
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ from typing import Any

from django.contrib.auth.base_user import AbstractBaseUser
from django.core.management.base import BaseCommand
from rest_framework.authtoken.models import Token

UserModel: AbstractBaseUser

class Command(BaseCommand):
help: str
def create_user_token(self, username: str, reset_token: bool): ...
def create_user_token(self, username: str, reset_token: bool) -> Token: ...
def add_arguments(self, parser: Any) -> None: ...
def handle(self, *args: Any, **options: Any) -> None: ...
3 changes: 2 additions & 1 deletion rest_framework-stubs/authtoken/models.pyi
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from typing import Any

from django.db import models
from typing_extensions import Self

class Token(models.Model):
key: models.CharField
Expand All @@ -11,4 +12,4 @@ class Token(models.Model):

class TokenProxy(Token):
@property
def pk(self) -> Any: ...
def pk(self: Self) -> Any: ...
4 changes: 2 additions & 2 deletions rest_framework-stubs/compat.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ except ImportError:
pygments = None
try:
import markdown
def apply_markdown(text: str): ...
def apply_markdown(text: str) -> str: ...

except ImportError:
apply_markdown = None # type: ignore
Expand All @@ -45,7 +45,7 @@ if markdown is not None and pygments is not None:
class CodeBlockPreprocessor(Preprocessor):
pattern: Any
formatter: Any
def run(self, lines: Any): ...
def run(self, lines: list[str]) -> list[str]: ...

def pygments_css(style: Any) -> str | None: ...
def pygments_highlight(text: str, lang: str, style: Any) -> Any: ...
Expand Down
6 changes: 3 additions & 3 deletions rest_framework-stubs/exceptions.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ from django.http import HttpRequest, JsonResponse
from django_stubs_ext import StrOrPromise
from rest_framework.renderers import BaseRenderer
from rest_framework.request import Request
from typing_extensions import TypeAlias, TypedDict
from typing_extensions import Self, TypeAlias, TypedDict

class ErrorDetail(str):
code: str | None
def __new__(cls, string: str, code: str | None = ...): ...
def __new__(cls, string: str, code: str | None = ...) -> Self: ...

_Detail: TypeAlias = ErrorDetail | list[_Detail] | dict[str, _Detail]
# NB! _APIExceptionInput doesn't technically handle Sequence/Mapping, but only list/tuple/dict.
Expand Down Expand Up @@ -68,7 +68,7 @@ class UnsupportedMediaType(APIException):
class Throttled(APIException):
extra_detail_singular: str
extra_detail_plural: str
def __init__(self, wait: float | None = ..., detail: _APIExceptionInput = ..., code: str | None = ...): ...
def __init__(self, wait: float | None = ..., detail: _APIExceptionInput = ..., code: str | None = ...) -> None: ...

def server_error(request: HttpRequest | Request, *args: Any, **kwargs: Any) -> JsonResponse: ...
def bad_request(request: HttpRequest | Request, exception: Exception, *args: Any, **kwargs: Any) -> JsonResponse: ...
5 changes: 3 additions & 2 deletions rest_framework-stubs/fields.pyi
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import datetime
import uuid
from _typeshed import Incomplete
from collections.abc import Callable, Generator, Iterable, Mapping, MutableMapping, Sequence
from decimal import Decimal
from enum import Enum
Expand All @@ -26,11 +27,11 @@ class CreateOnlyDefault:
requires_context: bool
default: Any
def __init__(self, default: Any) -> None: ...
def __call__(self, serializer_field: Field): ...
def __call__(self, serializer_field: Field) -> Incomplete: ...

class CurrentUserDefault:
requires_context: bool
def __call__(self, serializer_field: Field): ...
def __call__(self, serializer_field: Field) -> Incomplete: ...

class SkipField(Exception): ...

Expand Down
17 changes: 11 additions & 6 deletions rest_framework-stubs/filters.pyi
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from _typeshed import Incomplete
from collections.abc import Iterable, Mapping, Sequence
from typing import Any, TypeVar

Expand All @@ -10,18 +11,18 @@ _MT = TypeVar("_MT", bound=Model)
class BaseFilterBackend:
def filter_queryset(self, request: Request, queryset: QuerySet[_MT], view: APIView) -> QuerySet[_MT]: ...
def get_schema_fields(self, view: APIView) -> list[Any]: ...
def get_schema_operation_parameters(self, view: APIView): ...
def get_schema_operation_parameters(self, view: APIView) -> list[dict[str, Incomplete]]: ...

class SearchFilter(BaseFilterBackend):
search_param: str
template: str
lookup_prefixes: dict[str, str]
search_title: str
search_description: str
def get_search_fields(self, view: APIView, request: Request): ...
def get_search_fields(self, view: APIView, request: Request) -> Incomplete: ...
def get_search_terms(self, request: Request) -> list[str]: ...
def construct_search(self, field_name: str) -> str: ...
def must_call_distinct(self, queryset: QuerySet, search_fields) -> bool: ...
def must_call_distinct(self, queryset: QuerySet, search_fields: Incomplete) -> bool: ...
def to_html(self, request: Request, queryset: QuerySet, view: APIView) -> str: ...

class OrderingFilter(BaseFilterBackend):
Expand All @@ -33,9 +34,13 @@ class OrderingFilter(BaseFilterBackend):
def get_ordering(self, request: Request, queryset: QuerySet, view: APIView) -> Sequence[str] | None: ...
def get_default_ordering(self, view: APIView) -> Sequence[str] | None: ...
def get_default_valid_fields(
self, queryset: QuerySet, view, context: Mapping[str, Any] = ...
self, queryset: QuerySet, view: APIView, context: Mapping[str, Any] = ...
) -> list[tuple[str, str]]: ...
def get_valid_fields(self, queryset: QuerySet, view, context: Mapping[str, Any] = ...) -> list[tuple[str, str]]: ...
def remove_invalid_fields(self, queryset: QuerySet, fields: Iterable[str], view, request: Request) -> list[str]: ...
def get_valid_fields(
self, queryset: QuerySet, view: APIView, context: Mapping[str, Any] = ...
) -> list[tuple[str, str]]: ...
def remove_invalid_fields(
self, queryset: QuerySet, fields: Iterable[str], view: APIView, request: Request
) -> list[str]: ...
def get_template_context(self, request: Request, queryset: QuerySet, view: APIView) -> dict[str, Any]: ...
def to_html(self, request: Request, queryset: QuerySet, view: APIView) -> str: ...
3 changes: 2 additions & 1 deletion rest_framework-stubs/generics.pyi
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from _typeshed import Incomplete
from collections.abc import Sequence
from typing import Any, Protocol, TypeVar

Expand Down Expand Up @@ -27,7 +28,7 @@ class BaseFilterProtocol(Protocol[_MT_inv]):
self, request: Request, queryset: QuerySet[_MT_inv], view: views.APIView
) -> QuerySet[_MT_inv]: ...
def get_schema_fields(self, view: views.APIView) -> list[Any]: ...
def get_schema_operation_parameters(self, view: views.APIView): ...
def get_schema_operation_parameters(self, view: views.APIView) -> Incomplete: ...

class GenericAPIView(views.APIView, UsesQuerySet[_MT_co]):
queryset: QuerySet[_MT_co] | Manager[_MT_co] | None
Expand Down
7 changes: 4 additions & 3 deletions rest_framework-stubs/management/commands/generateschema.pyi
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from _typeshed import Incomplete
from typing import Any

from django.core.management.base import BaseCommand
Expand All @@ -7,8 +8,8 @@ COREAPI_MODE: str

class Command(BaseCommand):
help: str
def get_mode(self): ...
def get_mode(self) -> Incomplete: ...
def add_arguments(self, parser: Any) -> None: ...
def handle(self, *args: Any, **options: Any) -> None: ...
def get_renderer(self, format: str): ...
def get_generator_class(self): ...
def get_renderer(self, format: str) -> Incomplete: ...
def get_generator_class(self) -> Incomplete: ...
5 changes: 4 additions & 1 deletion rest_framework-stubs/negotiation.pyi
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from _typeshed import Incomplete
from collections.abc import Iterable

from rest_framework.parsers import BaseParser
Expand All @@ -7,7 +8,9 @@ from rest_framework.settings import api_settings

class BaseContentNegotiation:
def select_parser(self, request: Request, parsers: Iterable[BaseParser]) -> BaseParser | None: ...
def select_renderer(self, request: Request, renderers: Iterable[BaseRenderer], format_suffix: str | None = ...): ...
def select_renderer(
self, request: Request, renderers: Iterable[BaseRenderer], format_suffix: str | None = ...
) -> Incomplete: ...

class DefaultContentNegotiation(BaseContentNegotiation):
settings = api_settings
Expand Down
10 changes: 6 additions & 4 deletions rest_framework-stubs/pagination.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,14 @@ _MT = TypeVar("_MT", bound=Model)

class BasePagination:
display_page_controls: bool
def get_paginated_response_schema(self, schema: Any): ...
def get_paginated_response_schema(self, schema: dict[str, Any]) -> dict[str, Any]: ...
def get_paginated_response(self, data: Any) -> Response: ...
def get_results(self, data: dict[str, Any]) -> Any: ...
def get_schema_fields(self, view: APIView) -> list: ...
def get_schema_operation_parameters(self, view: APIView) -> list: ...
def paginate_queryset(self, queryset: QuerySet, request: Request, view: APIView | None = ...): ...
def get_schema_fields(self, view: APIView) -> list[Any]: ...
def get_schema_operation_parameters(self, view: APIView) -> list[Any]: ...
def paginate_queryset(
self, queryset: QuerySet[_MT], request: Request, view: APIView | None = ...
) -> list[_MT] | None: ...
def to_html(self) -> str: ...

class PageNumberPagination(BasePagination):
Expand Down
9 changes: 5 additions & 4 deletions rest_framework-stubs/permissions.pyi
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from _typeshed import Incomplete
from collections.abc import Sequence
from typing import Any, Protocol # noqa: Y037 # https://github.com/python/mypy/issues/12392

Expand Down Expand Up @@ -25,17 +26,17 @@ class OperationHolderMixin:
class SingleOperandHolder(OperationHolderMixin):
operator_class: _SupportsHasPermission
op1_class: _PermissionClass
def __init__(self, operator_class: _SupportsHasPermission, op1_class: _PermissionClass): ...
def __call__(self, *args, **kwargs) -> _SupportsHasPermission: ...
def __init__(self, operator_class: _SupportsHasPermission, op1_class: _PermissionClass) -> None: ...
def __call__(self, *args: Incomplete, **kwargs: Incomplete) -> _SupportsHasPermission: ...

class OperandHolder(OperationHolderMixin):
operator_class: _SupportsHasPermission
op1_class: _PermissionClass
op2_class: _PermissionClass
def __init__(
self, operator_class: _SupportsHasPermission, op1_class: _PermissionClass, op2_class: _PermissionClass
): ...
def __call__(self, *args, **kwargs) -> _SupportsHasPermission: ...
) -> None: ...
def __call__(self, *args: Incomplete, **kwargs: Incomplete) -> _SupportsHasPermission: ...

class AND(_SupportsHasPermission):
def __init__(self, op1: _SupportsHasPermission, op2: _SupportsHasPermission) -> None: ...
Expand Down
2 changes: 1 addition & 1 deletion rest_framework-stubs/relations.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class ObjectTypeError(TypeError): ...

class Hyperlink(str):
def __new__(cls, url: str, obj: Any) -> Self: ...
def __getnewargs__(self): ...
def __getnewargs__(self) -> tuple[str, str]: ... # type: ignore[override]
@property
def name(self) -> str: ...
is_hyperlink: bool
Expand Down
20 changes: 13 additions & 7 deletions rest_framework-stubs/renderers.pyi
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from _typeshed import Incomplete
from collections.abc import Iterable, Mapping, Sequence
from json import JSONEncoder
from typing import Any
Expand Down Expand Up @@ -31,7 +32,7 @@ class TemplateHTMLRenderer(BaseRenderer):
template_name: str | None
exception_template_names: Sequence[str]
def resolve_template(self, template_names: Iterable[str]) -> Any: ...
def get_template_context(self, data: Any, renderer_context: Mapping[str, Any]): ...
def get_template_context(self, data: Any, renderer_context: Mapping[str, Any]) -> Incomplete: ...
def get_template_names(self, response: Response, view: APIView) -> list[str]: ...
def get_exception_template(self, response: Response) -> Any: ...

Expand All @@ -42,7 +43,7 @@ class HTMLFormRenderer(BaseRenderer):
base_template: str

default_style: ClassLookupDict
def render_field(self, field, parent_style: Mapping[str, Any]) -> str: ...
def render_field(self, field: Incomplete, parent_style: Mapping[str, Any]) -> str: ...

class BrowsableAPIRenderer(BaseRenderer):
"""
Expand All @@ -59,7 +60,12 @@ class BrowsableAPIRenderer(BaseRenderer):
) -> str: ...
def show_form_for_method(self, view: APIView, method: str, request: Request, obj: Any) -> bool: ...
def _get_serializer(
self, serializer_class: type[BaseSerializer], view_instance: APIView, request: Request, *args, **kwargs
self,
serializer_class: type[BaseSerializer],
view_instance: APIView,
request: Request,
*args: Incomplete,
**kwargs: Incomplete
) -> BaseSerializer: ...
def get_rendered_html_form(self, data: Any, view: APIView, method: str, request: Request) -> Any: ...
def render_form_for_serializer(self, serializer: BaseSerializer) -> Any: ...
Expand Down Expand Up @@ -96,11 +102,11 @@ class _BaseOpenAPIRenderer:
charset: Any
format: str
def __init__(self) -> None: ...
def render(self, data: Any, media_type: Any | None = ..., renderer_context: Any | None = ...): ...
def render(self, data: Any, media_type: Any | None = ..., renderer_context: Any | None = ...) -> Incomplete: ...
def get_schema(self, instance: Any) -> dict[str, Any]: ...
def get_parameters(self, link) -> dict[str, Any]: ...
def get_operation(self, link, name, tag) -> dict[str, Any]: ...
def get_paths(self, document) -> dict[str, Any]: ...
def get_parameters(self, link: Incomplete) -> dict[str, Any]: ...
def get_operation(self, link: Incomplete, name: Incomplete, tag: Incomplete) -> dict[str, Any]: ...
def get_paths(self, document: Incomplete) -> dict[str, Any]: ...
def get_structure(self, data: Any) -> dict[str, Any]: ...

class JSONOpenAPIRenderer(_BaseOpenAPIRenderer): ...
Expand Down
5 changes: 3 additions & 2 deletions rest_framework-stubs/request.pyi
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from _typeshed import Incomplete
from collections.abc import Iterator, Sequence
from contextlib import AbstractContextManager, contextmanager
from types import TracebackType
Expand All @@ -17,7 +18,7 @@ from rest_framework.views import APIView
def is_form_media_type(media_type: str) -> bool: ...

class override_method(AbstractContextManager[Request]):
def __init__(self, view: APIView, request: Request, method: str): ...
def __init__(self, view: APIView, request: Request, method: str) -> None: ...
def __enter__(self) -> Request: ...
def __exit__(
self,
Expand Down Expand Up @@ -79,5 +80,5 @@ class Request(HttpRequest):
@property
def POST(self) -> _ImmutableQueryDict: ... # type: ignore[override]
@property
def FILES(self): ...
def FILES(self) -> Incomplete: ... # type: ignore[override]
def force_plaintext_errors(self, value: Any) -> None: ...
3 changes: 2 additions & 1 deletion rest_framework-stubs/schemas/coreapi.pyi
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from _typeshed import Incomplete
from collections import Counter
from collections.abc import Iterable, Sequence
from typing import Any
Expand Down Expand Up @@ -43,7 +44,7 @@ class SchemaGenerator(BaseSchemaGenerator):
def get_keys(self, subpath: Any, method: Any, view: APIView) -> list[str]: ...
def determine_path_prefix(self, paths: list[str]) -> str: ...

def field_to_schema(field: Field): ...
def field_to_schema(field: Field) -> Incomplete: ...

class AutoSchema(ViewInspector):
def __init__(self, manual_fields: list[coreapi.Field] | None = ...) -> None: ...
Expand Down
5 changes: 3 additions & 2 deletions rest_framework-stubs/schemas/inspectors.pyi
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from _typeshed import Incomplete
from collections.abc import Mapping
from re import Pattern
from typing import Any
Expand All @@ -6,10 +7,10 @@ class ViewInspector:
header_regex: Pattern
instance_schemas: Mapping[str, Any]
def __init__(self) -> None: ...
def __get__(self, instance: Any, owner: Any): ...
def __get__(self, instance: Any, owner: Any) -> Incomplete: ...
def __set__(self, instance: Any, other: Any) -> None: ...
@property
def view(self): ...
def view(self) -> Incomplete: ...
@view.setter
def view(self, value: Any) -> None: ...
def get_description(self, path: Any, method: Any) -> str: ...
Expand Down
Loading