Skip to content

Commit

Permalink
Introduce flake8-pyi in pre-commit checks (#286)
Browse files Browse the repository at this point in the history
This is a PR similar to typeddjango/django-stubs#1253, only for rest_framework-stubs.

All statements that are unclear on how to proceed are marked with # noqa: in the code, with the exception of compat.pyi, which has additional rules turned off in setup.cfg.

* configure flake8-pyi plugin in pre-commit
* fix Y015
* fix Y037
* use PEP 585 container types where possible, replace obsolete typing types with collections.abc
* disable Y041 rule
* add typealias annotation where feasible, add self annotations
* fix failing tests, silence remaining warnings since unclear how to proceed
* address review
* amend tests
* amend rebase error

Signed-off-by: Oleg Hoefling <oleg.hoefling@ionos.com>
  • Loading branch information
hoefling committed Nov 16, 2022
1 parent a1ec425 commit 158fd4f
Show file tree
Hide file tree
Showing 56 changed files with 1,073 additions and 1,123 deletions.
4 changes: 4 additions & 0 deletions .pre-commit-config.yaml
Expand Up @@ -27,6 +27,10 @@ repos:
rev: 5.0.4
hooks:
- id: flake8
additional_dependencies:
- flake8-pyi==22.10.0
types: []
files: ^.*.pyi?$
- repo: local
hooks:
- id: mypy
Expand Down
22 changes: 11 additions & 11 deletions rest_framework-stubs/authentication.pyi
@@ -1,4 +1,4 @@
from typing import Any, Optional, Tuple, Type
from typing import Any

from django.contrib.auth import authenticate as authenticate
from django.db.models import Model
Expand All @@ -10,23 +10,23 @@ def get_authorization_header(request: Request) -> bytes: ...
class CSRFCheck(CsrfViewMiddleware): ...

class BaseAuthentication:
def authenticate(self, request: Request) -> Optional[Tuple[Any, Any]]: ...
def authenticate_header(self, request: Request) -> Optional[str]: ...
def authenticate(self, request: Request) -> tuple[Any, Any] | None: ... # noqa: F811
def authenticate_header(self, request: Request) -> str | None: ...

class BasicAuthentication(BaseAuthentication):
www_authenticate_realm: str = ...
www_authenticate_realm: str
def authenticate_credentials(
self, userid: str, password: str, request: Optional[Request] = ...
) -> Tuple[Any, None]: ...
self, userid: str, password: str, request: Request | None = ...
) -> tuple[Any, None]: ...

class SessionAuthentication(BaseAuthentication):
def enforce_csrf(self, request: Request) -> None: ...

class TokenAuthentication(BaseAuthentication):
keyword: str = ...
model: Optional[Type[Model]] = ...
def get_model(self) -> Type[Model]: ...
def authenticate_credentials(self, key: str) -> Tuple[Any, Any]: ...
keyword: str
model: type[Model] | None
def get_model(self) -> type[Model]: ...
def authenticate_credentials(self, key: str) -> tuple[Any, Any]: ...

class RemoteUserAuthentication(BaseAuthentication):
header: str = ...
header: str
2 changes: 1 addition & 1 deletion rest_framework-stubs/authtoken/__init__.pyi
@@ -1 +1 @@
default_app_config: str = ...
default_app_config: str
Expand Up @@ -6,7 +6,7 @@ from django.core.management.base import BaseCommand
UserModel: AbstractBaseUser

class Command(BaseCommand):
help: str = ...
help: str
def create_user_token(self, username: str, reset_token: bool): ...
def add_arguments(self, parser: Any) -> None: ...
def handle(self, *args: Any, **options: Any) -> None: ...
6 changes: 3 additions & 3 deletions rest_framework-stubs/authtoken/models.pyi
Expand Up @@ -3,9 +3,9 @@ from typing import Any
from django.db import models

class Token(models.Model):
key: models.CharField = ...
user: models.OneToOneField = ...
created: models.DateTimeField = ...
key: models.CharField
user: models.OneToOneField
created: models.DateTimeField
@classmethod
def generate_key(cls) -> str: ...

Expand Down
6 changes: 3 additions & 3 deletions rest_framework-stubs/authtoken/serializers.pyi
@@ -1,6 +1,6 @@
from rest_framework import serializers

