0001"""ORM Wrappers"""
0002import inspect
0003from webhelpers.util import Partial
0004
0005orms = {}
0006try:
0007 import sqlobject
0008except:
0009 pass
0010else:
0011 orms['sqlobject'] = True
0012try:
0013 import sqlalchemy
0014except:
0015 pass
0016else:
0017 orms['sqlalchemy'] = True
0018
0019def get_wrapper(obj, *args, **kw):
0020 if isinstance(obj, (list, tuple)):
0021 return obj
0022 if orms.get('sqlobject'):
0023 if inspect.isclass(obj) and issubclass(obj, sqlobject.SQLObject):
0024 return SQLObjectLazy(obj.select, *args, **kw)
0025 if orms.get('sqlalchemy'):
0026 if hasattr(obj, '_is_primary_mapper') or (not sqlalchemy.__version__.startswith('0.4') and isinstance(obj, sqlalchemy.Query)):
0029 return SQLAlchemyLazyMapper(obj, *args, **kw)
0030 if hasattr(obj, 'mapper') and hasattr(obj, 'select') and hasattr(obj, 'count'):
0031 return SQLAlchemyLazyMapper(obj, *args, **kw)
0032 if isinstance(obj, sqlalchemy.Table):
0033 return SQLAlchemyLazyTable(obj, *args, **kw)
0034 if hasattr(obj, 'query'):
0035 return SQLAlchemy04LazySessionMapper(obj, *args, **kw)
0036 if '_session' in kw:
0037 return SQLAlchemy04LazyMapper(obj, *args, **kw)
0038 raise TypeError("You must call paginate() with either a sequence, an "
0039 "SQLObject class or an SQLAlchemy query object.")
0040
0041
0042class SQLObjectLazy(Partial):
0043 def __getitem__(self, key):
0044 if not isinstance(key, slice):
0045 raise Exception, "SQLObjectLazy doesn't support getitem without slicing"
0046 return list(self()[key.start:key.stop])
0047
0048 def __len__(self):
0049 return self().count()
0050
0051class SQLAlchemyLazyTable(Partial):
0052 def __getitem__(self, key):
0053 if not isinstance(key, slice):
0054 raise Exception, "SQLAlchemyLazy doesn't support getitem without slicing"
0055 limit = key.stop - key.start
0056 offset = key.start
0057 fn = self.fn
0058 self.fn = fn.select
0059 results = self(limit=limit, offset=offset).execute()
0060 self.fn = fn
0061 return results
0062
0063 def __len__(self):
0064 s = self.fn.select(*self.args, **self.kw)
0065 return self.fn([func.count(1)], from_obj=[s])
0066
0067class SQLAlchemyLazyMapper(Partial):
0068 def __getitem__(self, key):
0069 if not isinstance(key, slice):
0070 raise Exception, "SQLAlchemyLazy doesn't support getitem without slicing"
0071 limit = key.stop - key.start
0072 offset = key.start
0073 fn = self.fn
0074 self.fn = fn.select
0075 results = self(limit=limit, offset=offset)
0076 self.fn = fn
0077 return results
0078
0079 def __len__(self):
0080 kw = {}
0081 for k, v in self.kw.iteritems():
0082 if k != 'order_by':
0083 kw[k] = v
0084 return self.fn.count(*self.args, **kw)
0085
0086class SQLAlchemy04LazySessionMapper(Partial):
0087 def __getitem__(self, key):
0088 if not isinstance(key, slice):
0089 raise Exception, "SQLAlchemyLazy doesn't support getitem without slicing"
0090 limit = key.stop - key.start
0091 offset = key.start
0092 fn = self.fn
0093 result = fn.query
0094 if self.args:
0095 result = result.filter(*self.args)
0096
0097 # Translate keyword args like 'order_by=blah' into func calls for SA 0.4
0098 # such that its .order_by(blah) on the query object
0099 for key, val in self.kw.iteritems():
0100 result = getattr(result, key)(val)
0101 return result.limit(limit).offset(offset).all()
0102
0103 def __len__(self):
0104 kw = {}
0105 fn = self.fn.query
0106 if self.args:
0107 fn = fn.filter(*self.args)
0108
0109 for key, val in self.kw.iteritems():
0110 fn = getattr(fn, key)(val)
0111 return fn.count()
0112
0113class SQLAlchemy04LazyMapper(Partial):
0114 def __getitem__(self, key):
0115 if not isinstance(key, slice):
0116 raise Exception, "SQLAlchemyLazy doesn't support getitem without slicing"
0117 Session = self.kw.pop('_session')
0118 limit = key.stop - key.start
0119 offset = key.start
0120 fn = self.fn
0121 result = Session.query(fn)
0122 if self.args:
0123 result = result.filter(*self.args)
0124
0125 # Translate keyword args like 'order_by=blah' into func calls for SA 0.4
0126 # such that its .order_by(blah) on the query object
0127 for key, val in self.kw.iteritems():
0128 result = getattr(result, key)(val)
0129 query = result.limit(limit).offset(offset)
0130 self.kw['_session'] = Session
0131 return query.all()
0132
0133 def __len__(self):
0134 Session = self.kw.pop('_session')
0135 kw = {}
0136 fn = Session.query(self.fn)
0137 if self.args:
0138 fn = fn.filter(*self.args)
0139
0140 for key, val in self.kw.iteritems():
0141 fn = getattr(fn, key)(val)
0142 count = fn.count()
0143 self.kw['_session'] = Session
0144 return count