From 869b65e3b161525a4e3fe9c20a1cb53ee7005a7c Mon Sep 17 00:00:00 2001 From: Noelle Leigh <5957867+noelleleigh@users.noreply.github.com> Date: Wed, 29 Nov 2023 08:27:04 -0500 Subject: [PATCH 1/9] ContextList: Add more specific generic types --- django-stubs/test/testcases.pyi | 2 +- django-stubs/test/utils.pyi | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/django-stubs/test/testcases.pyi b/django-stubs/test/testcases.pyi index 89e2b7463..9da91884d 100644 --- a/django-stubs/test/testcases.pyi +++ b/django-stubs/test/testcases.pyi @@ -27,7 +27,7 @@ class _AssertTemplateUsedContext: template_name: str = ... rendered_templates: list[Template] = ... rendered_template_names: list[str] = ... - context: ContextList = ... + context: ContextList[Any] = ... def __init__(self, test_case: Any, template_name: Any) -> None: ... def on_template_render( self, sender: Any, signal: Any, template: Any, context: Any, **kwargs: Any diff --git a/django-stubs/test/utils.pyi b/django-stubs/test/utils.pyi index e9a7b7fa9..a90b35774 100644 --- a/django-stubs/test/utils.pyi +++ b/django-stubs/test/utils.pyi @@ -16,6 +16,8 @@ from django.test.testcases import SimpleTestCase _TestClass = type[SimpleTestCase] _DecoratedTest = Callable[..., Any] | _TestClass _C = TypeVar("_C", bound=Callable[..., Any]) +_T = TypeVar("_T") +_U = TypeVar("_U") TZ_SUPPORT: bool = ... @@ -24,8 +26,8 @@ class Approximate: places: int = ... def __init__(self, val: Decimal | float, places: int = ...) -> None: ... -class ContextList(list[Any]): - def get(self, key: str, default: str | None = ...) -> str: ... +class ContextList(list[Mapping[str, _T]]): + def get(self, key: str, default: _U | None = ...) -> _T | _U | None: ... def keys(self) -> set[str]: ... class _TestState: ... From 8b8b94feab5ccfb89e146462508233edcea1a484 Mon Sep 17 00:00:00 2001 From: Noelle Leigh <5957867+noelleleigh@users.noreply.github.com> Date: Wed, 29 Nov 2023 08:28:30 -0500 Subject: [PATCH 2/9] Add setup_databases --- django-stubs/test/utils.pyi | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/django-stubs/test/utils.pyi b/django-stubs/test/utils.pyi index a90b35774..257c3c940 100644 --- a/django-stubs/test/utils.pyi +++ b/django-stubs/test/utils.pyi @@ -10,6 +10,7 @@ from django.conf import LazySettings, Settings from django.core.checks.registry import CheckRegistry from django.db.models.lookups import Lookup, Transform from django.db.models.query_utils import RegisterLookupMixin +from django.db import DefaultConnectionProxy from django.test.runner import DiscoverRunner from django.test.testcases import SimpleTestCase @@ -34,6 +35,17 @@ class _TestState: ... def setup_test_environment(debug: bool | None = ...) -> None: ... def teardown_test_environment() -> None: ... +def setup_databases( + verbosity: int, + interactive: bool, + *, + time_keeper: Any | None = ..., + keepdb: bool = ..., + debug_sql: bool = ..., + parallel: int = ..., + aliases: Iterable[str] | None = ..., + **kwargs: Any +) -> list[tuple[DefaultConnectionProxy, str, bool]]: ... def get_runner( settings: LazySettings, test_runner_class: str | None = ... ) -> type[DiscoverRunner]: ... From 004d6932b0d62c0f40a5696432a8fb2e8b00d1fa Mon Sep 17 00:00:00 2001 From: Noelle Leigh <5957867+noelleleigh@users.noreply.github.com> Date: Wed, 29 Nov 2023 08:31:05 -0500 Subject: [PATCH 3/9] TestContextDecorator: Add more specific generic types --- django-stubs/test/utils.pyi | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/django-stubs/test/utils.pyi b/django-stubs/test/utils.pyi index 257c3c940..ed1caed66 100644 --- a/django-stubs/test/utils.pyi +++ b/django-stubs/test/utils.pyi @@ -2,8 +2,9 @@ import decimal from collections.abc import Callable, Iterable, Iterator, Mapping from contextlib import AbstractContextManager, contextmanager from decimal import Decimal +from types import TracebackType from io import StringIO -from typing import Any, TypeVar +from typing import Any, TypeVar, overload from django.apps.registry import Apps from django.conf import LazySettings, Settings @@ -19,6 +20,7 @@ _DecoratedTest = Callable[..., Any] | _TestClass _C = TypeVar("_C", bound=Callable[..., Any]) _T = TypeVar("_T") _U = TypeVar("_U") +_TestClassGeneric = TypeVar("_TestClassGeneric", bound=_TestClass) TZ_SUPPORT: bool = ... @@ -56,13 +58,21 @@ class TestContextDecorator: def __init__( self, attr_name: str | None = ..., kwarg_name: str | None = ... ) -> None: ... - def enable(self) -> Any: ... + def enable(self) -> Any | None: ... def disable(self) -> None: ... - def __enter__(self) -> Apps | None: ... - def __exit__(self, exc_type: None, exc_value: None, traceback: None) -> None: ... - def decorate_class(self, cls: _TestClass) -> _TestClass: ... + def __enter__(self) -> Any | None: ... + def __exit__( + self, + exc_type: type[Exception] | None, + exc_value: Exception | None, + traceback: TracebackType | None, + ) -> None: ... + def decorate_class(self, cls: _TestClassGeneric) -> _TestClassGeneric: ... def decorate_callable(self, func: _C) -> _C: ... - def __call__(self, decorated: _DecoratedTest) -> Any: ... + @overload + def __call__(self, decorated: _TestClassGeneric) -> _TestClassGeneric: ... + @overload + def __call__(self, decorated: _C) -> _C: ... class override_settings(TestContextDecorator): options: dict[str, Any] = ... From 4750a1763953ebe948ab97f0847138461abadf54 Mon Sep 17 00:00:00 2001 From: Noelle Leigh <5957867+noelleleigh@users.noreply.github.com> Date: Wed, 29 Nov 2023 08:55:30 -0500 Subject: [PATCH 4/9] override_settings: Remove decorate_class override Fixes less-specific type inference Also move properties to top --- django-stubs/test/utils.pyi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/django-stubs/test/utils.pyi b/django-stubs/test/utils.pyi index ed1caed66..1d9df88a9 100644 --- a/django-stubs/test/utils.pyi +++ b/django-stubs/test/utils.pyi @@ -75,11 +75,11 @@ class TestContextDecorator: def __call__(self, decorated: _C) -> _C: ... class override_settings(TestContextDecorator): + enable_exception: bool | None = ... + wrapped: Settings = ... options: dict[str, Any] = ... def __init__(self, **kwargs: Any) -> None: ... - wrapped: Settings = ... def save_options(self, test_func: _DecoratedTest) -> None: ... - def decorate_class(self, cls: type) -> type: ... class modify_settings(override_settings): wrapped: Settings From b5476df02cc0164560f7b96527342b675310461c Mon Sep 17 00:00:00 2001 From: Noelle Leigh <5957867+noelleleigh@users.noreply.github.com> Date: Wed, 29 Nov 2023 09:14:52 -0500 Subject: [PATCH 5/9] modify_settings: Move properties to top --- django-stubs/test/utils.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/django-stubs/test/utils.pyi b/django-stubs/test/utils.pyi index 1d9df88a9..790ab517a 100644 --- a/django-stubs/test/utils.pyi +++ b/django-stubs/test/utils.pyi @@ -84,9 +84,9 @@ class override_settings(TestContextDecorator): class modify_settings(override_settings): wrapped: Settings operations: list[tuple[str, dict[str, list[str] | str]]] = ... + options: dict[str, list[tuple[str, str] | str]] = ... def __init__(self, *args: Any, **kwargs: Any) -> None: ... def save_options(self, test_func: _DecoratedTest) -> None: ... - options: dict[str, list[tuple[str, str] | str]] = ... class override_system_checks(TestContextDecorator): registry: CheckRegistry = ... From 709f2a131b0e8a15021f87345a14cdf08fe14bb2 Mon Sep 17 00:00:00 2001 From: Noelle Leigh <5957867+noelleleigh@users.noreply.github.com> Date: Wed, 29 Nov 2023 09:15:03 -0500 Subject: [PATCH 6/9] override_system_checks: Move properties to top --- django-stubs/test/utils.pyi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/django-stubs/test/utils.pyi b/django-stubs/test/utils.pyi index 790ab517a..c4333a723 100644 --- a/django-stubs/test/utils.pyi +++ b/django-stubs/test/utils.pyi @@ -92,13 +92,13 @@ class override_system_checks(TestContextDecorator): registry: CheckRegistry = ... new_checks: list[Callable[..., Any]] = ... deployment_checks: list[Callable[..., Any]] | None = ... + old_checks: set[Callable[..., Any]] = ... + old_deployment_checks: set[Callable[..., Any]] = ... def __init__( self, new_checks: list[Callable[..., Any]], deployment_checks: list[Callable[..., Any]] | None = ..., ) -> None: ... - old_checks: set[Callable[..., Any]] = ... - old_deployment_checks: set[Callable[..., Any]] = ... class CaptureQueriesContext: connection: Any = ... From 5a3527d6531d881489f1d270daf2dbdb632612e9 Mon Sep 17 00:00:00 2001 From: Noelle Leigh <5957867+noelleleigh@users.noreply.github.com> Date: Wed, 29 Nov 2023 09:15:43 -0500 Subject: [PATCH 7/9] CaptureQueriesContext: Use Self for __enter__ --- django-stubs/test/utils.pyi | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/django-stubs/test/utils.pyi b/django-stubs/test/utils.pyi index c4333a723..58eaff324 100644 --- a/django-stubs/test/utils.pyi +++ b/django-stubs/test/utils.pyi @@ -5,6 +5,7 @@ from decimal import Decimal from types import TracebackType from io import StringIO from typing import Any, TypeVar, overload +from typing_extensions import Self from django.apps.registry import Apps from django.conf import LazySettings, Settings @@ -111,7 +112,7 @@ class CaptureQueriesContext: def __len__(self) -> int: ... @property def captured_queries(self) -> list[dict[str, str]]: ... - def __enter__(self) -> CaptureQueriesContext: ... + def __enter__(self) -> Self: ... def __exit__(self, exc_type: None, exc_value: None, traceback: None) -> None: ... class ignore_warnings(TestContextDecorator): From 024ba97c3c83d7a76af776bb395e53ca5e35cb0e Mon Sep 17 00:00:00 2001 From: Noelle Leigh <5957867+noelleleigh@users.noreply.github.com> Date: Wed, 29 Nov 2023 09:18:24 -0500 Subject: [PATCH 8/9] tag: Is a decorator (returns a function) --- django-stubs/test/utils.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/django-stubs/test/utils.pyi b/django-stubs/test/utils.pyi index 58eaff324..0ed9d1ca3 100644 --- a/django-stubs/test/utils.pyi +++ b/django-stubs/test/utils.pyi @@ -154,7 +154,7 @@ def captured_stdout() -> Iterator[StringIO]: ... def captured_stderr() -> Iterator[StringIO]: ... @contextmanager def freeze_time(t: float) -> Iterator[None]: ... -def tag(*tags: str) -> Any: ... +def tag(*tags: str) -> Callable[[_T], _T]: ... _Signature = str _TestDatabase = tuple[str, list[str]] From 6c20a2dae6a194125f33d83d6694ab94737087dc Mon Sep 17 00:00:00 2001 From: Noelle Leigh <5957867+noelleleigh@users.noreply.github.com> Date: Wed, 29 Nov 2023 09:19:23 -0500 Subject: [PATCH 9/9] Remove non-public APIs --- django-stubs/test/utils.pyi | 41 +------------------------------------ 1 file changed, 1 insertion(+), 40 deletions(-) diff --git a/django-stubs/test/utils.pyi b/django-stubs/test/utils.pyi index 0ed9d1ca3..91aff0325 100644 --- a/django-stubs/test/utils.pyi +++ b/django-stubs/test/utils.pyi @@ -1,17 +1,14 @@ import decimal from collections.abc import Callable, Iterable, Iterator, Mapping -from contextlib import AbstractContextManager, contextmanager +from contextlib import AbstractContextManager from decimal import Decimal from types import TracebackType -from io import StringIO from typing import Any, TypeVar, overload from typing_extensions import Self from django.apps.registry import Apps from django.conf import LazySettings, Settings from django.core.checks.registry import CheckRegistry -from django.db.models.lookups import Lookup, Transform -from django.db.models.query_utils import RegisterLookupMixin from django.db import DefaultConnectionProxy from django.test.runner import DiscoverRunner from django.test.testcases import SimpleTestCase @@ -142,40 +139,4 @@ class isolate_apps(TestContextDecorator): def __init__(self, *installed_apps: Any, **kwargs: Any) -> None: ... old_apps: Apps = ... -@contextmanager -def extend_sys_path(*paths: str) -> Iterator[None]: ... -@contextmanager -def captured_output(stream_name: Any) -> Iterator[StringIO]: ... -@contextmanager -def captured_stdin() -> Iterator[StringIO]: ... -@contextmanager -def captured_stdout() -> Iterator[StringIO]: ... -@contextmanager -def captured_stderr() -> Iterator[StringIO]: ... -@contextmanager -def freeze_time(t: float) -> Iterator[None]: ... def tag(*tags: str) -> Callable[[_T], _T]: ... - -_Signature = str -_TestDatabase = tuple[str, list[str]] - -def dependency_ordered( - test_databases: Iterable[tuple[_Signature, _TestDatabase]], - dependencies: Mapping[str, list[str]], -) -> list[tuple[_Signature, _TestDatabase]]: ... -def get_unique_databases_and_mirrors() -> ( - tuple[dict[_Signature, _TestDatabase], dict[str, Any]] -): ... -def teardown_databases( - old_config: Iterable[tuple[Any, str, bool]], - verbosity: int, - parallel: int = ..., - keepdb: bool = ..., -) -> None: ... -def require_jinja2(test_func: _C) -> _C: ... -@contextmanager -def register_lookup( - field: type[RegisterLookupMixin], - *lookups: type[Lookup[Any] | Transform], - lookup_name: str | None = ... -) -> Iterator[None]: ...