class AuthTokenSerializer(serializers.Serializer):
username: serializers.CharField = ...
password: serializers.CharField = ...
token: serializers.CharField = ...
username: serializers.CharField
password: serializers.CharField
token: serializers.CharField
6 changes: 3 additions & 3 deletions rest_framework-stubs/authtoken/views.pyi
@@ -1,12 +1,12 @@
from typing import Any, Type
from typing import Any

from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import Serializer
from rest_framework.views import APIView, AsView, GenericView

class ObtainAuthToken(APIView):
serializer_class: Type[Serializer] = ...
serializer_class: type[Serializer]
def post(self, request: Request, *args: Any, **kwargs: Any) -> Response: ...

obtain_auth_token: AsView[GenericView] = ...
obtain_auth_token: AsView[GenericView]
4 changes: 2 additions & 2 deletions rest_framework-stubs/checks.pyi
@@ -1,3 +1,3 @@
from typing import Any, List
from typing import Any

def pagination_system_check(app_configs: Any, **kwargs: Any) -> List[Any]: ...
def pagination_system_check(app_configs: Any, **kwargs: Any) -> list[Any]: ...
18 changes: 9 additions & 9 deletions rest_framework-stubs/compat.pyi
@@ -1,4 +1,4 @@
from typing import Any, Optional, Tuple, Union
from typing import Any

import requests # noqa: F401
from django.db.models import QuerySet
Expand Down Expand Up @@ -43,19 +43,19 @@ if markdown is not None and pygments is not None:
from markdown.preprocessors import Preprocessor # type: ignore

class CodeBlockPreprocessor(Preprocessor):
pattern: Any = ...
formatter: Any = ...
pattern: Any
formatter: Any
def run(self, lines: Any): ...

def pygments_css(style: Any) -> Optional[str]: ...
def pygments_css(style: Any) -> str | None: ...
def pygments_highlight(text: str, lang: str, style: Any) -> Any: ...
def md_filter_add_syntax_highlight(md: Any) -> bool: ...
def unicode_http_header(value: Union[str, bytes]) -> str: ...
def distinct(queryset: QuerySet, base: Optional[QuerySet]) -> QuerySet: ...
def unicode_http_header(value: str | bytes) -> str: ...
def distinct(queryset: QuerySet, base: QuerySet | None) -> QuerySet: ...

SHORT_SEPARATORS: Tuple[str, str]
LONG_SEPARATORS: Tuple[str, str]
INDENT_SEPARATORS: Tuple[str, str]
SHORT_SEPARATORS: tuple[str, str]
LONG_SEPARATORS: tuple[str, str]
INDENT_SEPARATORS: tuple[str, str]

