Skip to content

Commit

Permalink
Creates a compatibility layer for transaction.[is_]managed
Browse files Browse the repository at this point in the history
  • Loading branch information
BertrandBordage committed Feb 5, 2014
1 parent 72a6dfd commit a2a353c
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 61 deletions.
24 changes: 24 additions & 0 deletions johnny/compat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# coding: utf-8

"""
Tools to ease compatibility across supported versions of Django & Python.
"""

from __future__ import unicode_literals
import django
from django.db import transaction


def is_managed(using=None):
if django.VERSION[:2] < (1, 6):
return transaction.is_managed(using=using)
return False
# Or maybe we should run the following line? I'm not sure…
# return not transaction.get_autocommit(using=using)


def managed(flag=True, using=None):
if django.VERSION[:2] < (1, 6):
transaction.managed(flag=flag, using=using)
# Maybe we should execute the following line otherwise? I'm not sure…
# transaction.set_autocommit(autocommit=not flag, using=using)
100 changes: 41 additions & 59 deletions johnny/tests/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,19 @@
except ImportError: # Python < 3.0
from Queue import Queue

import django
from django.conf import settings
from django.core.paginator import Paginator
from django.db import connection, connections, transaction
from django.db.models import Q, Count, Sum
from johnny import middleware, settings as johnny_settings, cache
from johnny.cache import get_tables_for_query, invalidate
from johnny.compat import is_managed, managed
from johnny.signals import qc_hit, qc_miss, qc_skip
from . import base
from .testapp.models import (
Genre, Book, Publisher, Person, PersonType, Issue24Model as i24m)


if django.VERSION[:2] < (1, 6):
def atomic(f):
return f
else:
from django.db.transaction import atomic


# put tests in here to be included in the testing suite
__all__ = ['MultiDbTest', 'SingleModelTest', 'MultiModelTest', 'TransactionSupportTest', 'BlackListTest', 'TransactionManagerTestCase']

Expand Down Expand Up @@ -74,8 +67,8 @@ def _post_teardown(self):
super(TransactionQueryCacheBase, self)._post_teardown()
if transaction.is_dirty():
transaction.rollback()
if transaction.is_managed():
transaction.managed(False)
if is_managed():
managed(False)

class BlackListTest(QueryCacheBase):
fixtures = base.johnny_fixtures
Expand Down Expand Up @@ -137,16 +130,16 @@ def test_basic_queries(self):
g2.save(using='second')
#fresh from cache since we saved each
with self.assertNumQueries(1, using='default'):
with self.assertNumQueries(1, using='second'):
g1 = Genre.objects.using('default').get(pk=1)
g2 = Genre.objects.using('second').get(pk=1)
g1 = Genre.objects.using('default').get(pk=1)
with self.assertNumQueries(1, using='second'):
g2 = Genre.objects.using('second').get(pk=1)
self.assertEqual(g1.title, "A default database")
self.assertEqual(g2.title, "A second database")
#should be a cache hit
with self.assertNumQueries(0, using='default'):
with self.assertNumQueries(0, using='second'):
g1 = Genre.objects.using('default').get(pk=1)
g2 = Genre.objects.using('second').get(pk=1)
g1 = Genre.objects.using('default').get(pk=1)
with self.assertNumQueries(0, using='second'):
g2 = Genre.objects.using('second').get(pk=1)

def test_cache_key_setting(self):
"""Tests that two databases use a single cached object when given the same DB cache key"""
Expand All @@ -168,9 +161,9 @@ def test_cache_key_setting(self):
g2.save(using='second')
#fresh from cache since we saved each
with self.assertNumQueries(1, using='default'):
with self.assertNumQueries(0, using='second'):
g1 = Genre.objects.using('default').get(pk=1)
g2 = Genre.objects.using('second').get(pk=1)
g1 = Genre.objects.using('default').get(pk=1)
with self.assertNumQueries(0, using='second'):
g2 = Genre.objects.using('second').get(pk=1)
johnny_settings.DB_CACHE_KEYS = old_cache_keys

