Skip to content

Commit

Permalink
Merge branch 'master' of github.com:martmatwarne/django
Browse files Browse the repository at this point in the history
Conflicts:
	docs/releases/1.6.txt
  • Loading branch information
Martin Warne committed May 18, 2013
2 parents 5121e72 + d5ce2ff commit 31cd55b
Show file tree
Hide file tree
Showing 42 changed files with 576 additions and 182 deletions.
4 changes: 4 additions & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ answer newbie questions, and generally made Django that much better:
Randy Barlow <randy@electronsweatshop.com>
Scott Barr <scott@divisionbyzero.com.au>
Jiri Barton
Jorge Bastida <me@jorgebastida.com>
Ned Batchelder <http://www.nedbatchelder.com/>
batiste@dosimple.ch
Batman
Expand Down Expand Up @@ -123,6 +124,7 @@ answer newbie questions, and generally made Django that much better:
bthomas
btoll@bestweb.net
Jonathan Buchanan <jonathan.buchanan@gmail.com>
Jacob Burch <jacobburch@gmail.com>
Keith Bussell <kbussell@gmail.com>
C8E
Chris Cahoon <chris.cahoon@gmail.com>
Expand Down Expand Up @@ -274,6 +276,7 @@ answer newbie questions, and generally made Django that much better:
Eric Holscher <http://ericholscher.com>
Ian Holsman <http://feh.holsman.net/>
Kieran Holland <http://www.kieranholland.com>
Markus Holtermann <http://markusholtermann.eu>
Sung-Jin Hong <serialx.net@gmail.com>
Leo "hylje" Honkanen <sealage@gmail.com>
Matt Hoskins <skaffenuk@googlemail.com>
Expand Down Expand Up @@ -502,6 +505,7 @@ answer newbie questions, and generally made Django that much better:
Bernd Schlapsi
schwank@gmail.com
scott@staplefish.com
Olivier Sels <olivier.sels@gmail.com>
Ilya Semenov <semenov@inetss.com>
Aleksandra Sendecka <asendecka@hauru.eu>
serbaut@gmail.com
Expand Down
11 changes: 6 additions & 5 deletions django/contrib/auth/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import re

from django.contrib.auth.signals import user_logged_in, user_logged_out, user_login_failed
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured, PermissionDenied
from django.utils.module_loading import import_by_path

from .signals import user_logged_in, user_logged_out, user_login_failed

SESSION_KEY = '_auth_user_id'
BACKEND_SESSION_KEY = '_auth_user_backend'
REDIRECT_FIELD_NAME = 'next'
Expand All @@ -14,7 +16,6 @@ def load_backend(path):


def get_backends():
from django.conf import settings
backends = []
for backend_path in settings.AUTHENTICATION_BACKENDS:
backends.append(load_backend(backend_path))
Expand Down Expand Up @@ -106,7 +107,6 @@ def logout(request):

def get_user_model():
"Return the User model that is active in this project"
from django.conf import settings
from django.db.models import get_model

try:
Expand All @@ -120,12 +120,13 @@ def get_user_model():


def get_user(request):
from django.contrib.auth.models import AnonymousUser
from .models import AnonymousUser
try:
user_id = request.session[SESSION_KEY]
backend_path = request.session[BACKEND_SESSION_KEY]
assert backend_path in settings.AUTHENTICATION_BACKENDS
backend = load_backend(backend_path)
user = backend.get_user(user_id) or AnonymousUser()
except KeyError:
except (KeyError, AssertionError):
user = AnonymousUser()
return user
53 changes: 52 additions & 1 deletion django/contrib/auth/tests/test_auth_backends.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@
from datetime import date

from django.conf import settings
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth.models import User, Group, Permission, AnonymousUser
from django.contrib.auth.tests.utils import skipIfCustomUser
from django.contrib.auth.tests.test_custom_user import ExtensionUser, CustomPermissionsUser, CustomUser
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ImproperlyConfigured, PermissionDenied
from django.contrib.auth import authenticate
from django.contrib.auth import authenticate, get_user
from django.http import HttpRequest
from django.test import TestCase
from django.test.utils import override_settings

Expand Down Expand Up @@ -402,3 +404,52 @@ def test_permission_denied(self):
settings.AUTHENTICATION_BACKENDS) + (backend, ))
def test_authenticates(self):
self.assertEqual(authenticate(username='test', password='test'), self.user1)


class NewModelBackend(ModelBackend):
pass


@skipIfCustomUser
class ChangedBackendSettingsTest(TestCase):
"""
Tests for changes in the settings.AUTHENTICATION_BACKENDS
"""
backend = 'django.contrib.auth.tests.test_auth_backends.NewModelBackend'

TEST_USERNAME = 'test_user'
TEST_PASSWORD = 'test_password'
TEST_EMAIL = 'test@example.com'

def setUp(self):
User.objects.create_user(self.TEST_USERNAME,
self.TEST_EMAIL,
self.TEST_PASSWORD)

@override_settings(AUTHENTICATION_BACKENDS=(backend, ))
def test_changed_backend_settings(self):
"""
Tests that removing a backend configured in AUTHENTICATION_BACKENDS
make already logged-in users disconnect.
"""

