From 509d9e4fc45c0596313ea47216716b585aeaa0a4 Mon Sep 17 00:00:00 2001 From: henribru <6639509+henribru@users.noreply.github.com> Date: Thu, 31 Mar 2022 22:38:54 +0200 Subject: [PATCH] Add django-stubs v1.10.0 compatibility (#203) * Add django-stubs v1.10.0 compatibility * Bump django-stubs to v1.10.1 * Pin click for black * Bump Black to 22.3.0 --- .github/workflows/test.yml | 4 ++-- .pre-commit-config.yaml | 2 +- mypy_drf_plugin/main.py | 4 ++-- requirements.txt | 2 +- rest_framework-stubs/compat.pyi | 1 + rest_framework-stubs/serializers.pyi | 1 + rest_framework-stubs/test.pyi | 3 ++- scripts/typecheck_tests.py | 13 ++++++++++++- setup.py | 7 +++---- tests/typecheck/test_serializers.yml | 2 +- 10 files changed, 26 insertions(+), 13 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 77acd8311..6682c2064 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -31,7 +31,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ['3.6', '3.7', '3.8', '3.9'] + python-version: ['3.7', '3.8', '3.9'] steps: - uses: actions/checkout@v2 - name: Setup system dependencies @@ -52,7 +52,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ['3.6', '3.7', '3.8', '3.9'] + python-version: ['3.7', '3.8', '3.9'] steps: - uses: actions/checkout@v2 - name: Setup system dependencies diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d1ab93c84..8cf21270b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -20,7 +20,7 @@ repos: hooks: - id: isort - repo: https://github.com/psf/black - rev: 21.12b0 + rev: 22.3.0 hooks: - id: black - repo: https://gitlab.com/pycqa/flake8 diff --git a/mypy_drf_plugin/main.py b/mypy_drf_plugin/main.py index 4ea85c940..5d79e6054 100644 --- a/mypy_drf_plugin/main.py +++ b/mypy_drf_plugin/main.py @@ -3,7 +3,7 @@ from mypy.nodes import TypeInfo from mypy.options import Options from mypy.plugin import ClassDefContext, Plugin -from mypy_django_plugin import main as mypy_django_main +from mypy_django_plugin.config import DjangoPluginConfig from mypy_django_plugin.django.context import DjangoContext from mypy_drf_plugin.lib import fullnames, helpers @@ -22,7 +22,7 @@ class NewSemanalDRFPlugin(Plugin): def __init__(self, options: Options) -> None: super().__init__(options) - django_settings_module = mypy_django_main.extract_django_settings_module(options.config_file) + django_settings_module = DjangoPluginConfig(options.config_file).django_settings_module self.django_context = DjangoContext(django_settings_module) def _get_currently_defined_serializers(self) -> Dict[str, int]: diff --git a/requirements.txt b/requirements.txt index ee836b71c..13119c59e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ wheel gitpython==3.1.9 -pre-commit==2.7.1 +pre-commit==2.9.2 pytest==6.1.1 pytest-mypy-plugins==1.9.1 djangorestframework==3.12.1 diff --git a/rest_framework-stubs/compat.pyi b/rest_framework-stubs/compat.pyi index 4e151eec2..a036ee1b3 100644 --- a/rest_framework-stubs/compat.pyi +++ b/rest_framework-stubs/compat.pyi @@ -38,6 +38,7 @@ except ImportError: if markdown is not None and pygments is not None: from markdown.preprocessors import Preprocessor + class CodeBlockPreprocessor(Preprocessor): pattern: Any = ... formatter: Any = ... diff --git a/rest_framework-stubs/serializers.pyi b/rest_framework-stubs/serializers.pyi index 2f6d8c7c2..e4a1f3454 100644 --- a/rest_framework-stubs/serializers.pyi +++ b/rest_framework-stubs/serializers.pyi @@ -219,6 +219,7 @@ class ModelSerializer(Serializer, BaseSerializer[_MT]): serializer_choice_field: Type[Field] = ... url_field_name: Optional[str] = ... instance: Optional[Union[_MT, Sequence[_MT]]] # type: ignore[override] + class Meta: model: Type[_MT] # type: ignore fields: Union[Sequence[str], Literal["__all__"]] diff --git a/rest_framework-stubs/test.pyi b/rest_framework-stubs/test.pyi index c723fb389..52ef6deb3 100644 --- a/rest_framework-stubs/test.pyi +++ b/rest_framework-stubs/test.pyi @@ -12,12 +12,13 @@ from django.test.client import RequestFactory as DjangoRequestFactory from rest_framework.authtoken.models import Token from rest_framework.request import Request from rest_framework.response import Response +import urllib3 def force_authenticate( request: HttpRequest, user: Optional[Union[AnonymousUser, AbstractBaseUser]] = ..., token: Optional[Token] = ... ) -> None: ... -class HeaderDict(requests.packages.urllib3._collections.HTTPHeaderDict): +class HeaderDict(urllib3._collections.HTTPHeaderDict): def get_all(self, key: Any, default: Any): ... class MockOriginalResponse: diff --git a/scripts/typecheck_tests.py b/scripts/typecheck_tests.py index 752bf298f..1a55aed1e 100644 --- a/scripts/typecheck_tests.py +++ b/scripts/typecheck_tests.py @@ -57,6 +57,8 @@ ' base class "BaseTokenAuthTests" defined the type as "None"', '"None" has no attribute "objects"', '"BaseTokenAuthTests" has no attribute "assertNumQueries"', + 'Module "django.middleware.csrf" has no attribute "_mask_cipher_secret"; maybe "_salt_cipher_secret"?', + "All conditional function variants must have identical signatures", ], "schemas": [ '(expression has type "CharField", base class "Field" defined the type as "bool")', @@ -78,6 +80,9 @@ ], "conftest.py": ["Unsupported operand types for"], "models.py": ['"ForeignKeyTarget" has no attribute "sources"'], + "serializers.pyi": [ + 'note: "IntegerSerializer" defined here', + ], "test_authtoken.py": [ 'Item "None" of "Optional[Token]" has no attribute "key"', 'Argument 1 to "get_fields" of "BaseModelAdmin" has incompatible type "object"; expected "HttpRequest"', @@ -143,6 +148,7 @@ "test_permissions.py": [ '"ResolverMatch" has incompatible type "str"; expected "Callable[..., Any]"', "_SupportsHasPermission", + "Invalid type alias: expression is not a valid type", ], "test_relations.py": [ 'Invalid index type "int" for "Union[str, List[Any], Dict[str, Any]]"; expected type "str"', @@ -175,6 +181,8 @@ '"CharField" has incompatible type "Collection[Any]"', 'Name "foo" is not defined', 'Argument "data" has incompatible type "None"', + 'Unsupported left operand type for | ("ReturnDict")', + 'Unsupported left operand type for | ("Dict[str, str]")', ], "test_serializer_bulk_update.py": [ 'Argument "data" has incompatible type "int"', @@ -184,6 +192,8 @@ "test_serializer_lists.py": [ 'The type "Type[ListSerializer]" is not generic and not indexable', 'Name "foo" is not defined', + 'Unexpected keyword argument "max_length" for "IntegerSerializer"', + 'Unexpected keyword argument "min_length" for "IntegerSerializer"', ], "test_serializer_nested.py": [ '(expression has type "NestedSerializer", base class "Field" defined the type as "bool")', @@ -214,7 +224,8 @@ 'Argument "detail" to "ValidationError" has incompatible type "Tuple[str, str]"; expected "Union[str, List[Any], Dict[str, Any], None]"', # noqa: E501 ], "test_validators.py": [ - 'has incompatible type "object"; expected "QuerySet[Any]"', + 'Argument "queryset" to "BaseUniqueForValidator" has incompatible type "object";' + ' expected "_QuerySet[Any, Any]"', 'to "filter_queryset" of "BaseUniqueForValidator" has incompatible type "None"', ], "test_versioning.py": [ diff --git a/setup.py b/setup.py index 8619f8edc..6b497c470 100644 --- a/setup.py +++ b/setup.py @@ -20,8 +20,8 @@ def find_stub_files(name): readme = f.read() dependencies = [ - "mypy>=0.790", - "django-stubs>=1.7.0", + "mypy>=0.930,<0.950", + "django-stubs>=1.10.1", "typing-extensions>=3.7.2", "requests>=2.0.0", "coreapi>=2.0.0", @@ -43,11 +43,10 @@ def find_stub_files(name): install_requires=dependencies, packages=["rest_framework-stubs", *find_packages(exclude=["scripts"])], package_data={"rest_framework-stubs": find_stub_files("rest_framework-stubs")}, - python_requires=">=3.6", + python_requires=">=3.7", classifiers=[ "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", - "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", diff --git a/tests/typecheck/test_serializers.yml b/tests/typecheck/test_serializers.yml index 06e1216f5..7bcf08313 100644 --- a/tests/typecheck/test_serializers.yml +++ b/tests/typecheck/test_serializers.yml @@ -15,7 +15,7 @@ from rest_framework import serializers reveal_type(serializers.ModelSerializer.Meta.model) # N: Revealed type is "Type[_MT?]" - reveal_type(serializers.ModelSerializer.Meta.fields) # N: Revealed type is "typing.Sequence[builtins.str]" + reveal_type(serializers.ModelSerializer.Meta.fields) # N: Revealed type is "Union[typing.Sequence[builtins.str], Literal['__all__']]" reveal_type(serializers.ModelSerializer.Meta.read_only_fields) # N: Revealed type is "Union[typing.Sequence[builtins.str], None]" reveal_type(serializers.ModelSerializer.Meta.exclude) # N: Revealed type is "Union[typing.Sequence[builtins.str], None]" reveal_type(serializers.ModelSerializer.Meta.depth) # N: Revealed type is "Union[builtins.int, None]"