def test_transactions(self):
Expand All @@ -195,7 +188,7 @@ def test_transactions(self):


# sanity check
self.assertFalse(transaction.is_managed())
self.assertFalse(is_managed())
self.assertFalse(transaction.is_dirty())
self.assertTrue("default" in getattr(settings, "DATABASES"))
self.assertTrue("second" in getattr(settings, "DATABASES"))
Expand All @@ -206,9 +199,9 @@ def test_transactions(self):
start_g1 = g1.title

transaction.enter_transaction_management(using='default')
transaction.managed(using='default')
managed(using='default')
transaction.enter_transaction_management(using='second')
transaction.managed(using='second')
managed(using='second')

g1.title = "Testing a rollback"
g2.title = "Testing a commit"
Expand All @@ -224,8 +217,8 @@ def test_transactions(self):

transaction.rollback(using='default')
transaction.commit(using='second')
transaction.managed(False, "default")
transaction.managed(False, "second")
managed(False, using='default')
managed(False, using='second')

#other thread should have seen rollback
other("Genre.objects.using('default').get(pk=1)")
Expand Down Expand Up @@ -272,7 +265,7 @@ def test_savepoints(self):
return

# sanity check
self.assertFalse(transaction.is_managed())
self.assertFalse(is_managed())
self.assertFalse(transaction.is_dirty())
self.assertTrue("default" in getattr(settings, "DATABASES"))
self.assertTrue("second" in getattr(settings, "DATABASES"))
Expand All @@ -282,9 +275,9 @@ def test_savepoints(self):
g2 = Genre.objects.using("second").get(pk=1)

transaction.enter_transaction_management(using='default')
transaction.managed(using='default')
managed(using='default')
transaction.enter_transaction_management(using='second')
transaction.managed(using='second')
managed(using='second')

g1.title = "Rollback savepoint"
g1.save()
Expand Down Expand Up @@ -326,7 +319,7 @@ def test_savepoints(self):
g2 = Genre.objects.using("second").get(pk=1)

transaction.commit(using="second")
transaction.managed(False, "second")
managed(False, using='second')

with self.assertNumQueries(0, using='second'):
g2 = Genre.objects.using("second").get(pk=1)
Expand All @@ -339,7 +332,6 @@ def test_savepoints(self):
self.assertEqual(ostart.title, g2.title)
self.assertTrue(hit)

transaction.managed(False, "default")
transaction.leave_transaction_management("default")
transaction.leave_transaction_management("second")

Expand Down Expand Up @@ -644,14 +636,13 @@ def miss(*args, **kwargs):

def setUp(self):
super(TransactionSupportTest, self).setUp()
if django.VERSION[:2] >= (1, 6):
transaction.set_autocommit(True)
managed(False)

def tearDown(self):
if transaction.is_managed():
if is_managed():
if transaction.is_dirty():
transaction.rollback()
transaction.managed(False)
managed(False)
transaction.leave_transaction_management()

def test_transaction_commit(self):
Expand All @@ -660,7 +651,7 @@ def test_transaction_commit(self):
print("\n Skipping test requiring multiple threads.")
return

self.assertFalse(transaction.is_managed())
self.assertFalse(is_managed())
self.assertFalse(transaction.is_dirty())
cache.local.clear()
q = Queue()
Expand All @@ -674,7 +665,7 @@ def test_transaction_commit(self):
self.assertEqual(ostart, start)
# enter manual transaction management
transaction.enter_transaction_management()
transaction.managed()
managed()
start.title = 'Jackie Chan Novels'
# local invalidation, this key should hit the localstore!
nowlen = len(cache.local)
Expand All @@ -693,7 +684,7 @@ def test_transaction_commit(self):
hit, ostart = q.get()
self.assertFalse(hit)
self.assertEqual(ostart.title, start.title)
transaction.managed(False)
managed(False)
transaction.leave_transaction_management()