# Get a session for the test user
self.assertTrue(self.client.login(
username=self.TEST_USERNAME,
password=self.TEST_PASSWORD)
)

# Prepare a request object
request = HttpRequest()
request.session = self.client.session

# Remove NewModelBackend
with self.settings(AUTHENTICATION_BACKENDS=(
'django.contrib.auth.backends.ModelBackend',)):
# Get the user from the request
user = get_user(request)

# Assert that the user retrieval is successful and the user is
# anonymous as the backend is not longer available.
self.assertIsNotNone(user)
self.assertTrue(user.is_anonymous())
2 changes: 2 additions & 0 deletions django/contrib/auth/tests/test_management.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from django.contrib.auth.models import User
from django.contrib.auth.tests.test_custom_user import CustomUser
from django.contrib.auth.tests.utils import skipIfCustomUser
from django.contrib.contenttypes.models import ContentType
from django.core.management import call_command
from django.core.management.base import CommandError
from django.core.management.validation import get_validation_errors
Expand Down Expand Up @@ -195,6 +196,7 @@ def setUp(self):

def tearDown(self):
models.Permission._meta.permissions = self._original_permissions
ContentType.objects.clear_cache()

def test_duplicated_permissions(self):
"""
Expand Down
10 changes: 7 additions & 3 deletions django/core/cache/backends/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ class CacheKeyWarning(DjangoRuntimeWarning):
pass


# Stub class to ensure not passing in a `timeout` argument results in
# the default timeout
DEFAULT_TIMEOUT = object()

# Memcached does not accept keys longer than this.
MEMCACHE_MAX_KEY_LENGTH = 250

Expand Down Expand Up @@ -84,7 +88,7 @@ def make_key(self, key, version=None):
new_key = self.key_func(key, self.key_prefix, version)
return new_key

def add(self, key, value, timeout=None, version=None):
def add(self, key, value, timeout=DEFAULT_TIMEOUT, version=None):
"""
Set a value in the cache if the key does not already exist. If
timeout is given, that timeout will be used for the key; otherwise
Expand All @@ -101,7 +105,7 @@ def get(self, key, default=None, version=None):
"""
raise NotImplementedError

def set(self, key, value, timeout=None, version=None):
def set(self, key, value, timeout=DEFAULT_TIMEOUT, version=None):
"""
Set a value in the cache. If timeout is given, that timeout will be
used for the key; otherwise the default cache timeout will be used.
Expand Down Expand Up @@ -163,7 +167,7 @@ def __contains__(self, key):
# if a subclass overrides it.
return self.has_key(key)

