Django

Code

Changeset 3768

Show
Ignore:
Timestamp:
09/17/06 14:12:04 (2 years ago)
Author:
jpellerin
Message:

[multi-db] Fixed bugs in connection handling and test database setup. All tests now pass for postgres backend. Still failures for mysql and sqlite3, others unknown.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/branches/multiple-db-support/django/db/__init__.py

    r3738 r3768  
    1515# singleton to represent the default connection in connections 
    1616class dummy(object): 
     17    def __repr__(self): 
     18        return self.__str__()     
    1719    def __str__(self): 
    1820        return '<default>' 
     
    2931 
    3032 
    31 def connect(settings): 
     33def connect(settings, **kw): 
    3234    """Connect to the database specified in settings. Returns a 
    3335    ConnectionInfo on success, raises ImproperlyConfigured if the 
    3436    settings don't specify a valid database connection. 
    3537    """ 
    36     info = ConnectionInfo(settings) 
    37  
    38     # Register an event that closes the database connection 
    39     # when a Django request is finished. 
    40     dispatcher.connect(info.close, signal=signals.request_finished) 
    41      
    42     # Register an event that resets connection.queries 
    43     # when a Django request is started. 
    44     dispatcher.connect(info.reset_queries, signal=signals.request_started) 
    45  
    46     return info 
     38    return ConnectionInfo(settings, **kw) 
    4739 
    4840     
     
    5345    connection, and resetting the connection's query log. 
    5446    """ 
    55     def __init__(self, settings=None): 
     47    def __init__(self, settings=None, **kw): 
     48        super(ConnectionInfo, self).__init__(**kw) 
    5649        if settings is None: 
    5750            from django.conf import settings 
     
    6154        self.DatabaseError = self.backend.DatabaseError 
    6255 
     56        # Register an event that closes the database connection 
     57        # when a Django request is finished. 
     58        dispatcher.connect(self.close, signal=signals.request_finished) 
     59     
     60        # Register an event that resets connection.queries 
     61        # when a Django request is started. 
     62        dispatcher.connect(self.reset_queries, signal=signals.request_started) 
     63         
    6364    def __repr__(self): 
    6465        return "Connection: %r (ENGINE=%s NAME=%s)" \ 
     
    115116        self.connection.queries = [] 
    116117 
    117      
     118 
    118119class LazyConnectionManager(object): 
    119120    """Manages named connections lazily, instantiating them as 
     
    124125        self.local.connections = {} 
    125126 
     127        # Reset connections on request finish, to make sure each request can 
     128        # load the correct connections for its settings 
     129        dispatcher.connect(self.reset, signal=signals.request_finished) 
     130         
    126131    def __iter__(self): 
    127         return self.local.connections.keys() 
     132        # Iterates only over *active* connections, not all possible 
     133        # connections 
     134        return iter(self.local.connections.keys()) 
    128135 
    129136    def __getattr__(self, attr): 
     
    178185        return cnx[name] 
    179186 
     187    def items(self): 
     188        # Iterates over *all possible* connections 
     189        items = [] 
     190        for key in self.keys(): 
     191            items.append((key, self[key])) 
     192        return items 
     193     
     194    def keys(self): 
     195        # Iterates over *all possible* connections 
     196        keys = [_default] 
     197        try: 
     198            keys.extend(settings.OTHER_DATABASES.keys()) 
     199        except AttributeError: 
     200            pass 
     201        return keys 
     202     
    180203    def reset(self): 
     204        if not hasattr(self.local, 'connections'): 
     205            return 
    181206        self.local.connections = {} 
    182  
    183  
     207         
    184208def model_connection_name(klass): 
    185209    """Get the connection name that a model is configured to use, with the 
     
    262286    def get_connection(self, instance): 
    263287        return connections[model_connection_name(instance.model)] 
    264              
     288 
    265289    def reset(self): 
     290        if not hasattr(self.local, 'cnx'): 
     291            return 
    266292        self.local.cnx = {} 
    267  
    268293 
    269294class LocalizingProxy: 
     
    278303        self.__arg = arg 
    279304        self.__kw = kw 
     305 
     306        # We need to clear out this thread's storage at the end of each 
     307        # request, in case new settings are loaded with the next 
     308        def reset(stor=storage, name=name): 
     309            if hasattr(stor, name): 
     310                delattr(stor, name) 
     311        dispatcher.connect(reset, signal=signals.request_finished) 
    280312         
    281313    def __getattr__(self, attr): 
     
    296328            return 
    297329        try: 
    298             print self.__storage, self.__name 
    299330            stor = getattr(self.__storage, self.__name)             
    300331        except AttributeError: 
     
    302333            setattr(self.__storage, self.__name, stor) 
    303334        setattr(stor, attr, val) 
    304      
     335 
    305336 
    306337# Create a manager for named connections 
     
    328359 
    329360 
    330 # Reset connections on request finish, to make sure each request can 
    331 # load the correct connections for its settings 
    332 dispatcher.connect(connections.reset, signal=signals.request_finished) 
    333  
    334  
    335361# Register an event that rolls back all connections 
    336362# when a Django request has an exception. 
  • django/branches/multiple-db-support/django/test/utils.py

    r3760 r3768  
    11import sys, time 
    22from django.conf import settings 
    3  
    43from django.db import backend, connect, connection, connection_info, connections 
    54from django.dispatch import dispatcher 
     
    9594 
    9695    # Fill OTHER_DATABASES with the TEST_DATABASES settings, 
    97     # and connect each named connection to the test database, using 
    98     # a separate connection instance for each (so, eg, transactions don't 
    99     # collide) 
     96    # and connect each named connection to the test database. 
    10097    test_databases = {} 
    10198    for db_name in settings.TEST_DATABASES: 
    102         if settings.DATABASE_ENGINE == 'sqlite3': 
    103             full_name = TEST_DATABASE_NAME 
    104         else: 
    105             full_name = TEST_DATABASE_NAME + db_name 
    106         db_st = {'DATABASE_NAME': full_name} 
     99        db_st = {'DATABASE_NAME': TEST_DATABASE_NAME} 
    107100        if db_name in settings.TEST_DATABASE_MODELS: 
    108101            db_st['MODELS'] = settings.TEST_DATABASE_MODELS.get(db_name, []) 
    109102        test_databases[db_name] = db_st 
    110         connections[db_name] = connect(connection_info.settings) 
    111         connections[db_name].connection.cursor() # Initialize it 
    112103    settings.OTHER_DATABASES = test_databases 
    113  
     104     
    114105def destroy_test_db(old_database_name, old_databases, verbosity=1): 
    115106    # Unless we're using SQLite, remove the test database to clean up after 
     
    119110    if verbosity >= 1: 
    120111        print "Destroying test database..." 
     112 
     113    connection.close() 
    121114    for cnx in connections.keys(): 
    122115        connections[cnx].close() 
     116    connections.reset() 
     117     
    123118    TEST_DATABASE_NAME = settings.DATABASE_NAME 
     119    if verbosity >= 2: 
     120        print "Closed connections to %s" % TEST_DATABASE_NAME 
    124121    settings.DATABASE_NAME = old_database_name 
    125  
     122     
    126123    if settings.DATABASE_ENGINE != "sqlite3": 
    127124        settings.OTHER_DATABASES = old_databases 
    128125        for cnx in connections.keys(): 
    129             connections[cnx].connection.cursor() 
     126            try: 
     127                connections[cnx].connection.cursor() 
     128            except (KeyboardInterrupt, SystemExit): 
     129                raise 
     130            except: 
     131                pass 
    130132        cursor = connection.cursor() 
    131133        _set_autocommit(connection) 
  • django/branches/multiple-db-support/tests/modeltests/multiple_databases/models.py

    r3760 r3768  
    8585Connection: ... 
    8686 
    87 # Let's see what connections are available.The default connection is 
    88 # in there, but let's ignore it 
    89  
    90 >>> non_default = connections.keys() 
    91 >>> non_default.remove(_default) 
    92 >>> non_default.sort() 
    93 >>> non_default 
    94 ['_a', '_b'] 
     87# Let's see what connections are available. The default connection is always 
     88# included in connections as well, and may be accessed as connections[_default]. 
     89 
     90>>> connection_names = connections.keys() 
     91>>> connection_names.sort() 
     92>>> connection_names 
     93[<default>, '_a', '_b'] 
    9594     
    9695# Invalid connection names raise ImproperlyConfigured 
     96 
    9797>>> connections['bad'] 
    9898Traceback (most recent call last): 
     
    100100ImproperlyConfigured: No database connection 'bad' has been configured 
    101101 
    102 # Models can access their connections through their managers 
     102# The model_connection_name() function will tell you the name of the 
     103# connection that a model is configured to use. 
     104 
    103105>>> model_connection_name(Artist) 
    104106'_a' 
     
    116118>>> list(artists) 
    117119[<Artist: Paul Klee>] 
     120 
     121# Models can access their connections through the db property of their 
     122# default manager. 
     123 
     124>>> paul = _[0] 
     125>>> Artist.objects.db 
     126Connection: ... (ENGINE=... NAME=...) 
     127>>> paul._default_manager.db 
     128Connection: ... (ENGINE=... NAME=...) 
    118129 
    119130# When transactions are not managed, model save will commit only