Commits

Anonymous committed 43abf43

Added code to make foreignkey on ActiveMapper accept a string and create the ForeignKey object on the fly. Also added ability to pass args and kwargs to Column constructor. ActiveMapper columns can have keyword args indexed and unique which will automatically create a index or a unique index. dburi in AutoConnectEngine can be a callable.

Comments (0)

Files changed (3)

lib/sqlalchemy/ext/activemapper.py

 from sqlalchemy             import objectstore, create_engine, assign_mapper, relation, mapper
 from sqlalchemy             import and_, or_
-from sqlalchemy             import Table, Column
+from sqlalchemy             import Table, Column, ForeignKey
 from sqlalchemy.ext.proxy   import ProxyEngine
 
 import inspect
-
+import sys
 
 #
 # the "proxy" to the database engine... this can be swapped out at runtime
 # declarative column declaration - this is so that we can infer the colname
 #
 class column(object):
-    def __init__(self, coltype, colname=None, foreign_key=None, primary_key=False):
+    def __init__(self, coltype, colname=None, foreign_key=None,
+                 primary_key=False, *args, **kwargs):
+        if isinstance( foreign_key, basestring ):
+            foreign_key= ForeignKey( foreign_key )
         self.coltype     = coltype
         self.colname     = colname
         self.foreign_key = foreign_key
         self.primary_key = primary_key
-
-
+        self.unique      = kwargs.pop( 'unique', False )
+        self.indexed     = kwargs.pop( 'indexed', self.unique )
+        self.kwargs      = kwargs
+        self.args        = args
 
 #
 # declarative relationship declaration
         table_name = clsname.lower()
         columns    = []
         relations  = {}
+        _engine    = getattr( sys.modules[cls.__module__], "__engine__", engine )
         
         if 'mapping' in dict:
             members = inspect.getmembers(dict.get('mapping'))
                     table_name = value
                     continue
                 
+                if '__engine__' == name:
+                    _engine= value
+                    continue
+                    
                 if name.startswith('__'): continue
                 
                 if isinstance(value, column):
                         col = Column(value.colname or name, 
                                      value.coltype,
                                      value.foreign_key, 
-                                     primary_key=value.primary_key)
+                                     primary_key=value.primary_key,
+                                     *value.args, **value.kwargs)
                     else:
                         col = Column(value.colname or name,
                                      value.coltype,
-                                     primary_key=value.primary_key)
+                                     primary_key=value.primary_key,
+                                     *value.args, **value.kwargs)
                     columns.append(col)
+                    if value.indexed:
+                        # create a Index object for the column
+                        index= Index( "%s_idx" % (value.colname or name),
+                                      col, unique= value.unique )
                     continue
                 
                 if isinstance(value, relationship):
                     relations[name] = value
-            
-            cls.table = Table(table_name, engine, *columns)
+            assert _engine is not None, "No engine specified"
+            cls.table = Table(table_name, _engine, *columns)
             assign_mapper(cls, cls.table)
             cls.relations = relations
             ActiveMapperMeta.classes[clsname] = cls

lib/sqlalchemy/ext/proxy.py

         
     def get_engine(self):
         if self._engine is None:
-            self._engine= create_engine( self.dburi, self.opts, **self.kwargs )
+            if callable(self.dburi):
+                dburi= self.dburi()
+            else:
+                dburi= self.dburi
+            self._engine= create_engine( dburi, self.opts, **self.kwargs )
         return self._engine
 
     def set_engine(self, engine):

test/autoconnect_engine.py

+from sqlalchemy import *
+from sqlalchemy.ext.proxy import AutoConnectEngine
+
+from testbase import PersistTest
+import testbase
+import os
+
+#
+# Define an engine, table and mapper at the module level, to show that the
+# table and mapper can be used with different real engines in multiple threads
+#
+
+
+module_engine = AutoConnectEngine( testbase.db_uri )
+users = Table('users', module_engine, 
+              Column('user_id', Integer, primary_key=True),
+              Column('user_name', String(16)),
+              Column('password', String(20))
+              )
+
+class User(object):
+    pass
+
+
+class AutoConnectEngineTest1(PersistTest):
+
+    def setUp(self):
+        clear_mappers()
+        objectstore.clear()
+        
+    def test_engine_connect(self):
+        users.create()
+        assign_mapper(User, users)
+        try:
+            trans = objectstore.begin()
+
+            user = User()
+            user.user_name='fred'
+            user.password='*'
+            trans.commit()
+
+            # select
+            sqluser = User.select_by(user_name='fred')[0]
+            assert sqluser.user_name == 'fred'
+
+            # modify
+            sqluser.user_name = 'fred jones'
+
+            # commit - saves everything that changed
+            objectstore.commit()
+        
+            allusers = [ user.user_name for user in User.select() ]
+            assert allusers == [ 'fred jones' ]
+        finally:
+            users.drop()
+
+
+        
+        
+if __name__ == "__main__":
+    testbase.main()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+