def set_many(self, data, timeout=None, version=None):
def set_many(self, data, timeout=DEFAULT_TIMEOUT, version=None):
"""
Set a bunch of values in the cache at once from a dict of key/value
pairs. For certain backends (memcached), this is much more efficient
Expand Down
15 changes: 9 additions & 6 deletions django/core/cache/backends/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import pickle

from django.conf import settings
from django.core.cache.backends.base import BaseCache
from django.core.cache.backends.base import BaseCache, DEFAULT_TIMEOUT
from django.db import connections, transaction, router, DatabaseError
from django.utils import timezone, six
from django.utils.encoding import force_bytes
Expand Down Expand Up @@ -65,6 +65,7 @@ def get(self, key, default=None, version=None):
if row is None:
return default
now = timezone.now()

if row[2] < now:
db = router.db_for_write(self.cache_model_class)
cursor = connections[db].cursor()
Expand All @@ -74,18 +75,18 @@ def get(self, key, default=None, version=None):
value = connections[db].ops.process_clob(row[1])
return pickle.loads(base64.b64decode(force_bytes(value)))

def set(self, key, value, timeout=None, version=None):
def set(self, key, value, timeout=DEFAULT_TIMEOUT, version=None):
key = self.make_key(key, version=version)
self.validate_key(key)
self._base_set('set', key, value, timeout)

def add(self, key, value, timeout=None, version=None):
def add(self, key, value, timeout=DEFAULT_TIMEOUT, version=None):
key = self.make_key(key, version=version)
self.validate_key(key)
return self._base_set('add', key, value, timeout)

def _base_set(self, mode, key, value, timeout=None):
if timeout is None:
def _base_set(self, mode, key, value, timeout=DEFAULT_TIMEOUT):
if timeout == DEFAULT_TIMEOUT:
timeout = self.default_timeout
db = router.db_for_write(self.cache_model_class)
table = connections[db].ops.quote_name(self._table)
Expand All @@ -95,7 +96,9 @@ def _base_set(self, mode, key, value, timeout=None):
num = cursor.fetchone()[0]
now = timezone.now()
now = now.replace(microsecond=0)
if settings.USE_TZ:
if timeout is None:
exp = datetime.max
elif settings.USE_TZ:
exp = datetime.utcfromtimestamp(time.time() + timeout)
else:
exp = datetime.fromtimestamp(time.time() + timeout)
Expand Down
8 changes: 4 additions & 4 deletions django/core/cache/backends/dummy.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
"Dummy cache backend"

from django.core.cache.backends.base import BaseCache
from django.core.cache.backends.base import BaseCache, DEFAULT_TIMEOUT

class DummyCache(BaseCache):
def __init__(self, host, *args, **kwargs):
BaseCache.__init__(self, *args, **kwargs)

def add(self, key, value, timeout=None, version=None):
def add(self, key, value, timeout=DEFAULT_TIMEOUT, version=None):
key = self.make_key(key, version=version)
self.validate_key(key)
return True
Expand All @@ -16,7 +16,7 @@ def get(self, key, default=None, version=None):
self.validate_key(key)
return default

def set(self, key, value, timeout=None, version=None):
def set(self, key, value, timeout=DEFAULT_TIMEOUT, version=None):
key = self.make_key(key, version=version)
self.validate_key(key)

Expand All @@ -32,7 +32,7 @@ def has_key(self, key, version=None):
self.validate_key(key)
return False

def set_many(self, data, timeout=0, version=None):
def set_many(self, data, timeout=DEFAULT_TIMEOUT, version=None):
pass

def delete_many(self, keys, version=None):
Expand Down
15 changes: 8 additions & 7 deletions django/core/cache/backends/filebased.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,18 @@
except ImportError:
import pickle

from django.core.cache.backends.base import BaseCache
from django.core.cache.backends.base import BaseCache, DEFAULT_TIMEOUT
from django.utils.encoding import force_bytes


class FileBasedCache(BaseCache):
def __init__(self, dir, params):
BaseCache.__init__(self, params)
self._dir = dir
if not os.path.exists(self._dir):
self._createdir()

def add(self, key, value, timeout=None, version=None):
def add(self, key, value, timeout=DEFAULT_TIMEOUT, version=None):
if self.has_key(key, version=version):
return False

Expand All @@ -35,22 +36,22 @@ def get(self, key, default=None, version=None):
with open(fname, 'rb') as f:
exp = pickle.load(f)
now = time.time()
if exp < now:
if exp is not None and exp < now:
self._delete(fname)
else:
return pickle.load(f)
except (IOError, OSError, EOFError, pickle.PickleError):
pass
return default

def set(self, key, value, timeout=None, version=None):
def set(self, key, value, timeout=DEFAULT_TIMEOUT, version=None):
key = self.make_key(key, version=version)
self.validate_key(key)

fname = self._key_to_file(key)
dirname = os.path.dirname(fname)

if timeout is None:
if timeout == DEFAULT_TIMEOUT:
timeout = self.default_timeout

self._cull()
Expand All @@ -60,8 +61,8 @@ def set(self, key, value, timeout=None, version=None):
os.makedirs(dirname)

with open(fname, 'wb') as f:
now = time.time()
pickle.dump(now + timeout, f, pickle.HIGHEST_PROTOCOL)
expiry = None if timeout is None else time.time() + timeout
pickle.dump(expiry, f, pickle.HIGHEST_PROTOCOL)
pickle.dump(value, f, pickle.HIGHEST_PROTOCOL)
except (IOError, OSError):
pass
Expand Down
19 changes: 9 additions & 10 deletions django/core/cache/backends/locmem.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
except ImportError:
import pickle

from django.core.cache.backends.base import BaseCache
from django.core.cache.backends.base import BaseCache, DEFAULT_TIMEOUT
from django.utils.synch import RWLock

# Global in-memory store of cache data. Keyed by name, to provide
Expand All @@ -23,7 +23,7 @@ def __init__(self, name, params):
self._expire_info = _expire_info.setdefault(name, {})
self._lock = _locks.setdefault(name, RWLock())

def add(self, key, value, timeout=None, version=None):
def add(self, key, value, timeout=DEFAULT_TIMEOUT, version=None):
key = self.make_key(key, version=version)
self.validate_key(key)
with self._lock.writer():
Expand All @@ -41,10 +41,8 @@ def get(self, key, default=None, version=None):
key = self.make_key(key, version=version)
self.validate_key(key)
with self._lock.reader():
exp = self._expire_info.get(key)
if exp is None:
return default
elif exp > time.time():
exp = self._expire_info.get(key, 0)
if exp is None or exp > time.time():
try:
pickled = self._cache[key]
return pickle.loads(pickled)
Expand All @@ -58,15 +56,16 @@ def get(self, key, default=None, version=None):
pass
return default

def _set(self, key, value, timeout=None):
def _set(self, key, value, timeout=DEFAULT_TIMEOUT):
if len(self._cache) >= self._max_entries:
self._cull()
if timeout is None:
if timeout == DEFAULT_TIMEOUT:
timeout = self.default_timeout
expiry = None if timeout is None else time.time() + timeout
self._cache[key] = value
self._expire_info[key] = time.time() + timeout
self._expire_info[key] = expiry

def set(self, key, value, timeout=None, version=None):
def set(self, key, value, timeout=DEFAULT_TIMEOUT, version=None):
key = self.make_key(key, version=version)
self.validate_key(key)
with self._lock.writer():
Expand Down
Loading

0 comments on commit 31cd55b

Please sign in to comment.