mirror of
https://github.com/davidhalter/django-stubs.git
synced 2025-12-15 08:17:08 +08:00
Fix CI (#1108)
* Fix CI
* Fix CI
* Fix CI
* Fix CI
* APply black
* APply black
* Fix mypy
* Fix mypy errors in django-stubs
* Fix format
* Fix plugin
* Do not patch builtins by default
* Fix mypy
* Only run mypy on 3.10 for now
* Only run mypy on 3.10 for now
* WHAT THE HELL
* Enable strict mode in mypy
* Enable strict mode in mypy
* Fix tests
* Fix tests
* Debug
* Debug
* Fix tests
* Fix tests
* Add TYPE_CHECKING debug
* Caching maybe?
* Caching maybe?
* Try explicit `${{ matrix.python-version }}`
* Remove debug
* Fix typing
* Finally
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import builtins
|
||||
from typing import Any, Generic, Iterable, List, Optional, Tuple, Type, TypeVar
|
||||
|
||||
from django import VERSION as VERSION
|
||||
@@ -17,6 +18,8 @@ from django.views.generic.detail import SingleObjectMixin
|
||||
from django.views.generic.edit import DeletionMixin, FormMixin
|
||||
from django.views.generic.list import MultipleObjectMixin
|
||||
|
||||
__all__ = ["monkeypatch"]
|
||||
|
||||
_T = TypeVar("_T")
|
||||
_VersionSpec = Tuple[int, int]
|
||||
|
||||
@@ -67,7 +70,7 @@ _need_generic: List[MPGeneric[Any]] = [
|
||||
]
|
||||
|
||||
|
||||
def monkeypatch(extra_classes: Optional[Iterable[type]] = None) -> None:
|
||||
def monkeypatch(extra_classes: Optional[Iterable[type]] = None, include_builtins: bool = True) -> None:
|
||||
"""Monkey patch django as necessary to work properly with mypy."""
|
||||
|
||||
# Add the __class_getitem__ dunder.
|
||||
@@ -81,5 +84,7 @@ def monkeypatch(extra_classes: Optional[Iterable[type]] = None) -> None:
|
||||
for cls in extra_classes:
|
||||
cls.__class_getitem__ = classmethod(lambda cls, *args, **kwargs: cls) # type: ignore[attr-defined]
|
||||
|
||||
|
||||
__all__ = ["monkeypatch"]
|
||||
# Add `reveal_type` and `reveal_locals` helpers if needed:
|
||||
if include_builtins:
|
||||
builtins.reveal_type = lambda _: None
|
||||
builtins.reveal_locals = lambda: None
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
import sys
|
||||
from typing import Any
|
||||
|
||||
if sys.version_info < (3, 8):
|
||||
from typing_extensions import Protocol
|
||||
else:
|
||||
from typing import Protocol
|
||||
from typing_extensions import Protocol
|
||||
|
||||
|
||||
# Used internally by mypy_django_plugin.
|
||||
class AnyAttrAllowed(Protocol):
|
||||
|
||||
@@ -12,7 +12,7 @@ dependencies = [
|
||||
|
||||
setup(
|
||||
name="django-stubs-ext",
|
||||
version="0.5.0",
|
||||
version="0.6.0",
|
||||
description="Monkey-patching and extensions for django-stubs",
|
||||
long_description=readme,
|
||||
long_description_content_type="text/markdown",
|
||||
@@ -23,7 +23,7 @@ setup(
|
||||
maintainer="Nikita Sobolev",
|
||||
maintainer_email="mail@sobolevn.me",
|
||||
py_modules=[],
|
||||
python_requires=">=3.6",
|
||||
python_requires=">=3.7",
|
||||
install_requires=dependencies,
|
||||
packages=["django_stubs_ext", *find_packages(exclude=["scripts"])],
|
||||
package_data={"django_stubs_ext": ["py.typed"]},
|
||||
@@ -33,6 +33,7 @@ setup(
|
||||
"Programming Language :: Python :: 3.7",
|
||||
"Programming Language :: Python :: 3.8",
|
||||
"Programming Language :: Python :: 3.9",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Typing :: Typed",
|
||||
"Framework :: Django",
|
||||
"Framework :: Django :: 2.2",
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import builtins
|
||||
from contextlib import suppress
|
||||
from typing import Iterable, Optional
|
||||
from typing import Iterable, List, Optional
|
||||
|
||||
import pytest
|
||||
from _pytest.fixtures import FixtureRequest
|
||||
from _pytest.monkeypatch import MonkeyPatch
|
||||
from django.db.models import Model
|
||||
from django.forms.models import ModelForm
|
||||
from django.views import View
|
||||
from typing_extensions import Protocol
|
||||
|
||||
import django_stubs_ext
|
||||
@@ -19,7 +18,10 @@ class _MakeGenericClasses(Protocol):
|
||||
"""Used to represent a type of ``make_generic_classes`` fixture."""
|
||||
|
||||
def __call__(
|
||||
self, django_version: Optional[_VersionSpec] = None, extra_classes: Optional[Iterable[type]] = None
|
||||
self,
|
||||
django_version: Optional[_VersionSpec] = None,
|
||||
extra_classes: Optional[Iterable[type]] = None,
|
||||
include_builtins: bool = True,
|
||||
) -> None:
|
||||
...
|
||||
|
||||
@@ -29,7 +31,7 @@ def make_generic_classes(
|
||||
request: FixtureRequest,
|
||||
monkeypatch: MonkeyPatch,
|
||||
) -> _MakeGenericClasses:
|
||||
_extra_classes: list[type] = []
|
||||
_extra_classes: List[type] = []
|
||||
|
||||
def fin() -> None:
|
||||
for el in _need_generic:
|
||||
@@ -38,13 +40,22 @@ def make_generic_classes(
|
||||
for cls in _extra_classes:
|
||||
with suppress(AttributeError):
|
||||
delattr(cls, "__class_getitem__")
|
||||
_extra_classes.clear()
|
||||
with suppress(AttributeError):
|
||||
del builtins.reveal_type
|
||||
with suppress(AttributeError):
|
||||
del builtins.reveal_locals
|
||||
|
||||
def factory(django_version: Optional[_VersionSpec] = None, extra_classes: Optional[Iterable[type]] = None) -> None:
|
||||
def factory(
|
||||
django_version: Optional[_VersionSpec] = None,
|
||||
extra_classes: Optional[Iterable[type]] = None,
|
||||
include_builtins: bool = True,
|
||||
) -> None:
|
||||
if extra_classes:
|
||||
_extra_classes.extend(extra_classes)
|
||||
if django_version is not None:
|
||||
monkeypatch.setattr(patch, "VERSION", django_version)
|
||||
django_stubs_ext.monkeypatch(extra_classes)
|
||||
django_stubs_ext.monkeypatch(extra_classes=extra_classes, include_builtins=include_builtins)
|
||||
|
||||
request.addfinalizer(fin)
|
||||
return factory
|
||||
@@ -64,14 +75,17 @@ def test_patched_generics(make_generic_classes: _MakeGenericClasses) -> None:
|
||||
|
||||
def test_patched_extra_classes_generics(make_generic_classes: _MakeGenericClasses) -> None:
|
||||
"""Test that the generics actually get patched for extra classes."""
|
||||
extra_classes = [View]
|
||||
|
||||
class _NotGeneric:
|
||||
pass
|
||||
|
||||
extra_classes = [_NotGeneric]
|
||||
make_generic_classes(django_version=None, extra_classes=extra_classes)
|
||||
|
||||
for cls in extra_classes:
|
||||
assert cls[type] is cls # type: ignore[misc]
|
||||
|
||||
class TestView(View[Model]): # type: ignore[type-arg]
|
||||
class _TestGeneric(_NotGeneric[Model]): # type: ignore
|
||||
pass
|
||||
|
||||
|
||||
@@ -106,7 +120,17 @@ def test_mypy_builtins_not_patched_globally(
|
||||
This should only happend during `django.setup()`
|
||||
(https://github.com/typeddjango/django-stubs/issues/609).
|
||||
"""
|
||||
make_generic_classes()
|
||||
make_generic_classes(include_builtins=False)
|
||||
|
||||
assert not hasattr(builtins, "reveal_type")
|
||||
assert not hasattr(builtins, "reveal_locals")
|
||||
|
||||
|
||||
def test_mypy_builtins_patched(
|
||||
make_generic_classes: _MakeGenericClasses,
|
||||
) -> None:
|
||||
"""Ensures that builtins are patched by default."""
|
||||
make_generic_classes()
|
||||
|
||||
assert hasattr(builtins, "reveal_type")
|
||||
assert hasattr(builtins, "reveal_locals")
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
# `main` is empty on purpose, because we test the `django.setup()` step.
|
||||
# It executes the `myapp/models.py` file and should not produce anything,
|
||||
# because `reveal_type` and `reveal_locals` are patched.
|
||||
monkeypatch: true
|
||||
installed_apps:
|
||||
- myapp
|
||||
files:
|
||||
|
||||
Reference in New Issue
Block a user