PageRenderTime 44ms CodeModel.GetById 9ms app.highlight 29ms RepoModel.GetById 2ms app.codeStats 0ms

/johnny/tests/base.py

https://bitbucket.org/jmoiron/johnny-cache/
Python | 145 lines | 122 code | 15 blank | 8 comment | 14 complexity | 02fc9201a8cd820b31f6914319384057 MD5 | raw file
  1#!/usr/bin/env python
  2# -*- coding: utf-8 -*-
  3
  4"""Base test class for Johnny Cache Tests."""
  5
  6import sys
  7
  8import django
  9from django.test import TestCase, TransactionTestCase
 10from django.conf import settings
 11from django.core.management import call_command
 12from django.db.models.loading import load_app
 13
 14from johnny import settings as johnny_settings
 15from johnny.decorators import wraps, available_attrs
 16
 17# order matters here;  I guess we aren't deferring foreign key checking :\
 18johnny_fixtures = ['authors.json', 'genres.json', 'publishers.json', 'books.json']
 19
 20def show_johnny_signals(hit=None, miss=None):
 21    """A decorator that can be put on a test function that will show the
 22    johnny hit/miss signals by default, or do what is provided by the hit
 23    and miss keyword args."""
 24    from pprint import pformat
 25    def _hit(*args, **kwargs):
 26        print "hit:\n\t%s\n\t%s\n" % (pformat(args), pformat(kwargs))
 27    def _miss(*args, **kwargs):
 28        print "miss:\n\t%s\n\t%s\n" % (pformat(args), pformat(kwargs))
 29    hit = hit or _hit
 30    miss = miss or _miss
 31    def deco(func):
 32        @wraps(func, assigned=available_attrs(func))
 33        def wrapped(*args, **kwargs):
 34            from johnny.signals import qc_hit, qc_miss
 35            qc_hit.connect(hit)
 36            qc_miss.connect(miss)
 37            try:
 38                ret = func(*args, **kwargs)
 39            finally:
 40                qc_hit.disconnect(hit)
 41                qc_miss.disconnect(miss)
 42            return ret
 43        return wrapped
 44    return deco
 45
 46def _pre_setup(self):
 47    self.saved_INSTALLED_APPS = settings.INSTALLED_APPS
 48    self.saved_DEBUG = settings.DEBUG
 49    test_app = 'johnny.tests.testapp'
 50    settings.INSTALLED_APPS = tuple(
 51        list(self.saved_INSTALLED_APPS) + [test_app]
 52    )
 53    settings.DEBUG = True
 54    # load our fake application and syncdb
 55    load_app(test_app)
 56    call_command('syncdb', verbosity=0, interactive=False)
 57    if hasattr(settings, 'DATABASES'):
 58        for dbname in settings.DATABASES:
 59            if dbname != 'default':
 60                call_command('syncdb', verbosity=0, interactive=False, database=dbname)
 61
 62def _post_teardown(self):
 63    settings.INSTALLED_APPS = self.saved_INSTALLED_APPS
 64    settings.DEBUG = self.saved_DEBUG
 65
 66class JohnnyTestCase(TestCase):
 67    def _pre_setup(self):
 68        _pre_setup(self)
 69        super(JohnnyTestCase, self)._pre_setup()
 70
 71    def _post_teardown(self):
 72        _post_teardown(self)
 73        super(JohnnyTestCase, self)._post_teardown()
 74
 75class TransactionJohnnyTestCase(TransactionTestCase):
 76    def _pre_setup(self):
 77        _pre_setup(self)
 78        super(TransactionJohnnyTestCase, self)._pre_setup()
 79
 80    def _post_teardown(self):
 81        _post_teardown(self)
 82        super(TransactionJohnnyTestCase, self)._post_teardown()
 83
 84class TransactionJohnnyWebTestCase(TransactionJohnnyTestCase):
 85    def _pre_setup(self):
 86        from johnny import middleware
 87        self.saved_MIDDLEWARE_CLASSES = settings.MIDDLEWARE_CLASSES
 88        if getattr(self.__class__, 'middleware', None):
 89            settings.MIDDLEWARE_CLASSES = self.__class__.middleware
 90        self.saved_DISABLE_SETTING = getattr(johnny_settings, 'DISABLE_QUERYSET_CACHE', False)
 91        johnny_settings.DISABLE_QUERYSET_CACHE = False
 92        self.saved_TEMPLATE_LOADERS = settings.TEMPLATE_LOADERS
 93        if django.VERSION[:2] < (1, 3):
 94            if 'django.template.loaders.app_directories.load_template_source' not in settings.TEMPLATE_LOADERS:
 95                settings.TEMPLATE_LOADERS += ('django.template.loaders.app_directories.load_template_source',)
 96        else:
 97            if 'django.template.loaders.app_directories.Loader' not in settings.TEMPLATE_LOADERS:
 98                settings.TEMPLATE_LOADERS += ('django.template.loaders.app_directories.Loader',)
 99        self.middleware = middleware.QueryCacheMiddleware()
100        self.saved_ROOT_URLCONF = settings.ROOT_URLCONF
101        settings.ROOT_URLCONF = 'johnny.tests.testapp.urls'
102        super(TransactionJohnnyWebTestCase, self)._pre_setup()
103
104    def _post_teardown(self):
105        self.middleware.unpatch()
106        johnny_settings.DISABLE_QUERYSET_CACHE = self.saved_DISABLE_SETTING
107        settings.MIDDLEWARE_CLASSES = self.saved_MIDDLEWARE_CLASSES
108        settings.ROOT_URLCONF = self.saved_ROOT_URLCONF
109        settings.TEMPLATE_LOADERS = self.saved_TEMPLATE_LOADERS
110        super(TransactionJohnnyWebTestCase, self)._post_teardown()
111
112class message_queue(object):
113    """Return a message queue that gets 'hit' or 'miss' messages.  The signal
114    handlers use weakrefs, so if we don't save references to this object they
115    will get gc'd pretty fast."""
116    def __init__(self):
117        from johnny.signals import qc_hit, qc_miss
118        from Queue import Queue as queue
119        self.q = queue()
120        qc_hit.connect(self._hit)
121        qc_miss.connect(self._miss)
122
123    def _hit(self, *a, **k): self.q.put(True)
124    def _miss(self, *a, **k): self.q.put(False)
125
126    def clear(self):
127        while not self.q.empty():
128            self.q.get_nowait()
129    def get(self): return self.q.get()
130    def get_nowait(self): return self.q.get_nowait()
131    def qsize(self): return self.q.qsize()
132    def empty(self): return self.q.empty()
133
134def supports_transactions(con):
135    """A convenience function which will work across multiple django versions
136    that checks whether or not a connection supports transactions."""
137    features = con.features.__dict__
138    vendor = con.vendor
139    if features.get("supports_transactions", False):
140        if vendor == "mysql" and not features.get('_storage_engine', '') == "InnoDB":
141            print "MySQL connection reports transactions supported but storage engine != InnoDB."
142            return False
143        return True
144    return False
145