Author: Alex
Date: 2011-01-17 03:52:47 -0600 (Mon, 17 Jan 2011)
New Revision: 15232

Removed:
   django/trunk/django/utils/thread_support.py
Modified:
   django/trunk/django/core/urlresolvers.py
   django/trunk/django/db/backends/__init__.py
   django/trunk/django/db/transaction.py
   django/trunk/django/utils/translation/trans_real.py
   django/trunk/tests/regressiontests/i18n/tests.py
Log:
Refactor all uses of thread locals to be more consistant and sane.

Modified: django/trunk/django/core/urlresolvers.py
===================================================================
--- django/trunk/django/core/urlresolvers.py    2011-01-17 02:40:16 UTC (rev 
15231)
+++ django/trunk/django/core/urlresolvers.py    2011-01-17 09:52:47 UTC (rev 
15232)
@@ -8,6 +8,7 @@
 """
 
 import re
+from threading import local
 
 from django.http import Http404
 from django.conf import settings
@@ -17,7 +18,6 @@
 from django.utils.functional import memoize
 from django.utils.importlib import import_module
 from django.utils.regex_helper import normalize
-from django.utils.thread_support import currentThread
 
 _resolver_cache = {} # Maps URLconf modules to RegexURLResolver instances.
 _callable_cache = {} # Maps view and url pattern names to their view functions.
@@ -25,11 +25,12 @@
 # SCRIPT_NAME prefixes for each thread are stored here. If there's no entry for
 # the current thread (which is the only one we ever access), it is assumed to
 # be empty.
-_prefixes = {}
+_prefixes = local()
 
 # Overridden URLconfs for each thread are stored here.
-_urlconfs = {}
+_urlconfs = local()
 
+
 class ResolverMatch(object):
     def __init__(self, func, args, kwargs, url_name=None, app_name=None, 
namespaces=None):
         self.func = func
@@ -401,7 +402,7 @@
     """
     if not prefix.endswith('/'):
         prefix += '/'
-    _prefixes[currentThread()] = prefix
+    _prefixes.value = prefix
 
 def get_script_prefix():
     """
@@ -409,27 +410,22 @@
     wishes to construct their own URLs manually (although accessing the request
     instance is normally going to be a lot cleaner).
     """
-    return _prefixes.get(currentThread(), u'/')
+    return getattr(_prefixes, "value", u'/')
 
 def set_urlconf(urlconf_name):
     """
     Sets the URLconf for the current thread (overriding the default one in
     settings). Set to None to revert back to the default.
     """
-    thread = currentThread()
     if urlconf_name:
-        _urlconfs[thread] = urlconf_name
+        _urlconfs.value = urlconf_name
     else:
-        # faster than wrapping in a try/except
-        if thread in _urlconfs:
-            del _urlconfs[thread]
+        if hasattr(_urlconfs, "value"):
+            del _urlconfs.value
 
 def get_urlconf(default=None):
     """
     Returns the root URLconf to use for the current thread if it has been
     changed from the default one.
     """
-    thread = currentThread()
-    if thread in _urlconfs:
-        return _urlconfs[thread]
-    return default
+    return getattr(_urlconfs, "value", default)

Modified: django/trunk/django/db/backends/__init__.py
===================================================================
--- django/trunk/django/db/backends/__init__.py 2011-01-17 02:40:16 UTC (rev 
15231)
+++ django/trunk/django/db/backends/__init__.py 2011-01-17 09:52:47 UTC (rev 
15232)
@@ -25,6 +25,11 @@
         self.alias = alias
         self.use_debug_cursor = None
 
+        # Transaction related attributes
+        self.transaction_state = []
+        self.savepoint_state = 0
+        self.dirty = None
+
     def __eq__(self, other):
         return self.alias == other.alias
 

Modified: django/trunk/django/db/transaction.py
===================================================================
--- django/trunk/django/db/transaction.py       2011-01-17 02:40:16 UTC (rev 
15231)
+++ django/trunk/django/db/transaction.py       2011-01-17 09:52:47 UTC (rev 
15232)
@@ -25,6 +25,7 @@
 from django.conf import settings
 from django.db import connections, DEFAULT_DB_ALIAS
 
