Drops Django 1.6 & Python 2.6 support.

This commit is contained in:
Bertrand Bordage 2015-04-11 01:57:13 +02:00
parent 9016c650ac
commit 16e14c9219
18 changed files with 58 additions and 109 deletions

View File

@ -261,8 +261,7 @@ def create_data(using):
if __name__ == '__main__': if __name__ == '__main__':
if django.VERSION[:2] >= (1, 7): django.setup()
django.setup()
write_conditions() write_conditions()

View File

@ -1,2 +1,4 @@
__version__ = (1, 0, 0) __version__ = (1, 0, 0)
version_string = '.'.join(str(n) for n in __version__) version_string = '.'.join(str(n) for n in __version__)
default_app_config = 'cachalot.apps.CachalotConfig'

13
cachalot/apps.py Normal file
View File

@ -0,0 +1,13 @@
from django.apps import AppConfig
from .monkey_patch import patch
class CachalotConfig(AppConfig):
name = 'cachalot'
patched = False
def ready(self):
if not self.patched:
patch()
self.patched = True

View File

@ -3,8 +3,7 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from threading import local from threading import local
# TODO: Replace with caches[CACHALOT_CACHE] when we drop Django 1.6 support. from django.core.cache import caches
from django.core.cache import get_cache as get_django_cache
from django.db import connections from django.db import connections
from .settings import cachalot_settings from .settings import cachalot_settings
@ -31,7 +30,7 @@ class CacheHandler(local):
min_level = -len(self.atomic_caches) min_level = -len(self.atomic_caches)
if atomic_level < min_level: if atomic_level < min_level:
return get_django_cache(cache_alias) return caches[cache_alias]
return self.get_atomic_cache(cache_alias, atomic_level) return self.get_atomic_cache(cache_alias, atomic_level)
def enter_atomic(self): def enter_atomic(self):

View File

@ -1,5 +0,0 @@
from .monkey_patch import is_patched, patch
if not is_patched():
patch()

View File

