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

Tests: Migrate db/test_transaction.yml to 'assert_type' tests #2209

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
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
2 changes: 1 addition & 1 deletion django-stubs/db/transaction.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def set_rollback(rollback: bool, using: str | None = ...) -> None: ...
def mark_for_rollback_on_error(using: str | None = ...) -> Iterator[None]: ...
def on_commit(func: Callable[[], object], using: str | None = ..., robust: bool = ...) -> None: ...

_C = TypeVar("_C", bound=Callable) # Any callable
_C = TypeVar("_C", bound=Callable[..., Any]) # Any callable

# Don't inherit from ContextDecorator, so we can provide a more specific signature for __call__
class Atomic:
Expand Down
73 changes: 73 additions & 0 deletions tests/assert_type/db/test_transaction.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
from collections.abc import Callable
from typing import List

from django.db.transaction import atomic, non_atomic_requests
from django.http import HttpRequest, HttpResponse


@atomic
def func1(x: int) -> List[int]: ...


x1: Callable[[int], List[int]] = func1
flaeppe marked this conversation as resolved.
Show resolved Hide resolved
func1("str") # type: ignore[arg-type] # pyright: ignore[reportArgumentType]


@atomic(using="bla", savepoint=False)
def func2(x: int) -> List[int]: ...


x1 = func2
func2("str") # type: ignore[arg-type] # pyright: ignore[reportArgumentType]


@atomic()
def func3(param1: str, param2: int) -> bool: ...


x2: Callable[[str, int], bool] = func3
func3(1.0, 2.0) # type: ignore[arg-type] # pyright: ignore[reportArgumentType]


class ClassWithAtomicMethod:
@atomic
def method1(self, abc: int) -> str: ...
@atomic(savepoint=True)
def method2(self) -> None: ...
@atomic(using="db", savepoint=True)
def method3(self, myparam: str) -> int: ...


# E: Argument 1 to "atomic_method1" of "ClassWithAtomicMethod" has incompatible type "str"; expected "int"
ClassWithAtomicMethod().method1("abc") # type: ignore[arg-type] # pyright: ignore[reportArgumentType]

x3: Callable[[int], str] = ClassWithAtomicMethod().method1
ClassWithAtomicMethod().method1(1.0) # type: ignore[arg-type] # pyright: ignore[reportArgumentType]

x4: Callable[[], None] = ClassWithAtomicMethod().method2
ClassWithAtomicMethod().method2(1.0) # type: ignore[call-arg] # pyright: ignore[reportCallIssue]

x5: Callable[[str], int] = ClassWithAtomicMethod().method3
ClassWithAtomicMethod().method3(1.0) # type: ignore[arg-type] # pyright: ignore[reportArgumentType]


with atomic():
...
with atomic(using="mydb", savepoint=False, durable=True):
...


@non_atomic_requests
def view_func1(request: HttpRequest) -> HttpResponse: ...


x6: Callable[[HttpRequest], HttpResponse] = view_func1
view_func1(1) # type: ignore[arg-type] # pyright: ignore[reportArgumentType]


@non_atomic_requests
def view_func2(request: HttpRequest, arg: str) -> HttpResponse: ...


x7: Callable[[HttpRequest, str], HttpResponse] = view_func2
view_func2(1, 1.0) # type: ignore[arg-type] # pyright: ignore[reportArgumentType]
29 changes: 0 additions & 29 deletions tests/typecheck/db/test_transaction.yml

This file was deleted.

46 changes: 0 additions & 46 deletions tests/typecheck/test_helpers.yml
Original file line number Diff line number Diff line change
@@ -1,49 +1,3 @@
- case: transaction_atomic_contextmanager
main: |
from django.db import transaction
with transaction.atomic():
pass
with transaction.atomic(using="mydb"):
pass
with transaction.atomic(using="mydb", savepoint=False):
pass
with transaction.atomic(using="mydb", savepoint=False, durable=True):
pass

- case: transaction_atomic_decorator
main: |
from django.db import transaction

@transaction.atomic()
def decorated_func(param1: str, param2: int) -> bool:
pass
# Ensure that the function's type is preserved
reveal_type(decorated_func) # N: Revealed type is "def (param1: builtins.str, param2: builtins.int) -> builtins.bool"

@transaction.atomic(using="mydb")
def decorated_func_using(param1: str, param2: int) -> bool:
pass
# Ensure that the function's type is preserved
reveal_type(decorated_func_using) # N: Revealed type is "def (param1: builtins.str, param2: builtins.int) -> builtins.bool"

class ClassWithAtomicMethod:
# Bare decorator
@transaction.atomic
def atomic_method1(self, abc: int) -> str:
pass
@transaction.atomic(savepoint=True)
def atomic_method2(self) -> None:
pass
@transaction.atomic(using="db", savepoint=True)
def atomic_method3(self, myparam: str) -> int:
pass
ClassWithAtomicMethod().atomic_method1("abc") # E: Argument 1 to "atomic_method1" of "ClassWithAtomicMethod" has incompatible type "str"; expected "int" [arg-type]
# Ensure that the method's type is preserved
reveal_type(ClassWithAtomicMethod().atomic_method1) # N: Revealed type is "def (abc: builtins.int) -> builtins.str"
# Ensure that the method's type is preserved
reveal_type(ClassWithAtomicMethod().atomic_method3) # N: Revealed type is "def (myparam: builtins.str) -> builtins.int"


- case: mark_safe_decorator_and_function
main: |
from django.utils.safestring import mark_safe
Expand Down
Loading