+
 class TransactionManagementError(Exception):
     """
     This exception is thrown when something bad happens with transaction
@@ -32,19 +33,6 @@
     """
     pass
 
-# The states are dictionaries of dictionaries of lists. The key to the outer
-# dict is the current thread, and the key to the inner dictionary is the
-# connection alias and the list is handled as a stack of values.
-state = {}
-savepoint_state = {}
-
-# The dirty flag is set by *_unless_managed functions to denote that the
-# code under transaction management has changed things to require a
-# database commit.
-# This is a dictionary mapping thread to a dictionary mapping connection
-# alias to a boolean.
-dirty = {}
-
 def enter_transaction_management(managed=True, using=None):
     """
     Enters transaction management for a running thread. It must be balanced 
with
@@ -58,15 +46,14 @@
     if using is None:
         using = DEFAULT_DB_ALIAS
     connection = connections[using]
-    thread_ident = thread.get_ident()
-    if thread_ident in state and state[thread_ident].get(using):
-        state[thread_ident][using].append(state[thread_ident][using][-1])
+
+    if connection.transaction_state:
+        connection.transaction_state.append(connection.transaction_state[-1])
     else:
-        state.setdefault(thread_ident, {})
-        state[thread_ident][using] = [settings.TRANSACTIONS_MANAGED]
-    if thread_ident not in dirty or using not in dirty[thread_ident]:
-        dirty.setdefault(thread_ident, {})
-        dirty[thread_ident][using] = False
+        connection.transaction_state.append(settings.TRANSACTIONS_MANAGED)
+
+    if connection.dirty is None:
+        connection.dirty = False
     connection._enter_transaction_management(managed)
 
 def leave_transaction_management(using=None):
@@ -78,16 +65,18 @@
     if using is None:
         using = DEFAULT_DB_ALIAS
     connection = connections[using]
+
     connection._leave_transaction_management(is_managed(using=using))
-    thread_ident = thread.get_ident()
-    if thread_ident in state and state[thread_ident].get(using):
-        del state[thread_ident][using][-1]
+    if connection.transaction_state:
+        del connection.transaction_state[-1]
     else:
-        raise TransactionManagementError("This code isn't under transaction 
management")
-    if dirty.get(thread_ident, {}).get(using, False):
+        raise TransactionManagementError("This code isn't under transaction "
+            "management")
+    if connection.dirty:
         rollback(using=using)
-        raise TransactionManagementError("Transaction managed block ended with 
pending COMMIT/ROLLBACK")
-    dirty[thread_ident][using] = False
+        raise TransactionManagementError("Transaction managed block ended with 
"
+            "pending COMMIT/ROLLBACK")
+    connection.dirty = False
 
 def is_dirty(using=None):
     """
@@ -96,8 +85,10 @@
     """
     if using is None:
         using = DEFAULT_DB_ALIAS
-    return dirty.get(thread.get_ident(), {}).get(using, False)
+    connection = connections[using]
 
+    return connection.dirty
+
 def set_dirty(using=None):
     """
     Sets a dirty flag for the current thread and code streak. This can be used
@@ -106,11 +97,13 @@
     """
     if using is None:
         using = DEFAULT_DB_ALIAS
-    thread_ident = thread.get_ident()
-    if thread_ident in dirty and using in dirty[thread_ident]:
-        dirty[thread_ident][using] = True
+    connection = connections[using]
+
+    if connection.dirty is not None:
+        connection.dirty = True
     else:
-        raise TransactionManagementError("This code isn't under transaction 
management")
+        raise TransactionManagementError("This code isn't under transaction "
+            "management")
 
 def set_clean(using=None):
     """
@@ -120,9 +113,10 @@
     """
     if using is None:
         using = DEFAULT_DB_ALIAS
-    thread_ident = thread.get_ident()
-    if thread_ident in dirty and using in dirty[thread_ident]:
-        dirty[thread_ident][using] = False
+    connection = connections[using]
+
+    if connection.dirty is not None:
+        connection.dirty = False
     else:
         raise TransactionManagementError("This code isn't under transaction 
management")
     clean_savepoints(using=using)
@@ -130,9 +124,8 @@
 def clean_savepoints(using=None):
     if using is None:
         using = DEFAULT_DB_ALIAS
-    thread_ident = thread.get_ident()
-    if thread_ident in savepoint_state and using in 
savepoint_state[thread_ident]:
-        del savepoint_state[thread_ident][using]
+    connection = connections[using]
+    connection.savepoint_state = 0
 
 def is_managed(using=None):
     """