@ -5,17 +5,9 @@ from collections import Iterable
from functools import wraps from functools import wraps
from time import time from time import time
from django import VERSION as django_version from django.db.backends.utils import CursorWrapper
from django.conf import settings
if django_version >= (1, 7):
from django.db.backends.utils import CursorWrapper
else:
from django.db.backends.util import CursorWrapper
from django.db.models.query import EmptyResultSet from django.db.models.query import EmptyResultSet
if django_version >= (1, 7): from django.db.models.signals import post_migrate
from django.db.models.signals import post_migrate
else:
from django.db.models.signals import post_syncdb as post_migrate
from django.db.models.sql.compiler import ( from django.db.models.sql.compiler import (
SQLCompiler, SQLInsertCompiler, SQLUpdateCompiler, SQLDeleteCompiler) SQLCompiler, SQLInsertCompiler, SQLUpdateCompiler, SQLDeleteCompiler)
from django.db.transaction import Atomic, get_connection from django.db.transaction import Atomic, get_connection
@ -32,13 +24,6 @@ from .utils import (
WRITE_COMPILERS = (SQLInsertCompiler, SQLUpdateCompiler, SQLDeleteCompiler) WRITE_COMPILERS = (SQLInsertCompiler, SQLUpdateCompiler, SQLDeleteCompiler)
PATCHED = False
def is_patched():
return PATCHED
def _unset_raw_connection(original): def _unset_raw_connection(original):
def inner(compiler, *args, **kwargs): def inner(compiler, *args, **kwargs):
compiler.connection.raw = False compiler.connection.raw = False
@ -178,21 +163,14 @@ def _patch_tests():
def _invalidate_on_migration(sender, **kwargs): def _invalidate_on_migration(sender, **kwargs):
db_alias = kwargs['using'] if django_version >= (1, 7) else kwargs['db'] db_alias = kwargs['using']
invalidate_all(db_alias=db_alias) invalidate_all(db_alias=db_alias)
def patch(): def patch():
global PATCHED
post_migrate.connect(_invalidate_on_migration) post_migrate.connect(_invalidate_on_migration)
if 'south' in settings.INSTALLED_APPS:
from south.signals import post_migrate as south_post_migrate
south_post_migrate.connect(_invalidate_on_migration)
_patch_cursor() _patch_cursor()
_patch_tests() _patch_tests()
_patch_atomic() _patch_atomic()
_patch_orm() _patch_orm()
PATCHED = True

View File

@ -1,10 +1,7 @@
# coding: utf-8 # coding: utf-8
from __future__ import unicode_literals from __future__ import unicode_literals
try: from unittest import skipIf
from unittest import skipIf
except ImportError: # For Python 2.6
from unittest2 import skipIf
from django.conf import settings from django.conf import settings
from django.contrib.auth.models import User from django.contrib.auth.models import User

View File

@ -1,10 +1,7 @@
# coding: utf-8 # coding: utf-8
from __future__ import unicode_literals from __future__ import unicode_literals
try: from unittest import skipIf
from unittest import skipIf
except ImportError: # For Python 2.6
from unittest2 import skipIf
from django.conf import settings from django.conf import settings
from django.db import DEFAULT_DB_ALIAS, connections from django.db import DEFAULT_DB_ALIAS, connections

View File

@ -1,10 +1,7 @@
# coding: utf-8 # coding: utf-8
from __future__ import unicode_literals from __future__ import unicode_literals
try: from unittest import skipIf
from unittest import skipIf
except ImportError: # For Python 2.6
from unittest2 import skipIf
from django.conf import settings from django.conf import settings
from django.core.cache import DEFAULT_CACHE_ALIAS from django.core.cache import DEFAULT_CACHE_ALIAS

View File

@ -1,12 +1,7 @@
# coding: utf-8 # coding: utf-8
from __future__ import unicode_literals from __future__ import unicode_literals
try:
from unittest import skipIf
except ImportError: # For Python 2.6
from unittest2 import skipIf
from django import VERSION as django_version
from django.contrib.auth.models import User, Permission, Group from django.contrib.auth.models import User, Permission, Group
from django.core.exceptions import MultipleObjectsReturned from django.core.exceptions import MultipleObjectsReturned
from django.core.management import call_command from django.core.management import call_command
@ -79,8 +74,6 @@ class WriteTestCase(TransactionTestCase):
data2 = list(Test.objects.all()) data2 = list(Test.objects.all())
self.assertListEqual(data2, [t]) self.assertListEqual(data2, [t])
@skipIf(django_version < (1, 7),
'QuerySet.update_or_create is not implemented in Django < 1.7')
def test_update_or_create(self): def test_update_or_create(self):
with self.assertNumQueries(1): with self.assertNumQueries(1):
self.assertListEqual(list(Test.objects.all()), []) self.assertListEqual(list(Test.objects.all()), [])
@ -821,7 +814,7 @@ class DatabaseCommandTestCase(TransactionTestCase):
call_command('flush', verbosity=0, interactive=False) call_command('flush', verbosity=0, interactive=False)
if django_version >= (1, 7) and connection.vendor == 'mysql': if connection.vendor == 'mysql':
# We need to reopen the connection or Django # We need to reopen the connection or Django
# will execute an extra SQL request below. # will execute an extra SQL request below.
connection.cursor() connection.cursor()
@ -836,7 +829,7 @@ class DatabaseCommandTestCase(TransactionTestCase):
call_command('loaddata', 'cachalot/tests/loaddata_fixture.json', call_command('loaddata', 'cachalot/tests/loaddata_fixture.json',
verbosity=0, interactive=False) verbosity=0, interactive=False)
if django_version >= (1, 7) and connection.vendor == 'mysql': if connection.vendor == 'mysql':
# We need to reopen the connection or Django # We need to reopen the connection or Django
# will execute an extra SQL request below. # will execute an extra SQL request below.
connection.cursor() connection.cursor()

View File

@ -4,14 +4,9 @@ from __future__ import unicode_literals
from hashlib import sha1 from hashlib import sha1
from time import time from time import time
import django
from django.db import connections from django.db import connections
from django.db.models.sql.where import ExtraWhere, SubqueryConstraint from django.db.models.sql.where import ExtraWhere, SubqueryConstraint
DJANGO_GTE_1_7 = django.VERSION[:2] >= (1, 7) from django.utils.module_loading import import_string
if DJANGO_GTE_1_7:
from django.utils.module_loading import import_string
else:
from django.utils.module_loading import import_by_path as import_string
from django.utils.six import PY3 from django.utils.six import PY3
from .settings import cachalot_settings from .settings import cachalot_settings
@ -87,9 +82,8 @@ def _find_subqueries(children):
yield child.query_object.query yield child.query_object.query
else: else:
rhs = None rhs = None
if DJANGO_GTE_1_7: if hasattr(child, 'rhs'):
if hasattr(child, 'rhs'): rhs = child.rhs
rhs = child.rhs
elif isinstance(child, tuple): elif isinstance(child, tuple):
rhs = child[-1] rhs = child[-1]
if hasattr(rhs, 'query'): if hasattr(rhs, 'query'):

View File

@ -4,16 +4,14 @@ Quick start
Requirements Requirements
............ ............
- Django 1.6 or 1.7 - Django 1.7 or 1.8
- Python 2.6, 2.7, 3.2, 3.3, or 3.4 - Python 2.7, 3.2, 3.3, or 3.4
- a cache configured as ``'default'`` with one of these backends: - a cache configured as ``'default'`` with one of these backends:
- `django-redis <https://github.com/niwibe/django-redis>`_ - `django-redis <https://github.com/niwibe/django-redis>`_
- `memcached <https://docs.djangoproject.com/en/1.7/topics/cache/#memcached>`_ - `memcached <https://docs.djangoproject.com/en/1.7/topics/cache/#memcached>`_
(using either python-memcached or pylibmc (but pylibmc is only supported (using either python-memcached or pylibmc)
with Django >= 1.7))
- `filebased <https://docs.djangoproject.com/en/1.7/topics/cache/#filesystem-caching>`_ - `filebased <https://docs.djangoproject.com/en/1.7/topics/cache/#filesystem-caching>`_
(only with Django >= 1.7 as it was not thread-safe before)
- `locmem <https://docs.djangoproject.com/en/1.7/topics/cache/#local-memory-caching>`_ - `locmem <https://docs.djangoproject.com/en/1.7/topics/cache/#local-memory-caching>`_
(but its not shared between processes, see :ref:`Limits`) (but its not shared between processes, see :ref:`Limits`)

View File

@ -1 +1 @@
Django>=1.6 Django>=1.7

View File

@ -9,8 +9,7 @@ import django
if __name__ == '__main__': if __name__ == '__main__':
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings') os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings')
if django.VERSION[:2] >= (1, 7): django.setup()
django.setup()
from django.test.runner import DiscoverRunner from django.test.runner import DiscoverRunner
test_runner = DiscoverRunner(verbosity=2) test_runner = DiscoverRunner(verbosity=2)
failures = test_runner.run_tests(['cachalot.tests']) failures = test_runner.run_tests(['cachalot.tests'])

