Commit 191d953c authored by Thomas Chaumeny's avatar Thomas Chaumeny Committed by Simon Charette
Browse files

Factorize some code using ContextDecorator.

parent c9c0be31
Loading
Loading
Loading
Loading
+2 −11
Original line number Diff line number Diff line
from functools import wraps

from django.db import (
    connections, DEFAULT_DB_ALIAS,
    DatabaseError, Error, ProgrammingError)
from django.utils.decorators import available_attrs
from django.utils.decorators import ContextDecorator


class TransactionManagementError(ProgrammingError):
@@ -109,7 +107,7 @@ def set_rollback(rollback, using=None):
# Decorators / context managers #
#################################

class Atomic(object):
class Atomic(ContextDecorator):
    """
    This class guarantees the atomic execution of a given block.

@@ -285,13 +283,6 @@ class Atomic(object):
                else:
                    connection.in_atomic_block = False

    def __call__(self, func):
        @wraps(func, assigned=available_attrs(func))
        def inner(*args, **kwargs):
            with self:
                return func(*args, **kwargs)
        return inner


def atomic(using=None, savepoint=True):
    # Bare decorator: @atomic -- although the first argument is called
+2 −8
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ from django.template import Template, loader, TemplateDoesNotExist
from django.template.loaders import cached
from django.test.signals import template_rendered, setting_changed
from django.utils import six
from django.utils.decorators import ContextDecorator
from django.utils.deprecation import RemovedInDjango19Warning, RemovedInDjango20Warning
from django.utils.encoding import force_str
from django.utils.translation import deactivate
@@ -146,7 +147,7 @@ def get_runner(settings, test_runner_class=None):
    return test_runner


class override_template_loaders(object):
class override_template_loaders(ContextDecorator):
    """
    Acts as a function decorator, context manager or start/end manager and
    override the template loaders. It could be used in the following ways:
@@ -174,13 +175,6 @@ class override_template_loaders(object):
    def __exit__(self, type, value, traceback):
        loader.template_source_loaders = self.old_loaders

    def __call__(self, test_func):
        @wraps(test_func)
        def inner(*args, **kwargs):
            with self:
                return test_func(*args, **kwargs)
        return inner

    @classmethod
    def override(cls, *loaders):
        if hasattr(loader, RESTORE_LOADERS_ATTR):
+20 −0
Original line number Diff line number Diff line
"Functions that help with dynamically creating decorators for views."

try:
    from contextlib import ContextDecorator
except ImportError:
    ContextDecorator = None

from functools import wraps, update_wrapper, WRAPPER_ASSIGNMENTS

from django.utils import six
@@ -124,3 +129,18 @@ def make_middleware_decorator(middleware_class):
            return _wrapped_view
        return _decorator
    return _make_decorator


if ContextDecorator is None:
    # ContextDecorator was introduced in Python 3.2
    # See https://docs.python.org/3/library/contextlib.html#contextlib.ContextDecorator
    class ContextDecorator(object):
        """
        A base class that enables a context manager to also be used as a decorator.
        """
        def __call__(self, func):
            @wraps(func, assigned=available_attrs(func))
            def inner(*args, **kwargs):
                with self:
                    return func(*args, **kwargs)
            return inner