@@ -140,10 +133,9 @@
     """
     if using is None:
         using = DEFAULT_DB_ALIAS
-    thread_ident = thread.get_ident()
-    if thread_ident in state and using in state[thread_ident]:
-        if state[thread_ident][using]:
-            return state[thread_ident][using][-1]
+    connection = connections[using]
+    if connection.transaction_state:
+        return connection.transaction_state[-1]
     return settings.TRANSACTIONS_MANAGED
 
 def managed(flag=True, using=None):
@@ -156,15 +148,16 @@
     if using is None:
         using = DEFAULT_DB_ALIAS
     connection = connections[using]
-    thread_ident = thread.get_ident()
-    top = state.get(thread_ident, {}).get(using, None)
+
+    top = connection.transaction_state
     if top:
         top[-1] = flag
         if not flag and is_dirty(using=using):
             connection._commit()
             set_clean(using=using)
     else:
-        raise TransactionManagementError("This code isn't under transaction 
management")
+        raise TransactionManagementError("This code isn't under transaction "
+            "management")
 
 def commit_unless_managed(using=None):
     """
@@ -221,13 +214,11 @@
         using = DEFAULT_DB_ALIAS
     connection = connections[using]
     thread_ident = thread.get_ident()
-    if thread_ident in savepoint_state and using in 
savepoint_state[thread_ident]:
-        savepoint_state[thread_ident][using].append(None)
-    else:
-        savepoint_state.setdefault(thread_ident, {})
-        savepoint_state[thread_ident][using] = [None]
+
+    connection.savepoint_state += 1
+
     tid = str(thread_ident).replace('-', '')
-    sid = "s%s_x%d" % (tid, len(savepoint_state[thread_ident][using]))
+    sid = "s%s_x%d" % (tid, connection.savepoint_state)
     connection._savepoint(sid)
     return sid
 
@@ -239,8 +230,8 @@
     if using is None:
         using = DEFAULT_DB_ALIAS
     connection = connections[using]
-    thread_ident = thread.get_ident()
-    if thread_ident in savepoint_state and using in 
savepoint_state[thread_ident]:
+
+    if connection.savepoint_state:
         connection._savepoint_rollback(sid)
 
 def savepoint_commit(sid, using=None):
@@ -251,8 +242,8 @@
     if using is None:
         using = DEFAULT_DB_ALIAS
     connection = connections[using]
-    thread_ident = thread.get_ident()
-    if thread_ident in savepoint_state and using in 
savepoint_state[thread_ident]:
+
+    if connection.savepoint_state:
         connection._savepoint_commit(sid)
 
 ##############

Deleted: django/trunk/django/utils/thread_support.py
===================================================================
--- django/trunk/django/utils/thread_support.py 2011-01-17 02:40:16 UTC (rev 
15231)
+++ django/trunk/django/utils/thread_support.py 2011-01-17 09:52:47 UTC (rev 
15232)
@@ -1,12 +0,0 @@
-"""
-Code used in a couple of places to work with the current thread's environment.
-Current users include i18n and request prefix handling.
-"""
-
-try:
-    import threading
-    currentThread = threading.currentThread
-except ImportError:
-    def currentThread():
-        return "no threading"
-

Modified: django/trunk/django/utils/translation/trans_real.py
===================================================================
--- django/trunk/django/utils/translation/trans_real.py 2011-01-17 02:40:16 UTC 
(rev 15231)
+++ django/trunk/django/utils/translation/trans_real.py 2011-01-17 09:52:47 UTC 
(rev 15232)
@@ -7,15 +7,16 @@
 import warnings
 import gettext as gettext_module
 from cStringIO import StringIO
+from threading import local
 
 from django.utils.importlib import import_module
 from django.utils.safestring import mark_safe, SafeData