__all__ = [
"coreapi",
Expand Down
35 changes: 16 additions & 19 deletions rest_framework-stubs/decorators.pyi
@@ -1,4 +1,5 @@
from typing import Any, Callable, List, Mapping, Optional, Protocol, Sequence, Type, TypeVar, Union
from collections.abc import Callable, Mapping, Sequence
from typing import Any, Protocol, TypeVar

from django.http import HttpRequest
from django.http.response import HttpResponseBase
Expand All @@ -10,7 +11,7 @@ from rest_framework.request import Request
from rest_framework.schemas.inspectors import ViewInspector
from rest_framework.throttling import BaseThrottle
from rest_framework.views import APIView, AsView # noqa: F401
from typing_extensions import Concatenate, Literal, ParamSpec
from typing_extensions import Concatenate, Literal, ParamSpec, TypeAlias

_View = TypeVar("_View", bound=Callable[..., HttpResponseBase])
_P = ParamSpec("_P")
Expand All @@ -28,7 +29,7 @@ class MethodMapper(dict):
def options(self, func: _View) -> _View: ...
def trace(self, func: _View) -> _View: ...

_LOWER_CASE_HTTP_VERBS = List[
_LOWER_CASE_HTTP_VERBS: TypeAlias = list[
Literal[
"get",
"post",
Expand All @@ -40,7 +41,7 @@ _LOWER_CASE_HTTP_VERBS = List[
]
]

_MIXED_CASE_HTTP_VERBS = List[
_MIXED_CASE_HTTP_VERBS: TypeAlias = list[
Literal[
"GET",
"POST",
Expand Down Expand Up @@ -71,26 +72,22 @@ class ViewSetAction(Protocol[_View]):
__call__: _View

def api_view(
http_method_names: Optional[Sequence[str]] = ...,
http_method_names: Sequence[str] | None = ...,
) -> Callable[[Callable[Concatenate[Request, _P], _RESP]], AsView[Callable[Concatenate[HttpRequest, _P], _RESP]]]: ...
def renderer_classes(
renderer_classes: Sequence[Union[BaseRenderer, Type[BaseRenderer]]]
) -> Callable[[_View], _View]: ...
def parser_classes(parser_classes: Sequence[Union[BaseParser, Type[BaseParser]]]) -> Callable[[_View], _View]: ...
def renderer_classes(renderer_classes: Sequence[BaseRenderer | type[BaseRenderer]]) -> Callable[[_View], _View]: ...
def parser_classes(parser_classes: Sequence[BaseParser | type[BaseParser]]) -> Callable[[_View], _View]: ...
def authentication_classes(
authentication_classes: Sequence[Union[BaseAuthentication, Type[BaseAuthentication]]]
) -> Callable[[_View], _View]: ...
def throttle_classes(
throttle_classes: Sequence[Union[BaseThrottle, Type[BaseThrottle]]]
authentication_classes: Sequence[BaseAuthentication | type[BaseAuthentication]],
) -> Callable[[_View], _View]: ...
def throttle_classes(throttle_classes: Sequence[BaseThrottle | type[BaseThrottle]]) -> Callable[[_View], _View]: ...
def permission_classes(permission_classes: Sequence[_PermissionClass]) -> Callable[[_View], _View]: ...
def schema(view_inspector: Optional[Union[ViewInspector, Type[ViewInspector]]]) -> Callable[[_View], _View]: ...
def schema(view_inspector: ViewInspector | type[ViewInspector] | None) -> Callable[[_View], _View]: ...
def action(
methods: Optional[_MIXED_CASE_HTTP_VERBS] = ...,
methods: _MIXED_CASE_HTTP_VERBS | None = ...,
detail: bool = ...,
url_path: Optional[str] = ...,
url_name: Optional[str] = ...,
suffix: Optional[str] = ...,
name: Optional[str] = ...,
url_path: str | None = ...,
url_name: str | None = ...,
suffix: str | None = ...,
name: str | None = ...,
**kwargs: Any,
) -> Callable[[_View], ViewSetAction[_View]]: ...
45 changes: 23 additions & 22 deletions rest_framework-stubs/documentation.pyi
@@ -1,42 +1,43 @@
from typing import Any, Callable, Optional, Sequence, Type
from collections.abc import Callable, Sequence
from typing import Any

from rest_framework.renderers import BaseRenderer
from rest_framework.schemas import SchemaGenerator
from rest_framework.urlpatterns import _AnyURL

def get_docs_view(
title: Optional[str] = ...,
url: Optional[str] = ...,
description: Optional[str] = ...,
urlconf: Optional[str] = ...,
renderer_classes: Optional[Sequence[Type[BaseRenderer]]] = ...,
title: str | None = ...,
url: str | None = ...,
description: str | None = ...,
urlconf: str | None = ...,
renderer_classes: Sequence[type[BaseRenderer]] | None = ...,
public: bool = ...,
patterns: Optional[Sequence[_AnyURL]] = ...,
generator_class: Type[SchemaGenerator] = ...,
patterns: Sequence[_AnyURL] | None = ...,
generator_class: type[SchemaGenerator] = ...,
authentication_classes: Sequence[str] = ...,
permission_classes: Sequence[str] = ...,
) -> Callable[..., Any]: ...
def get_schemajs_view(
title: Optional[str] = ...,
url: Optional[str] = ...,
description: Optional[str] = ...,
urlconf: Optional[str] = ...,
renderer_classes: Optional[Sequence[Type[BaseRenderer]]] = ...,
title: str | None = ...,
url: str | None = ...,
description: str | None = ...,
urlconf: str | None = ...,
renderer_classes: Sequence[type[BaseRenderer]] | None = ...,
public: bool = ...,
patterns: Optional[Sequence[_AnyURL]] = ...,
generator_class: Type[SchemaGenerator] = ...,
patterns: Sequence[_AnyURL] | None = ...,
generator_class: type[SchemaGenerator] = ...,
authentication_classes: Sequence[str] = ...,
permission_classes: Sequence[str] = ...,
) -> Callable[..., Any]: ...
def include_docs_urls(
title: Optional[str] = ...,
url: Optional[str] = ...,
description: Optional[str] = ...,
urlconf: Optional[str] = ...,
renderer_classes: Optional[Sequence[Type[BaseRenderer]]] = ...,
title: str | None = ...,
url: str | None = ...,
description: str | None = ...,
urlconf: str | None = ...,
renderer_classes: Sequence[type[BaseRenderer]] | None = ...,
public: bool = ...,
patterns: Optional[Sequence[_AnyURL]] = ...,
generator_class: Type[SchemaGenerator] = ...,
patterns: Sequence[_AnyURL] | None = ...,
generator_class: type[SchemaGenerator] = ...,
authentication_classes: Sequence[str] = ...,
permission_classes: Sequence[str] = ...,
) -> Any: ...
47 changes: 24 additions & 23 deletions rest_framework-stubs/exceptions.pyi
@@ -1,26 +1,29 @@
from typing import Any, Dict, List, Optional, Sequence, Union
from collections.abc import Sequence
from typing import Any

from typing_extensions import TypeAlias

from django.http import HttpRequest, JsonResponse
from rest_framework.renderers import BaseRenderer
from rest_framework.request import Request

def _get_error_details(data: Any, default_code: Optional[str] = ...) -> Any: ...
def _get_error_details(data: Any, default_code: str | None = ...) -> Any: ...
def _get_codes(detail: Any) -> Any: ...
def _get_full_details(detail: Any) -> Any: ...

class ErrorDetail(str):
code: Optional[str] = None
def __new__(cls, string: str, code: Optional[str] = ...): ...
code: str | None
def __new__(cls, string: str, code: str | None = ...): ...

_Detail = Union[str, List[Any], Dict[str, Any]]
_Detail: TypeAlias = str | list[Any] | dict[str, Any]

class APIException(Exception):
status_code: int = ...
default_detail: _Detail = ...
default_code: str = ...
status_code: int
default_detail: _Detail
default_code: str

detail: _Detail
def __init__(self, detail: Optional[_Detail] = ..., code: Optional[str] = ...) -> None: ...
def __init__(self, detail: _Detail | None = ..., code: str | None = ...) -> None: ...
def get_codes(self) -> Any: ...
def get_full_details(self) -> Any: ...

Expand All @@ -32,26 +35,24 @@ class PermissionDenied(APIException): ...
class NotFound(APIException): ...

class MethodNotAllowed(APIException):
def __init__(self, method: str, detail: Optional[_Detail] = ..., code: Optional[str] = ...) -> None: ...
def __init__(self, method: str, detail: _Detail | None = ..., code: str | None = ...) -> None: ...

class NotAcceptable(APIException):
available_renderers: Optional[Sequence[BaseRenderer]]
available_renderers: Sequence[BaseRenderer] | None
def __init__(
self,
detail: Optional[_Detail] = ...,
code: Optional[str] = ...,
available_renderers: Optional[Sequence[BaseRenderer]] = ...,
detail: _Detail | None = ...,
code: str | None = ...,
available_renderers: Sequence[BaseRenderer] | None = ...,
) -> None: ...

class UnsupportedMediaType(APIException):
def __init__(self, media_type: str, detail: Optional[_Detail] = ..., code: Optional[str] = ...) -> None: ...
def __init__(self, media_type: str, detail: _Detail | None = ..., code: str | None = ...) -> None: ...

class Throttled(APIException):
extra_detail_singular: str = ...
extra_detail_plural: str = ...
def __init__(self, wait: Optional[float] = ..., detail: Optional[_Detail] = ..., code: Optional[str] = ...): ...

def server_error(request: Union[HttpRequest, Request], *args: Any, **kwargs: Any) -> JsonResponse: ...
def bad_request(
request: Union[HttpRequest, Request], exception: Exception, *args: Any, **kwargs: Any
) -> JsonResponse: ...
extra_detail_singular: str
extra_detail_plural: str
def __init__(self, wait: float | None = ..., detail: _Detail | None = ..., code: str | 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: ...

0 comments on commit 158fd4f

Please sign in to comment.