Add better typings plus test for transaction.atomic.

- All cases are handled, including bare decorator (@transaction.atomic).
- Decorated function's signature is preserved when type-checking.
This commit is contained in:
Seth Yastrov
2019-02-19 07:55:50 +01:00
parent ab73d53ae5
commit 67c99434e5
2 changed files with 62 additions and 9 deletions

View File

@@ -1,5 +1,4 @@
from contextlib import ContextDecorator
from typing import Any, Callable, Optional, Union, Iterator, overload, ContextManager
from typing import Any, Callable, Optional, overload, TypeVar
from django.db import ProgrammingError
@@ -18,19 +17,23 @@ def get_rollback(using: None = ...) -> bool: ...
def set_rollback(rollback: bool, using: Optional[str] = ...) -> None: ...
def on_commit(func: Callable, using: None = ...) -> None: ...
class Atomic(ContextDecorator):
_C = TypeVar("_C", bound=Callable) # Any callable
# Don't inherit from ContextDecorator, so we can provide a more specific signature for __call__
class Atomic:
using: Optional[str] = ...
savepoint: bool = ...
def __init__(self, using: Optional[str], savepoint: bool) -> None: ...
# When decorating, return the decorated function as-is, rather than clobbering it as ContextDecorator does.
def __call__(self, func: _C) -> _C: ...
def __enter__(self) -> None: ...
def __exit__(self, exc_type: None, exc_value: None, traceback: None) -> None: ...
# Bare decorator
@overload
def atomic() -> Atomic: ...
def atomic(using: _C) -> _C: ...
# Decorator or context-manager with parameters
@overload
def atomic(using: Optional[str] = ...,) -> ContextManager[Atomic]: ...
@overload
def atomic(using: Callable = ...) -> Callable: ...
@overload
def atomic(using: Optional[str] = ..., savepoint: bool = ...) -> ContextManager[Atomic]: ...
def atomic(using: Optional[str] = None, savepoint: bool = True) -> Atomic: ...
def non_atomic_requests(using: Callable = ...) -> Callable: ...