Code

Ticket #1442: magic.threading.patch

File magic.threading.patch, 9.1 KB (added by eugene@…, 8 years ago)

patch for magic-removal branch

  • C:/Projects/Magic/django/db/backends/mysql/base.py

     
    4646        else: 
    4747            return getattr(self.cursor, attr) 
    4848 
    49 class DatabaseWrapper: 
     49try: 
     50    # only exists in python 2.4+ 
     51    from threading import local 
     52except ImportError: 
     53    # import copy of _thread_local.py from python 2.4 
     54    from django.utils._threading_local import local 
     55 
     56class DatabaseWrapper(local): 
    5057    def __init__(self): 
    5158        self.connection = None 
    5259        self.queries = [] 
    5360 
     61    def _valid_connection(self): 
     62        if self.connection is not None: 
     63            try: 
     64                self.connection.ping() 
     65                return True 
     66            except DatabaseError: 
     67                self.connection.close() 
     68                self.connection = None 
     69        return False 
     70 
    5471    def cursor(self): 
    5572        from django.conf import settings 
    56         if self.connection is None: 
     73        if not self._valid_connection(): 
    5774            kwargs = { 
    5875                'user': settings.DATABASE_USER, 
    5976                'db': settings.DATABASE_NAME, 
  • C:/Projects/Magic/django/db/backends/postgresql/base.py

     
    99 
    1010DatabaseError = Database.DatabaseError 
    1111 
    12 class DatabaseWrapper: 
     12try: 
     13    # only exists in python 2.4+ 
     14    from threading import local 
     15except ImportError: 
     16    # import copy of _thread_local.py from python 2.4 
     17    from django.utils._threading_local import local 
     18 
     19class DatabaseWrapper(local): 
    1320    def __init__(self): 
    1421        self.connection = None 
    1522        self.queries = [] 
  • C:/Projects/Magic/django/utils/_threading_local.py

     
     1"""Thread-local objects 
     2 
     3(Note that this module provides a Python version of thread 
     4 threading.local class.  Depending on the version of Python you're 
     5 using, there may be a faster one available.  You should always import 
     6 the local class from threading.) 
     7 
     8Thread-local objects support the management of thread-local data. 
     9If you have data that you want to be local to a thread, simply create 
     10a thread-local object and use its attributes: 
     11 
     12  >>> mydata = local() 
     13  >>> mydata.number = 42 
     14  >>> mydata.number 
     15  42 
     16 
     17You can also access the local-object's dictionary: 
     18 
     19  >>> mydata.__dict__ 
     20  {'number': 42} 
     21  >>> mydata.__dict__.setdefault('widgets', []) 
     22  [] 
     23  >>> mydata.widgets 
     24  [] 
     25 
     26What's important about thread-local objects is that their data are 
     27local to a thread. If we access the data in a different thread: 
     28 
     29  >>> log = [] 
     30  >>> def f(): 
     31  ...     items = mydata.__dict__.items() 
     32  ...     items.sort() 
     33  ...     log.append(items) 
     34  ...     mydata.number = 11 
     35  ...     log.append(mydata.number) 
     36 
     37  >>> import threading 
     38  >>> thread = threading.Thread(target=f) 
     39  >>> thread.start() 
     40  >>> thread.join() 
     41  >>> log 
     42  [[], 11] 
     43 
     44we get different data.  Furthermore, changes made in the other thread 
     45don't affect data seen in this thread: 
     46 
     47  >>> mydata.number 
     48  42 
     49 
     50Of course, values you get from a local object, including a __dict__ 
     51attribute, are for whatever thread was current at the time the 
     52attribute was read.  For that reason, you generally don't want to save 
     53these values across threads, as they apply only to the thread they 
     54came from. 
     55 
     56You can create custom local objects by subclassing the local class: 
     57 
     58  >>> class MyLocal(local): 
     59  ...     number = 2 
     60  ...     initialized = False 
     61  ...     def __init__(self, **kw): 
     62  ...         if self.initialized: 
     63  ...             raise SystemError('__init__ called too many times') 
     64  ...         self.initialized = True 
     65  ...         self.__dict__.update(kw) 
     66  ...     def squared(self): 
     67  ...         return self.number ** 2 
     68 
     69This can be useful to support default values, methods and 
     70initialization.  Note that if you define an __init__ method, it will be 
     71called each time the local object is used in a separate thread.  This 
     72is necessary to initialize each thread's dictionary. 
     73 
     74Now if we create a local object: 
     75 
     76  >>> mydata = MyLocal(color='red') 
     77 
     78Now we have a default number: 
     79 
     80  >>> mydata.number 
     81  2 
     82 
     83an initial color: 
     84 
     85  >>> mydata.color 
     86  'red' 
     87  >>> del mydata.color 
     88 
     89And a method that operates on the data: 
     90 
     91  >>> mydata.squared() 
     92  4 
     93 
     94As before, we can access the data in a separate thread: 
     95 
     96  >>> log = [] 
     97  >>> thread = threading.Thread(target=f) 
     98  >>> thread.start() 
     99  >>> thread.join() 
     100  >>> log 
     101  [[('color', 'red'), ('initialized', True)], 11] 
     102 
     103without affecting this thread's data: 
     104 
     105  >>> mydata.number 
     106  2 
     107  >>> mydata.color 
     108  Traceback (most recent call last): 
     109  ... 
     110  AttributeError: 'MyLocal' object has no attribute 'color' 
     111 
     112Note that subclasses can define slots, but they are not thread 
     113local. They are shared across threads: 
     114 
     115  >>> class MyLocal(local): 
     116  ...     __slots__ = 'number' 
     117 
     118  >>> mydata = MyLocal() 
     119  >>> mydata.number = 42 
     120  >>> mydata.color = 'red' 
     121 
     122So, the separate thread: 
     123 
     124  >>> thread = threading.Thread(target=f) 
     125  >>> thread.start() 
     126  >>> thread.join() 
     127 
     128affects what we see: 
     129 
     130  >>> mydata.number 
     131  11 
     132 
     133>>> del mydata 
     134""" 
     135 
     136# Threading import is at end 
     137 
     138class _localbase(object): 
     139    __slots__ = '_local__key', '_local__args', '_local__lock' 
     140 
     141    def __new__(cls, *args, **kw): 
     142        self = object.__new__(cls) 
     143        key = '_local__key', 'thread.local.' + str(id(self)) 
     144        object.__setattr__(self, '_local__key', key) 
     145        object.__setattr__(self, '_local__args', (args, kw)) 
     146        object.__setattr__(self, '_local__lock', RLock()) 
     147 
     148        if args or kw and (cls.__init__ is object.__init__): 
     149            raise TypeError("Initialization arguments are not supported") 
     150 
     151        # We need to create the thread dict in anticipation of 
     152        # __init__ being called, to make sire we don't cal it 
     153        # again ourselves. 
     154        dict = object.__getattribute__(self, '__dict__') 
     155        currentThread().__dict__[key] = dict 
     156 
     157        return self 
     158 
     159def _patch(self): 
     160    key = object.__getattribute__(self, '_local__key') 
     161    d = currentThread().__dict__.get(key) 
     162    if d is None: 
     163        d = {} 
     164        currentThread().__dict__[key] = d 
     165        object.__setattr__(self, '__dict__', d) 
     166 
     167        # we have a new instance dict, so call out __init__ if we have 
     168        # one 
     169        cls = type(self) 
     170        if cls.__init__ is not object.__init__: 
     171            args, kw = object.__getattribute__(self, '_local__args') 
     172            cls.__init__(self, *args, **kw) 
     173    else: 
     174        object.__setattr__(self, '__dict__', d) 
     175 
     176class local(_localbase): 
     177 
     178    def __getattribute__(self, name): 
     179        lock = object.__getattribute__(self, '_local__lock') 
     180        lock.acquire() 
     181        try: 
     182            _patch(self) 
     183            return object.__getattribute__(self, name) 
     184        finally: 
     185            lock.release() 
     186 
     187    def __setattr__(self, name, value): 
     188        lock = object.__getattribute__(self, '_local__lock') 
     189        lock.acquire() 
     190        try: 
     191            _patch(self) 
     192            return object.__setattr__(self, name, value) 
     193        finally: 
     194            lock.release() 
     195 
     196    def __delattr__(self, name): 
     197        lock = object.__getattribute__(self, '_local__lock') 
     198        lock.acquire() 
     199        try: 
     200            _patch(self) 
     201            return object.__delattr__(self, name) 
     202        finally: 
     203            lock.release() 
     204 
     205 
     206    def __del__(): 
     207        threading_enumerate = enumerate 
     208        __getattribute__ = object.__getattribute__ 
     209 
     210        def __del__(self): 
     211            key = __getattribute__(self, '_local__key') 
     212 
     213            try: 
     214                threads = list(threading_enumerate()) 
     215            except: 
     216                # if enumerate fails, as it seems to do during 
     217                # shutdown, we'll skip cleanup under the assumption 
     218                # that there is nothing to clean up 
     219                return 
     220 
     221            for thread in threads: 
     222                try: 
     223                    __dict__ = thread.__dict__ 
     224                except AttributeError: 
     225                    # Thread is dying, rest in peace 
     226                    continue 
     227 
     228                if key in __dict__: 
     229                    try: 
     230                        del __dict__[key] 
     231                    except KeyError: 
     232                        pass # didn't have anything in this thread 
     233 
     234        return __del__ 
     235    __del__ = __del__() 
     236 
     237from threading import currentThread, enumerate, RLock