View File

@ -5,6 +5,3 @@ MySQL-python
django-redis django-redis
python-memcached python-memcached
pylibmc pylibmc
South
# For Python 2.6
unittest2

View File

@ -4,4 +4,3 @@ psycopg2
https://github.com/clelland/MySQL-for-Python-3/tarball/master https://github.com/clelland/MySQL-for-Python-3/tarball/master
django-redis django-redis
python3-memcached python3-memcached
South

View File

@ -3,8 +3,6 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import os import os
import django
DATABASES = { DATABASES = {
'sqlite3': { 'sqlite3': {
@ -26,26 +24,12 @@ DATABASES = {
} }
for alias in DATABASES: for alias in DATABASES:
test_db_name = 'test_' + DATABASES[alias]['NAME'] test_db_name = 'test_' + DATABASES[alias]['NAME']
if django.VERSION < (1, 7): DATABASES[alias]['TEST'] = {'NAME': test_db_name}
DATABASES[alias]['TEST_NAME'] = test_db_name
else:
DATABASES[alias]['TEST'] = {'NAME': test_db_name}
DATABASES['default'] = DATABASES.pop(os.environ.get('DB_ENGINE', 'sqlite3')) DATABASES['default'] = DATABASES.pop(os.environ.get('DB_ENGINE', 'sqlite3'))
CACHES = { CACHES = {
'locmem': {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
'OPTIONS': {
# We want that limit to be infinite, otherwise we cant
# reliably count the number of SQL queries executed in tests.
# In this context, 10e9 is enough to be considered
# infinite.
'MAX_ENTRIES': 10e9,
}
},
'redis': { 'redis': {
'BACKEND': 'django_redis.cache.RedisCache', 'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION': 'redis://127.0.0.1:6379/0', 'LOCATION': 'redis://127.0.0.1:6379/0',
@ -60,24 +44,35 @@ CACHES = {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': '127.0.0.1:11211', 'LOCATION': '127.0.0.1:11211',
}, },
} 'locmem': {
if django.VERSION >= (1, 7): 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
CACHES['filebased'] = { 'OPTIONS': {
# We want that limit to be infinite, otherwise we cant
# reliably count the number of SQL queries executed in tests.
# In this context, 10e9 is enough to be considered
# infinite.
'MAX_ENTRIES': 10e9,
}
},
'filebased': {
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache', 'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
'LOCATION': '/tmp/django_cache', 'LOCATION': '/tmp/django_cache',
'OPTIONS': { 'OPTIONS': {
'MAX_ENTRIES': 10e9, # (See locmem) 'MAX_ENTRIES': 10e9, # (See locmem)
} }
} }
try: }
import pylibmc
except ImportError: try:
pass import pylibmc
else: except ImportError:
CACHES['pylibmc'] = { pass
'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache', else:
'LOCATION': '127.0.0.1:11211', CACHES['pylibmc'] = {
} 'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
'LOCATION': '127.0.0.1:11211',
}
DEFAULT_CACHE_ALIAS = os.environ.get('CACHE_BACKEND', 'locmem') DEFAULT_CACHE_ALIAS = os.environ.get('CACHE_BACKEND', 'locmem')
CACHES['default'] = CACHES.pop(DEFAULT_CACHE_ALIAS) CACHES['default'] = CACHES.pop(DEFAULT_CACHE_ALIAS)
@ -92,8 +87,6 @@ INSTALLED_APPS = [
'django.contrib.auth', 'django.contrib.auth',
'django.contrib.contenttypes', 'django.contrib.contenttypes',
] ]
if django.VERSION < (1, 7):
INSTALLED_APPS.append('south')
MIGRATION_MODULES = { MIGRATION_MODULES = {

View File

@ -27,7 +27,6 @@ setup(
'License :: OSI Approved :: BSD License', 'License :: OSI Approved :: BSD License',
'Operating System :: OS Independent', 'Operating System :: OS Independent',
'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.2', 'Programming Language :: Python :: 3.2',