Factorize some code using ContextDecorator.
This commit is contained in:
parent
c9c0be31c5
commit
191d953c99
|
@ -1,9 +1,7 @@
|
||||||
from functools import wraps
|
|
||||||
|
|
||||||
from django.db import (
|
from django.db import (
|
||||||
connections, DEFAULT_DB_ALIAS,
|
connections, DEFAULT_DB_ALIAS,
|
||||||
DatabaseError, Error, ProgrammingError)
|
DatabaseError, Error, ProgrammingError)
|
||||||
from django.utils.decorators import available_attrs
|
from django.utils.decorators import ContextDecorator
|
||||||
|
|
||||||
|
|
||||||
class TransactionManagementError(ProgrammingError):
|
class TransactionManagementError(ProgrammingError):
|
||||||
|
@ -109,7 +107,7 @@ def set_rollback(rollback, using=None):
|
||||||
# Decorators / context managers #
|
# Decorators / context managers #
|
||||||
#################################
|
#################################
|
||||||
|
|
||||||
class Atomic(object):
|
class Atomic(ContextDecorator):
|
||||||
"""
|
"""
|
||||||
This class guarantees the atomic execution of a given block.
|
This class guarantees the atomic execution of a given block.
|
||||||
|
|
||||||
|
@ -285,13 +283,6 @@ class Atomic(object):
|
||||||
else:
|
else:
|
||||||
connection.in_atomic_block = False
|
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):
|
def atomic(using=None, savepoint=True):
|
||||||
# Bare decorator: @atomic -- although the first argument is called
|
# Bare decorator: @atomic -- although the first argument is called
|
||||||
|
|
|
@ -18,6 +18,7 @@ from django.template import Template, loader, TemplateDoesNotExist
|
||||||
from django.template.loaders import cached
|
from django.template.loaders import cached
|
||||||
from django.test.signals import template_rendered, setting_changed
|
from django.test.signals import template_rendered, setting_changed
|
||||||
from django.utils import six
|
from django.utils import six
|
||||||
|
from django.utils.decorators import ContextDecorator
|
||||||
from django.utils.deprecation import RemovedInDjango19Warning, RemovedInDjango20Warning
|
from django.utils.deprecation import RemovedInDjango19Warning, RemovedInDjango20Warning
|
||||||
from django.utils.encoding import force_str
|
from django.utils.encoding import force_str
|
||||||
from django.utils.translation import deactivate
|
from django.utils.translation import deactivate
|
||||||
|
@ -146,7 +147,7 @@ def get_runner(settings, test_runner_class=None):
|
||||||
return test_runner
|
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
|
Acts as a function decorator, context manager or start/end manager and
|
||||||
override the template loaders. It could be used in the following ways:
|
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):
|
def __exit__(self, type, value, traceback):
|
||||||
loader.template_source_loaders = self.old_loaders
|
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
|
@classmethod
|
||||||
def override(cls, *loaders):
|
def override(cls, *loaders):
|
||||||
if hasattr(loader, RESTORE_LOADERS_ATTR):
|
if hasattr(loader, RESTORE_LOADERS_ATTR):
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
"Functions that help with dynamically creating decorators for views."
|
"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 functools import wraps, update_wrapper, WRAPPER_ASSIGNMENTS
|
||||||
|
|
||||||
from django.utils import six
|
from django.utils import six
|
||||||
|
@ -124,3 +129,18 @@ def make_middleware_decorator(middleware_class):
|
||||||
return _wrapped_view
|
return _wrapped_view
|
||||||
return _decorator
|
return _decorator
|
||||||
return _make_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
|
||||||
|
|
Loading…
Reference in New Issue