-from django.utils.thread_support import currentThread
 
+
 # Translations are cached in a dictionary for every language+app tuple.
 # The active translations are stored by threadid to make them thread local.
 _translations = {}
-_active = {}
+_active = local()
 
 # The default translation is based on the settings file.
 _default = None
@@ -197,16 +198,15 @@
             "Please use the 'nb' translation instead.",
             DeprecationWarning
         )
-    _active[currentThread()] = translation(language)
+    _active.value = translation(language)
 
 def deactivate():
     """
     Deinstalls the currently active translation object so that further _ calls
     will resolve against the default translation object, again.
     """
-    global _active
-    if currentThread() in _active:
-        del _active[currentThread()]
+    if hasattr(_active, "value"):
+        del _active.value
 
 def deactivate_all():
     """
@@ -214,11 +214,11 @@
     useful when we want delayed translations to appear as the original string
     for some reason.
     """
-    _active[currentThread()] = gettext_module.NullTranslations()
+    _active.value = gettext_module.NullTranslations()
 
 def get_language():
     """Returns the currently selected language."""
-    t = _active.get(currentThread(), None)
+    t = getattr(_active, "value", None)
     if t is not None:
         try:
             return t.to_language()
@@ -246,8 +246,9 @@
     This can be used if you need to modify the catalog or want to access the
     whole message catalog instead of just translating one string.
     """
-    global _default, _active
-    t = _active.get(currentThread(), None)
+    global _default
+
+    t = getattr(_active, "value", None)
     if t is not None:
         return t
     if _default is None:
@@ -262,9 +263,10 @@
     translation object to use. If no current translation is activated, the
     message will be run through the default translation object.
     """
+    global _default
+
     eol_message = message.replace('\r\n', '\n').replace('\r', '\n')
-    global _default, _active
-    t = _active.get(currentThread(), None)
+    t = getattr(_active, "value", None)
     if t is not None:
         result = getattr(t, translation_function)(eol_message)
     else:
@@ -300,9 +302,9 @@
     return message
 
 def do_ntranslate(singular, plural, number, translation_function):
-    global _default, _active
+    global _default
 
-    t = _active.get(currentThread(), None)
+    t = getattr(_active, "value", None)
     if t is not None:
         return getattr(t, translation_function)(singular, plural, number)
     if _default is None:
@@ -587,4 +589,3 @@
     if month_day_format == 'MONTH_DAY_FORMAT':
         month_day_format = settings.MONTH_DAY_FORMAT
     return year_month_format, month_day_format
-

Modified: django/trunk/tests/regressiontests/i18n/tests.py
===================================================================
--- django/trunk/tests/regressiontests/i18n/tests.py    2011-01-17 02:40:16 UTC 
(rev 15231)
+++ django/trunk/tests/regressiontests/i18n/tests.py    2011-01-17 09:52:47 UTC 
(rev 15232)
@@ -4,10 +4,12 @@
 import os
 import sys
 import pickle
+from threading import local
 
 from django.conf import settings
 from django.template import Template, Context
-from django.utils.formats import get_format, date_format, time_format, 
localize, localize_input, iter_format_modules
+from django.utils.formats import (get_format, date_format, time_format,
+    localize, localize_input, iter_format_modules)
 from django.utils.importlib import import_module
 from django.utils.numberformat import format as nformat
 from django.utils.safestring import mark_safe, SafeString, SafeUnicode
@@ -61,7 +63,7 @@
         self.old_locale_paths = settings.LOCALE_PATHS
         settings.LOCALE_PATHS += 
(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'other', 'locale'),)
         from django.utils.translation import trans_real
-        trans_real._active = {}
+        trans_real._active = local()
         trans_real._translations = {}
         activate('de')
 
@@ -649,7 +651,7 @@
         from django.utils.translation import trans_real
         # Okay, this is brutal, but we have no other choice to fully reset
         # the translation framework
-        trans_real._active = {}
+        trans_real._active = local()
         trans_real._translations = {}
         activate('de')
 

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to django-updates@googlegroups.com.
To unsubscribe from this group, send email to 
django-updates+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en.

Reply via email to