def test_transaction_rollback(self):
Expand All @@ -705,7 +696,7 @@ def test_transaction_rollback(self):
print("\n Skipping test requiring multiple threads.")
return

self.assertFalse(transaction.is_managed())
self.assertFalse(is_managed())
self.assertFalse(transaction.is_dirty())
cache.local.clear()
q = Queue()
Expand All @@ -720,7 +711,7 @@ def test_transaction_rollback(self):
self.assertEqual(ostart, start)
# enter manual transaction management
transaction.enter_transaction_management()
transaction.managed()
managed()
start.title = 'Jackie Chan Novels'
# local invalidation, this key should hit the localstore!
nowlen = len(cache.local)
Expand Down Expand Up @@ -749,21 +740,19 @@ def test_transaction_rollback(self):
self.assertTrue(hit)
start = Genre.objects.get(id=1)
self.assertEqual(ostart.title, start.title)
transaction.managed(False)
managed(False)
transaction.leave_transaction_management()

@atomic
def test_savepoint_rollback(self):
"""Tests rollbacks of savepoints"""
if not connection.features.uses_savepoints:
return
if django.VERSION[:2] < (1, 6):
self.assertFalse(transaction.is_managed())
self.assertFalse(transaction.is_dirty())
self.assertFalse(is_managed())
self.assertFalse(transaction.is_dirty())
cache.local.clear()
if django.VERSION[:2] < (1, 6):
transaction.enter_transaction_management()
transaction.managed()
managed()
transaction.enter_transaction_management()

g = Genre.objects.get(pk=1)
start_title = g.title
g.title = "Adventures in Savepoint World"
Expand All @@ -781,21 +770,18 @@ def test_savepoint_rollback(self):
transaction.rollback()
g = Genre.objects.get(pk=1)
self.assertEqual(g.title, start_title)
if django.VERSION[:2] < (1, 6):
transaction.managed(False)
transaction.leave_transaction_management()

def test_savepoint_commit(self):
"""Tests a transaction commit (release)
The release actually pushes the savepoint back into the dirty stack,
but at the point it was saved in the transaction"""
if not connection.features.uses_savepoints:
return
self.assertFalse(transaction.is_managed())
self.assertFalse(is_managed())
self.assertFalse(transaction.is_dirty())
cache.local.clear()
transaction.enter_transaction_management()
transaction.managed()
managed()
g = Genre.objects.get(pk=1)
start_title = g.title
g.title = "Adventures in Savepoint World"
Expand All @@ -819,26 +805,22 @@ def test_savepoint_commit(self):
with self.assertNumQueries(0):
g = Genre.objects.get(pk=1)
self.assertEqual(g.title, "In the Void")
transaction.managed(False)
managed(False)
transaction.leave_transaction_management()


class TransactionManagerTestCase(base.TransactionJohnnyTestCase):

def setUp(self):
self.middleware = middleware.QueryCacheMiddleware()

def tearDown(self):
if transaction.is_managed():
transaction.managed(False)
if is_managed():
managed(False)

def test_savepoint_localstore_flush(self):
"""
This is a very simple test to see if savepoints will actually
be committed, i.e. flushed out from localstore into cache.
"""
transaction.enter_transaction_management()
transaction.managed()
managed()

TABLE_NAME = 'test_table'
cache_backend = cache.get_backend()
Expand Down
4 changes: 2 additions & 2 deletions johnny/transaction.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import django
from django.db import transaction, connection, DEFAULT_DB_ALIAS

from johnny import settings as johnny_settings
from johnny.compat import is_managed
from johnny.decorators import wraps, available_attrs


Expand Down Expand Up @@ -49,7 +49,7 @@ def _clear_sid_stack(self, using=None):
del self.local['trans_sids']

def is_managed(self, using=None):
return transaction.is_managed(using=using)
return is_managed(using=using)

def get(self, key, default=None, using=None):
if self.is_managed(using) and self._patched_var:
Expand Down

0 comments on commit a2a353c

Please sign in to comment.