PKa95 khhsqlobject/boundattributes.py""" Bound attributes are attributes that are bound to a specific class and a specific name. In SQLObject a typical example is a column object, which knows its name and class. A bound attribute should define a method ``__addtoclass__(added_class, name)`` (attributes without this method will simply be treated as normal). The return value is ignored; if the attribute wishes to change the value in the class, it must call ``setattr(added_class, name, new_value)``. BoundAttribute is a class that facilitates lazy attribute creation. ``bind_attributes(cls, new_attrs)`` is a function that looks for attributes with this special method. ``new_attrs`` is a dictionary, as typically passed into ``__classinit__`` with declarative (calling ``bind_attributes`` in ``__classinit__`` would be typical). Note if you do this that attributes defined in a superclass will not be rebound in subclasses. If you want to rebind attributes in subclasses, use ``bind_attributes_local``, which adds a ``__bound_attributes__`` variable to your class to track these active attributes. """ __all__ = ['BoundAttribute', 'BoundFactory', 'bind_attributes', 'bind_attributes_local'] import declarative class BoundAttribute(declarative.Declarative): """ This is a declarative class that passes all the values given to it to another object. So you can pass it arguments (via __init__/__call__) or give it the equivalent of keyword arguments through subclassing. Then a bound object will be added in its place. To hook this other object in, override ``make_object(added_class, name, **attrs)`` and maybe ``set_object(added_class, name, **attrs)`` (the default implementation of ``set_object`` just resets the attribute to whatever ``make_object`` returned). """ _private_variables = ( '_private_variables', '_all_attributes', '__classinit__', '__addtoclass__', '_add_attrs', 'set_object', 'make_object', ) _all_attrs = () def __classinit__(cls, new_attrs): declarative.Declarative.__classinit__(cls, new_attrs) cls._all_attrs = cls._add_attrs(cls, new_attrs) def __instanceinit__(self, new_attrs): declarative.Declarative.__instanceinit__(self, new_attrs) self._all_attrs = self._add_attrs(self, new_attrs) def _add_attrs(this_object, new_attrs): private = this_object._private_variables all_attrs = list(this_object._all_attrs) for key in new_attrs.keys(): if key.startswith('_') or key in private: continue if key not in all_attrs: all_attrs.append(key) return tuple(all_attrs) _add_attrs = staticmethod(_add_attrs) def __addtoclass__(self, cls, added_class, attr_name): me = self or cls attrs = {} for name in me._all_attrs: attrs[name] = getattr(me, name) attrs['added_class'] = added_class attrs['attr_name'] = attr_name obj = me.make_object(**attrs) me.set_object(added_class, attr_name, obj) __addtoclass__ = declarative.classinstancemethod(__addtoclass__) def set_object(cls, added_class, attr_name, obj): setattr(added_class, attr_name, obj) set_object = classmethod(set_object) def make_object(cls, added_class, attr_name, *args, **attrs): raise NotImplementedError make_object = classmethod(make_object) class BoundFactory(BoundAttribute): factory_class = None def make_object(cls, added_class, attr_name, *args, **kw): return cls.factory_class(added_class, attr_name, *args, **kw) def bind_attributes(cls, new_attrs): for name, value in new_attrs.items(): if hasattr(value, '__addtoclass__'): value.__addtoclass__(cls, name) def bind_attributes_local(cls, new_attrs): new_bound_attributes = {} for name, value in getattr(cls, '__bound_attributes__', {}).items(): if new_attrs.has_key(name): # The attribute is being REbound, so don't try to bind it # again. continue value.__addtoclass__(cls, name) new_bound_attributes[name] = value for name, value in new_attrs.items(): if hasattr(value, '__addtoclass__'): value.__addtoclass__(cls, name) new_bound_attributes[name] = value cls.__bound_attributes__ = new_bound_attributes PKa95~~~sqlobject/converters.pyimport array try: import mx.DateTime.ISO origISOStr = mx.DateTime.ISO.strGMT from mx.DateTime import DateTimeType, DateTimeDeltaType except ImportError: try: import DateTime.ISO origISOStr = DateTime.ISO.strGMT from DateTime import DateTimeType, DateTimeDeltaType except ImportError: origISOStr = None DateTimeType = None DateTimeDeltaType = None import time try: import datetime except ImportError: datetime = None try: import Sybase NumericType=Sybase.NumericType except ImportError: NumericType = None if type(1==1) == type(1): class BOOL(object): def __init__(self, value): self.value = not not value def __nonzero__(self): return self.value def __repr__(self): if self: return 'TRUE' else: return 'FALSE' TRUE = BOOL(1) FALSE = BOOL(0) else: TRUE = 1==1 FALSE = 0==1 from types import InstanceType, ClassType, TypeType try: from decimal import Decimal except ImportError: Decimal = None ######################################## ## Quoting ######################################## sqlStringReplace = [ ('\\', '\\\\'), ("'", "\\'"), ('\000', '\\0'), ('\b', '\\b'), ('\n', '\\n'), ('\r', '\\r'), ('\t', '\\t'), ] def isoStr(val): """ Gets rid of time zone information (@@: should we convert to GMT?) """ val = origISOStr(val) if val.find('+') == -1: return val else: return val[:val.find('+')] class ConverterRegistry: def __init__(self): self.basic = {} self.klass = {} def registerConverter(self, typ, func): if type(typ) is ClassType: self.klass[typ] = func else: self.basic[typ] = func def lookupConverter(self, value, default=None): if type(value) == InstanceType: # lookup on klasses dict return self.klass.get(value.__class__, default) return self.basic.get(type(value), default) converters = ConverterRegistry() registerConverter = converters.registerConverter lookupConverter = converters.lookupConverter array_type = type(array.array('c', '')) # In Python 2.2 array.array and buffer buffer_type = type(buffer('')) # are functions, not classes def StringLikeConverter(value, db): if isinstance(value, array_type): try: value = value.tounicode() except ValueError: value = value.tostring() elif isinstance(value, buffer_type): value = str(value) if db in ('mysql', 'postgres'): for orig, repl in sqlStringReplace: value = value.replace(orig, repl) elif db in ('sqlite', 'firebird', 'sybase', 'maxdb', 'mssql'): value = value.replace("'", "''") else: assert 0, "Database %s unknown" % db return "'%s'" % value registerConverter(type(""), StringLikeConverter) registerConverter(type(u""), StringLikeConverter) registerConverter(array_type, StringLikeConverter) registerConverter(buffer_type, StringLikeConverter) def IntConverter(value, db): return repr(int(value)) registerConverter(type(1), IntConverter) def LongConverter(value, db): return str(value) registerConverter(type(0L), LongConverter) if NumericType: registerConverter(NumericType, IntConverter) def BoolConverter(value, db): if db in ('postgres',): if value: return "'t'" else: return "'f'" else: if value: return '1' else: return '0' if type(TRUE) == InstanceType: # Python 2.2 compatibility: registerConverter(BOOL, BoolConverter) else: registerConverter(type(TRUE), BoolConverter) def FloatConverter(value, db): return repr(value) registerConverter(type(1.0), FloatConverter) if DateTimeType: def DateTimeConverter(value, db): return "'%s'" % isoStr(value) registerConverter(DateTimeType, DateTimeConverter) def TimeConverter(value, db): return "'%s'" % value.strftime("%T") registerConverter(DateTimeDeltaType, TimeConverter) def NoneConverter(value, db): return "NULL" registerConverter(type(None), NoneConverter) def SequenceConverter(value, db): return "(%s)" % ", ".join([sqlrepr(v, db) for v in value]) registerConverter(type(()), SequenceConverter) registerConverter(type([]), SequenceConverter) if hasattr(time, 'struct_time'): def StructTimeConverter(value, db): return time.strftime("'%Y-%m-%d %H:%M:%S'", value) registerConverter(time.struct_time, StructTimeConverter) if datetime: def DateTimeConverter(value, db): return "'%4d-%02d-%02d %02d:%02d:%02d'" % ( value.year, value.month, value.day, value.hour, value.minute, value.second) registerConverter(datetime.datetime, DateTimeConverter) def DateConverter(value, db): return "'%4d-%02d-%02d'" % (value.year, value.month, value.day) registerConverter(datetime.date, DateConverter) def TimeConverter(value, db): return "'%02d:%02d:%02d'" % (value.hour, value.minute, value.second) registerConverter(datetime.time, TimeConverter) if Decimal: def DecimalConverter(value, db): return value.to_eng_string() registerConverter(Decimal, DecimalConverter) def sqlrepr(obj, db=None): try: reprFunc = obj.__sqlrepr__ except AttributeError: converter = lookupConverter(obj) if converter is None: raise ValueError, "Unknown SQL builtin type: %s for %s" % \ (type(obj), repr(obj)) return converter(obj, db) else: return reprFunc(db) PKa95"199sqlobject/classregistry.py""" classresolver.py 2 February 2004, Ian Bicking Resolves strings to classes, and runs callbacks when referenced classes are created. Classes are referred to only by name, not by module. So that identically-named classes can coexist, classes are put into individual registries, which are keyed on strings (names). These registries are created on demand. Use like:: >>> import classregistry >>> registry = classregistry.registry('MyModules') >>> def afterMyClassExists(cls): ... print 'Class finally exists:', cls >>> registry.addClassCallback('MyClass', afterMyClassExists) >>> class MyClass: ... pass >>> registry.addClass(MyClass) Class finally exists: MyClass """ class ClassRegistry(object): """ We'll be dealing with classes that reference each other, so class C1 may reference C2 (in a join), while C2 references C1 right back. Since classes are created in an order, there will be a point when C1 exists but C2 doesn't. So we deal with classes by name, and after each class is created we try to fix up any references by replacing the names with actual classes. Here we keep a dictionaries of class names to classes -- note that the classes might be spread among different modules, so since we pile them together names need to be globally unique, to just module unique. Like needSet below, the container dictionary is keyed by the class registry. """ def __init__(self, name): self.name = name self.classes = {} self.callbacks = {} self.genericCallbacks = [] def addClassCallback(self, className, callback, *args, **kw): """ Whenever a name is substituted for the class, you can register a callback that will be called when the needed class is created. If it's already been created, the callback will be called immediately. """ if self.classes.has_key(className): callback(self.classes[className], *args, **kw) else: self.callbacks.setdefault(className, []).append((callback, args, kw)) def addCallback(self, callback, *args, **kw): """ This callback is called for all classes, not just specific ones (like addClassCallback). """ self.genericCallbacks.append((callback, args, kw)) for cls in self.classes.values(): callback(cls, *args, **kw) def addClass(self, cls): """ Everytime a class is created, we add it to the registry, so that other classes can find it by name. We also call any callbacks that are waiting for the class. """ if cls.__name__ in self.classes: import sys other = self.classes[cls.__name__] raise ValueError( "class %s is already in the registry (other class is " "%r, from the module %s in %s; attempted new class is " "%r, from the module %s in %s)" % (cls.__name__, other, other.__module__, getattr(sys.modules.get(other.__module__), '__file__', '(unknown)'), cls, cls.__module__, getattr(sys.modules.get(cls.__module__), '__file__', '(unknown)'))) self.classes[cls.__name__] = cls if self.callbacks.has_key(cls.__name__): for callback, args, kw in self.callbacks[cls.__name__]: callback(cls, *args, **kw) del self.callbacks[cls.__name__] for callback, args, kw in self.genericCallbacks: callback(cls, *args, **kw) def getClass(self, className): try: return self.classes[className] except KeyError: all = self.classes.keys() all.sort() raise KeyError( "No class %s found in the registry %s (these classes " "exist: %s)" % (className, self.name or '[default]', ', '.join(all))) def allClasses(self): return self.classes.values() class _MasterRegistry(object): """ This singleton holds all the class registries. There can be multiple registries to hold different unrelated sets of classes that reside in the same process. These registries are named with strings, and are created on demand. The MasterRegistry module global holds the singleton. """ def __init__(self): self.registries = {} def registry(self, item): if not self.registries.has_key(item): self.registries[item] = ClassRegistry(item) return self.registries[item] MasterRegistry = _MasterRegistry() registry = MasterRegistry.registry def findClass(name, class_registry=None): return registry(class_registry).getClass(name) PKa95Q6sqlobject/__init__.pyfrom main import * from col import * from sqlbuilder import AND, OR, NOT, IN, LIKE, RLIKE, DESC, CONTAINSSTRING, const, func from styles import * from joins import * from index import * from dbconnection import connectionForURI ## Each of these imports allows the driver to install itself ## Then we set up some backward compatibility def _warn(msg): import warnings warnings.warn(msg, DeprecationWarning, stacklevel=2) import firebird as _firebird def FirebirdConnection(*args, **kw): _warn('FirebirdConnection is deprecated; use connectionForURI("firebird://...") or "from sqlobject.firebird import builder; FirebirdConnection = builder()"') return _firebird.builder()(*args, **kw) import mysql as _mysql def MySQLConnection(*args, **kw): _warn('MySQLConnection is deprecated; use connectionForURI("mysql://...") or "from sqlobject.mysql import builder; MySQLConnection = builder()"') return _mysql.builder()(*args, **kw) import postgres as _postgres def PostgresConnection(*args, **kw): _warn('PostgresConnection is deprecated; use connectionForURI("postgres://...") or "from sqlobject.postgres import builder; PostgresConnection = builder()"') return _postgres.builder()(*args, **kw) import sqlite as _sqlite def SQLiteConnection(*args, **kw): _warn('SQLiteConnection is deprecated; use connectionForURI("sqlite://...") or "from sqlobject.sqlite import builder; SQLiteConnection = builder()"') return _sqlite.builder()(*args, **kw) import sybase as _sybase def SybaseConnection(*args, **kw): _warn('SybaseConnection is deprecated; use connectionForURI("sybase://...") or "from sqlobject.sybase import builder; SybaseConnection = builder()"') return _sybase.builder()(*args, **kw) import maxdb as _maxdb def MaxdbConnection(*args, **kw): _warn('MaxdbConnection is deprecated; use connectionForURI("maxdb://...") or "from sqlobject.maxdb import builder; MaxdbConnection = builder()"') return _maxdb.builder()(*args, **kw) import mssql as _mssql def MSSQLConnection(*args, **kw): _warn('MssqlConnection is deprecated; use connectionForURI("mssql://...") or "from sqlobject.mssql import builder; MSSQLConnection = builder()"') return _mssql.builder()(*args, **kw) PKa95K%%sqlobject/cache.py""" This implements the instance caching in SQLObject. Caching is relatively aggressive. All objects are retained so long as they are in memory, by keeping weak references to objects. We also keep other objects in a cache that doesn't allow them to be garbage collected (unless caching is turned off). """ import threading from weakref import ref from time import time as now True, False = 1==1, 0==1 class CacheFactory(object): """ CacheFactory caches object creation. Each object should be referenced by a single hashable ID (note tuples of hashable values are also hashable). """ def __init__(self, cullFrequency=100, cullFraction=2, cache=True): """ Every cullFrequency times that an item is retrieved from this cache, the cull method is called. The cull method then expires an arbitrary fraction of the cached objects. The idea is at no time will the cache be entirely emptied, placing a potentially high load at that moment, but everything object will have its time to go eventually. The fraction is given as an integer, and one in that many objects are expired (i.e., the default is 1/2 of objects are expired). By setting cache to False, items won't be cached. However, in all cases a weak reference is kept to created objects, and if the object hasn't been garbage collected it will be returned. """ self.cullFrequency = cullFrequency self.cullCount = cullFrequency self.cullOffset = 0 self.cullFraction = cullFraction self.doCache = cache if self.doCache: self.cache = {} self.expiredCache = {} self.lock = threading.Lock() def tryGet(self, id): """ This returns None, or the object in cache. """ value = self.expiredCache.get(id) if value: # it's actually a weakref: return value() if not self.doCache: return None return self.cache.get(id) def get(self, id): """ This method can cause deadlocks! tryGet is safer This returns the object found in cache, or None. If None, then the cache will remain locked! This is so that the calling function can create the object in a threadsafe manner before releasing the lock. You should use this like (note that ``cache`` is actually a CacheSet object in this example):: obj = cache.get(some_id, my_class) if obj is None: try: obj = create_object(some_id) cache.put(some_id, my_class, obj) finally: cache.finishPut(cls) This method checks both the main cache (which retains references) and the 'expired' cache, which retains only weak references. """ if self.doCache: if self.cullCount > self.cullFrequency: # Two threads could hit the cull in a row, but # that's not so bad. At least by setting cullCount # back to zero right away we avoid this. The cull # method has a lock, so it's threadsafe. self.cullCount = 0 self.cull() else: self.cullCount += 1 try: return self.cache[id] except KeyError: pass self.lock.acquire() try: val = self.cache[id] except KeyError: pass else: self.lock.release() return val try: val = self.expiredCache[id]() except KeyError: return None else: del self.expiredCache[id] if val is None: return None self.cache[id] = val self.lock.release() return val else: try: val = self.expiredCache[id]() if val is not None: return val except KeyError: pass self.lock.acquire() try: val = self.expiredCache[id]() except KeyError: return None else: if val is None: del self.expiredCache[id] return None self.lock.release() return val def put(self, id, obj): """ Puts an object into the cache. Should only be called after .get(), so that duplicate objects don't end up in the cache. """ if self.doCache: self.cache[id] = obj else: self.expiredCache[id] = ref(obj) def finishPut(self): """ Releases the lock that is retained when .get() is called and returns None. """ self.lock.release() def created(self, id, obj): """ Inserts and object into the cache. Should be used when no one else knows about the object yet, so there cannot be any object already in the cache. After a database INSERT is an example of this situation. """ if self.doCache: self.cache[id] = obj else: self.expiredCache[id] = ref(obj) def cull(self): """ Runs through the cache and expires objects. E.g., if ``cullFraction`` is 3, then every third object is moved to the 'expired' (aka weakref) cache. """ self.lock.acquire() try: keys = self.cache.keys() for i in xrange(self.cullOffset, len(keys), self.cullFraction): id = keys[i] self.expiredCache[id] = ref(self.cache[id]) del self.cache[id] # This offset tries to balance out which objects we # expire, so no object will just hang out in the cache # forever. self.cullOffset = (self.cullOffset + 1) % self.cullFraction finally: self.lock.release() def clear(self): """ Removes everything from the cache. Warning! This can cause duplicate objects in memory. """ if self.doCache: self.cache.clear() self.expiredCache.clear() def expire(self, id): """ Expires a single object. Typically called after a delete. Doesn't even keep a weakref. (@@: bad name?) """ if not self.doCache: return self.lock.acquire() try: if self.cache.has_key(id): del self.cache[id] if self.expiredCache.has_key(id): del self.expiredCache[id] finally: self.lock.release() def expireAll(self): """ Expires all objects, moving them all into the expired/weakref cache. """ if not self.doCache: return self.lock.acquire() try: for key, value in self.cache.items(): self.expiredCache[key] = ref(value) self.cache = {} finally: self.lock.release() def allIDs(self): """ Returns the IDs of all objects in the cache. """ if self.doCache: all = self.cache.keys() else: all = [] for id, value in self.expiredCache.items(): if value(): all.append(id) return all class CacheSet(object): """ A CacheSet is used to collect and maintain a series of caches. In SQLObject, there is one CacheSet per connection, and one Cache in the CacheSet for each class, since IDs are not unique across classes. It contains methods similar to Cache, but that take a ``cls`` argument. """ def __init__(self, *args, **kw): self.caches = {} self.args = args self.kw = kw def get(self, id, cls): try: return self.caches[cls.__name__].get(id) except KeyError: self.caches[cls.__name__] = CacheFactory(*self.args, **self.kw) return self.caches[cls.__name__].get(id) def put(self, id, cls, obj): self.caches[cls.__name__].put(id, obj) def finishPut(self, cls): self.caches[cls.__name__].finishPut() def created(self, id, cls, obj): try: self.caches[cls.__name__].created(id, obj) except KeyError: self.caches[cls.__name__] = CacheFactory(*self.args, **self.kw) self.caches[cls.__name__].created(id, obj) def expire(self, id, cls): try: self.caches[cls.__name__].expire(id) except KeyError: pass def clear(self, cls=None): if cls is None: for cache in self.caches.values(): cache.clear() elif self.caches.has_key(cls.__name__): self.caches[cls.__name__].clear() def tryGet(self, id, cls): return self.tryGetByName(id, cls.__name__) def tryGetByName(self, id, clsname): try: return self.caches[clsname].tryGet(id) except KeyError: return None def allIDs(self, cls): try: self.caches[cls.__name__].allIDs() except KeyError: return [] def allSubCaches(self): return self.caches.values() def allSubCachesByClassNames(self): return self.caches PKa95Rsqlobject/dbconnection.pyfrom __future__ import generators True, False = 1==1, 0==1 import threading from util.threadinglocal import local as threading_local import re import warnings import atexit import os import new import types import urllib import weakref import inspect import sqlbuilder from cache import CacheSet import col popKey = col.popKey import main from joins import sorter from converters import sqlrepr import classregistry warnings.filterwarnings("ignore", "DB-API extension cursor.lastrowid used") _connections = {} def _closeConnection(ref): conn = ref() if conn is not None: conn.close() class DBConnection: def __init__(self, name=None, debug=False, debugOutput=False, cache=True, style=None, autoCommit=True, debugThreading=False, registry=None): self.name = name self.debug = debug self.debugOutput = debugOutput self.debugThreading = debugThreading self.cache = CacheSet(cache=cache) self.doCache = cache self.style = style self._connectionNumbers = {} self._connectionCount = 1 self.autoCommit = autoCommit self.registry = registry or None classregistry.registry(self.registry).addCallback( self.soClassAdded) registerConnectionInstance(self) atexit.register(_closeConnection, weakref.ref(self)) def uri(self): auth = getattr(self, 'user', None) or '' if auth: if self.password: auth = auth + ':' + self.password auth = auth + '@' else: assert not getattr(self, 'password', None), ( 'URIs cannot express passwords without usernames') uri = '%s://%s' % (self.dbName, auth) if self.host: uri += self.host uri += '/' db = self.db if db.startswith('/'): db = path[1:] return uri + db def isSupported(cls): raise NotImplemented isSupported = classmethod(isSupported) def connectionFromURI(cls, uri): raise NotImplemented connectionFromURI = classmethod(connectionFromURI) def _parseURI(uri): schema, rest = uri.split(':', 1) assert rest.startswith('/'), "URIs must start with scheme:/ -- you did not include a / (in %r)" % rest if rest.startswith('/') and not rest.startswith('//'): host = None rest = rest[1:] elif rest.startswith('///'): host = None rest = rest[3:] else: rest = rest[2:] if rest.find('/') == -1: host = rest rest = '' else: host, rest = rest.split('/', 1) if host and host.find('@') != -1: user = host[:host.rfind('@')] # Python 2.3 doesn't have .rsplit() host = host[host.rfind('@')+1:] # !!! if user.find(':') != -1: user, password = user.split(':', 1) else: password = None else: user = password = None if host and host.find(':') != -1: _host, port = host.split(':') try: port = int(port) except ValueError: raise ValueError, "port must be integer, got '%s' instead" % port if not (1 <= port <= 65535): raise ValueError, "port must be integer in the range 1-65535, got '%d' instead" % port host = _host else: port = None path = '/' + rest if os.name == 'nt': if (len(rest) > 1) and (rest[1] == '|'): path = "%s:%s" % (rest[0], rest[2:]) args = {} if path.find('?') != -1: path, arglist = path.split('?', 1) arglist = arglist.split('&') for single in arglist: argname, argvalue = single.split('=', 1) argvalue = urllib.unquote(argvalue) args[argname] = argvalue return user, password, host, port, path, args _parseURI = staticmethod(_parseURI) def soClassAdded(self, soClass): """ This is called for each new class; we use this opportunity to create an instance method that is bound to the class and this connection. """ name = soClass.__name__ assert not hasattr(self, name), ( "Connection %r already has an attribute with the name " "%r (and you just created the conflicting class %r)" % (self, name, soClass)) setattr(self, name, ConnWrapper(soClass, self)) class ConnWrapper(object): """ This represents a SQLObject class that is bound to a specific connection (instances have a connection instance variable, but classes are global, so this is binds the connection variable lazily when a class method is accessed) """ # @@: methods that take connection arguments should be explicitly # marked up instead of the implicit use of a connection argument # and inspect.getargspec() def __init__(self, soClass, connection): self._soClass = soClass self._connection = connection def __call__(self, *args, **kw): kw['connection'] = self._connection return self._soClass(*args, **kw) def __getattr__(self, attr): meth = getattr(self._soClass, attr) if not isinstance(meth, types.MethodType): # We don't need to wrap non-methods return meth try: takes_conn = meth.takes_connection except AttributeError: args, varargs, varkw, defaults = inspect.getargspec(meth) assert not varkw and not varargs, ( "I cannot tell whether I must wrap this method, " "because it takes **kw: %r" % meth) takes_conn = 'connection' in args meth.im_func.takes_connection = takes_conn if not takes_conn: return meth return ConnMethodWrapper(meth, self._connection) class ConnMethodWrapper(object): def __init__(self, method, connection): self._method = method self._connection = connection def __getattr__(self, attr): return getattr(self._method, attr) def __call__(self, *args, **kw): kw['connection'] = self._connection return self._method(*args, **kw) def __repr__(self): return '' % ( self._method, self._connection) class DBAPI(DBConnection): """ Subclass must define a `makeConnection()` method, which returns a newly-created connection object. ``queryInsertID`` must also be defined. """ dbName = None def __init__(self, **kw): self._pool = [] self._poolLock = threading.Lock() DBConnection.__init__(self, **kw) self._binaryType = type(self.module.Binary('')) def _runWithConnection(self, meth, *args): conn = self.getConnection() try: val = meth(conn, *args) finally: self.releaseConnection(conn) return val def getConnection(self): self._poolLock.acquire() try: if not self._pool: conn = self.makeConnection() self._connectionNumbers[id(conn)] = self._connectionCount self._connectionCount += 1 else: conn = self._pool.pop() if self.debug: s = 'ACQUIRE' if self._pool is not None: s += ' pool=[%s]' % ', '.join([str(self._connectionNumbers[id(v)]) for v in self._pool]) self.printDebug(conn, s, 'Pool') return conn finally: self._poolLock.release() def releaseConnection(self, conn, explicit=False): if self.debug: if explicit: s = 'RELEASE (explicit)' else: s = 'RELEASE (implicit, autocommit=%s)' % self.autoCommit if self._pool is None: s += ' no pooling' else: s += ' pool=[%s]' % ', '.join([str(self._connectionNumbers[id(v)]) for v in self._pool]) self.printDebug(conn, s, 'Pool') if self.supportTransactions and not explicit: if self.autoCommit == 'exception': if self.debug: self.printDebug(conn, 'auto/exception', 'ROLLBACK') conn.rollback() raise Exception, 'Object used outside of a transaction; implicit COMMIT or ROLLBACK not allowed' elif self.autoCommit: if self.debug: self.printDebug(conn, 'auto', 'COMMIT') if not getattr(conn, 'autocommit', False): conn.commit() else: if self.debug: self.printDebug(conn, 'auto', 'ROLLBACK') conn.rollback() if self._pool is not None: if conn not in self._pool: # @@: We can get duplicate releasing of connections with # the __del__ in Iteration (unfortunately, not sure why # it happens) self._pool.insert(0, conn) else: conn.close() def printDebug(self, conn, s, name, type='query'): if name == 'Pool' and self.debug != 'Pool': return if type == 'query': sep = ': ' else: sep = '->' s = repr(s) n = self._connectionNumbers[id(conn)] spaces = ' '*(8-len(name)) if self.debugThreading: threadName = threading.currentThread().getName() threadName = (':' + threadName + ' '*(8-len(threadName))) else: threadName = '' print '%(n)2i%(threadName)s/%(name)s%(spaces)s%(sep)s %(s)s' % locals() def _executeRetry(self, conn, cursor, query): if self.debug: self.printDebug(conn, query, 'QueryR') return cursor.execute(query) def _query(self, conn, s): if self.debug: self.printDebug(conn, s, 'Query') self._executeRetry(conn, conn.cursor(), s) def query(self, s): return self._runWithConnection(self._query, s) def _queryAll(self, conn, s): if self.debug: self.printDebug(conn, s, 'QueryAll') c = conn.cursor() self._executeRetry(conn, c, s) value = c.fetchall() if self.debugOutput: self.printDebug(conn, value, 'QueryAll', 'result') return value def queryAll(self, s): return self._runWithConnection(self._queryAll, s) def _queryAllDescription(self, conn, s): """ Like queryAll, but returns (description, rows), where the description is cursor.description (which gives row types) """ if self.debug: self.printDebug(conn, s, 'QueryAllDesc') c = conn.cursor() self._executeRetry(conn, c, s) value = c.fetchall() if self.debugOutput: self.printDebug(conn, value, 'QueryAll', 'result') return c.description, value def queryAllDescription(self, s): return self._runWithConnection(self._queryAllDescription, s) def _queryOne(self, conn, s): if self.debug: self.printDebug(conn, s, 'QueryOne') c = conn.cursor() self._executeRetry(conn, c, s) value = c.fetchone() if self.debugOutput: self.printDebug(conn, value, 'QueryOne', 'result') return value def queryOne(self, s): return self._runWithConnection(self._queryOne, s) def _insertSQL(self, table, names, values): return ("INSERT INTO %s (%s) VALUES (%s)" % (table, ', '.join(names), ', '.join([self.sqlrepr(v) for v in values]))) def transaction(self): return Transaction(self) def queryInsertID(self, soInstance, id, names, values): return self._runWithConnection(self._queryInsertID, soInstance, id, names, values) def iterSelect(self, select): return select.IterationClass(self, self.getConnection(), select, keepConnection=False) def accumulateSelect(self, select, *expressions): """ Apply an accumulate function(s) (SUM, COUNT, MIN, AVG, MAX, etc...) to the select object. """ ops = select.ops join = ops.get('join') if join: tables = self._fixTablesForJoins(select) else: tables = select.tables q = "SELECT %s" % ", ".join([str(expression) for expression in expressions]) q += " FROM %s" % ", ".join(tables) if join: q += self._addJoins(select, tables) q += " WHERE" q = self._addWhereClause(select, q, limit=0, order=0) val = self.queryOne(q) if len(expressions) == 1: val = val[0] return val def queryForSelect(self, select): ops = select.ops join = ops.get('join') cls = select.sourceClass if join: tables = self._fixTablesForJoins(select) else: tables = select.tables if ops.get('distinct', False): q = 'SELECT DISTINCT ' else: q = 'SELECT ' if ops.get('lazyColumns', 0): q += "%s.%s FROM %s" % \ (cls.sqlmeta.table, cls.sqlmeta.idName, ", ".join(tables)) else: columns = ", ".join(["%s.%s" % (cls.sqlmeta.table, col.dbName) for col in cls.sqlmeta.columnList]) if columns: q += "%s.%s, %s FROM %s" % \ (cls.sqlmeta.table, cls.sqlmeta.idName, columns, ", ".join(tables)) else: q += "%s.%s FROM %s" % \ (cls.sqlmeta.table, cls.sqlmeta.idName, ", ".join(tables)) if join: q += self._addJoins(select, tables) q += " WHERE" return self._addWhereClause(select, q) def _fixTablesForJoins(self, select): ops = select.ops join = ops.get('join') tables = select.tables if type(join) is str: return tables else: tables = tables[:] # maka a copy for modification if isinstance(join, sqlbuilder.SQLJoin): if join.table1 in tables: tables.remove(join.table1) if join.table2 in tables: tables.remove(join.table2) else: for j in join: if j.table1 in tables: tables.remove(j.table1) if j.table2 in tables: tables.remove(j.table2) return tables def _addJoins(self, select, tables): ops = select.ops join = ops.get('join') if type(join) is str: join_str = ' ' + join elif isinstance(join, sqlbuilder.SQLJoin): if tables and join.table1: join_str = ", " else: join_str = ' ' join_str += self.sqlrepr(join) else: join_str = "" for j in join: if tables and j.table1: sep = ", " else: sep = ' ' join_str += sep + self.sqlrepr(j) return join_str def _addWhereClause(self, select, startSelect, limit=1, order=1): q = select.clause if type(q) not in [type(''), type(u'')]: q = self.sqlrepr(q) ops = select.ops def clauseList(lst, desc=False): if type(lst) not in (type([]), type(())): lst = [lst] lst = [clauseQuote(i) for i in lst] if desc: lst = [sqlbuilder.DESC(i) for i in lst] return ', '.join([self.sqlrepr(i) for i in lst]) def clauseQuote(s): if type(s) is type(""): if s.startswith('-'): desc = True s = s[1:] else: desc = False assert sqlbuilder.sqlIdentifier(s), "Strings in clauses are expected to be column identifiers. I got: %r" % s if s in select.sourceClass.sqlmeta.columns: s = select.sourceClass.sqlmeta.columns[s].dbName if desc: return sqlbuilder.DESC(sqlbuilder.SQLConstant(s)) else: return sqlbuilder.SQLConstant(s) else: return s if order and ops.get('dbOrderBy'): q = "%s ORDER BY %s" % (q, clauseList(ops['dbOrderBy'], ops.get('reversed', False))) start = ops.get('start', 0) end = ops.get('end', None) q = startSelect + ' ' + q if limit and (start or end): # @@: Raising an error might be an annoyance, but some warning is # in order. #assert ops.get('orderBy'), "Getting a slice of an unordered set is unpredictable!" q = self._queryAddLimitOffset(q, start, end) return q def _SO_createJoinTable(self, join): self.query(self._SO_createJoinTableSQL(join)) def _SO_createJoinTableSQL(self, join): return ('CREATE TABLE %s (\n%s %s,\n%s %s\n)' % (join.intermediateTable, join.joinColumn, self.joinSQLType(join), join.otherColumn, self.joinSQLType(join))) def _SO_dropJoinTable(self, join): self.query("DROP TABLE %s" % join.intermediateTable) def _SO_createIndex(self, soClass, index): self.query(self.createIndexSQL(soClass, index)) def createIndexSQL(self, soClass, index): assert 0, 'Implement in subclasses' def createTable(self, soClass): self.query(self.createTableSQL(soClass)) def createTableSQL(self, soClass): return ('CREATE TABLE %s (\n%s\n)' % (soClass.sqlmeta.table, self.createColumns(soClass))) def createColumns(self, soClass): columnDefs = [self.createIDColumn(soClass)] \ + [self.createColumn(soClass, col) for col in soClass.sqlmeta.columnList] return ",\n".join([" %s" % c for c in columnDefs]) def createColumn(self, soClass, col): assert 0, "Implement in subclasses" def dropTable(self, tableName, cascade=False): self.query("DROP TABLE %s" % tableName) def clearTable(self, tableName): # 3-03 @@: Should this have a WHERE 1 = 1 or similar # clause? In some configurations without the WHERE clause # the query won't go through, but maybe we shouldn't override # that. self.query("DELETE FROM %s" % tableName) def createBinary(self, value): """ Create a binary object wrapper for the given database. """ # Default is Binary() function from the connection driver. return self.module.Binary(value) # The _SO_* series of methods are sorts of "friend" methods # with SQLObject. They grab values from the SQLObject instances # or classes freely, but keep the SQLObject class from accessing # the database directly. This way no SQL is actually created # in the SQLObject class. def _SO_update(self, so, values): self.query("UPDATE %s SET %s WHERE %s = (%s)" % (so.sqlmeta.table, ", ".join(["%s = (%s)" % (dbName, self.sqlrepr(value)) for dbName, value in values]), so.sqlmeta.idName, self.sqlrepr(so.id))) def _SO_selectOne(self, so, columnNames): columns = ", ".join(columnNames) if columns: return self.queryOne( "SELECT %s FROM %s WHERE %s = (%s)" % (columns, so.sqlmeta.table, so.sqlmeta.idName, self.sqlrepr(so.id))) else: return self.queryOne( "SELECT NULL FROM %s WHERE %s = (%s)" % (so.sqlmeta.table, so.sqlmeta.idName, self.sqlrepr(so.id))) def _SO_selectOneAlt(self, cls, columnNames, column, value): return self.queryOne("SELECT %s FROM %s WHERE %s = %s" % (", ".join(columnNames), cls.sqlmeta.table, column, self.sqlrepr(value))) def _SO_delete(self, so): self.query("DELETE FROM %s WHERE %s = (%s)" % (so.sqlmeta.table, so.sqlmeta.idName, self.sqlrepr(so.id))) def _SO_selectJoin(self, soClass, column, value): return self.queryAll("SELECT %s FROM %s WHERE %s = (%s)" % (soClass.sqlmeta.idName, soClass.sqlmeta.table, column, self.sqlrepr(value))) def _SO_intermediateJoin(self, table, getColumn, joinColumn, value): return self.queryAll("SELECT %s FROM %s WHERE %s = (%s)" % (getColumn, table, joinColumn, self.sqlrepr(value))) def _SO_intermediateDelete(self, table, firstColumn, firstValue, secondColumn, secondValue): self.query("DELETE FROM %s WHERE %s = (%s) AND %s = (%s)" % (table, firstColumn, self.sqlrepr(firstValue), secondColumn, self.sqlrepr(secondValue))) def _SO_intermediateInsert(self, table, firstColumn, firstValue, secondColumn, secondValue): self.query("INSERT INTO %s (%s, %s) VALUES (%s, %s)" % (table, firstColumn, secondColumn, self.sqlrepr(firstValue), self.sqlrepr(secondValue))) def _SO_columnClause(self, soClass, kw): ops = {None: "IS"} data = {} if 'id' in kw: data[soClass.sqlmeta.idName] = popKey(kw, 'id') for key, col in soClass.sqlmeta.columns.items(): if key in kw: data[col.dbName] = popKey(kw, key) elif col.foreignName in kw: obj = popKey(kw, col.foreignName) if isinstance(obj, main.SQLObject): data[col.dbName] = obj.id else: data[col.dbName] = obj if kw: # pick the first key from kw to use to raise the error, raise TypeError, "got an unexpected keyword argument(s): %r" % kw.keys() if not data: return None return ' AND '.join( ['%s %s %s' % (dbName, ops.get(value, "="), self.sqlrepr(value)) for dbName, value in data.items()]) def sqlrepr(self, v): return sqlrepr(v, self.dbName) def __del__(self): self.close() def close(self): if not hasattr(self, '_pool'): # Probably there was an exception while creating this # instance, so it is incomplete. return if not self._pool: return self._poolLock.acquire() try: conns = self._pool[:] self._pool[:] = [] for conn in conns: try: conn.close() except self.module.Error: pass del conn del conns finally: self._poolLock.release() def createEmptyDatabase(self): """ Create an empty database. """ raise NotImplementedError class Iteration(object): def __init__(self, dbconn, rawconn, select, keepConnection=False): self.dbconn = dbconn self.rawconn = rawconn self.select = select self.keepConnection = keepConnection self.cursor = rawconn.cursor() self.query = self.dbconn.queryForSelect(select) if dbconn.debug: dbconn.printDebug(rawconn, self.query, 'Select') self.dbconn._executeRetry(self.rawconn, self.cursor, self.query) def __iter__(self): return self def next(self): result = self.cursor.fetchone() if result is None: self._cleanup() raise StopIteration if result[0] is None: return None if self.select.ops.get('lazyColumns', 0): obj = self.select.sourceClass.get(result[0], connection=self.dbconn) return obj else: obj = self.select.sourceClass.get(result[0], selectResults=result[1:], connection=self.dbconn) return obj def _cleanup(self): if getattr(self, 'query', None) is None: # already cleaned up return self.query = None if not self.keepConnection: self.dbconn.releaseConnection(self.rawconn) self.dbconn = self.rawconn = self.select = self.cursor = None def __del__(self): self._cleanup() class Transaction(object): def __init__(self, dbConnection): # this is to skip __del__ in case of an exception in this __init__ self._obsolete = True self._dbConnection = dbConnection self._connection = dbConnection.getConnection() self._dbConnection._setAutoCommit(self._connection, 0) self.cache = CacheSet(cache=dbConnection.doCache) self._deletedCache = {} self._obsolete = False def assertActive(self): assert not self._obsolete, "This transaction has already gone through ROLLBACK; begin another transaction" def query(self, s): self.assertActive() return self._dbConnection._query(self._connection, s) def queryAll(self, s): self.assertActive() return self._dbConnection._queryAll(self._connection, s) def queryOne(self, s): self.assertActive() return self._dbConnection._queryOne(self._connection, s) def queryInsertID(self, soInstance, id, names, values): self.assertActive() return self._dbConnection._queryInsertID( self._connection, soInstance, id, names, values) def iterSelect(self, select): self.assertActive() # We can't keep the cursor open with results in a transaction, # because we might want to use the connection while we're # still iterating through the results. # @@: But would it be okay for psycopg, with threadsafety # level 2? return iter(list(select.IterationClass(self, self._connection, select, keepConnection=True))) def _SO_delete(self, inst): cls = inst.__class__.__name__ if not self._deletedCache.has_key(cls): self._deletedCache[cls] = [] self._deletedCache[cls].append(inst.id) meth = new.instancemethod(self._dbConnection._SO_delete.im_func, self, self.__class__) return meth(inst) def commit(self): if self._obsolete: # @@: is it okay to get extraneous commits? return if self._dbConnection.debug: self._dbConnection.printDebug(self._connection, '', 'COMMIT') self._connection.commit() subCaches = [(sub[0], sub[1].allIDs()) for sub in self.cache.allSubCachesByClassNames().items()] subCaches.extend([(x[0], x[1]) for x in self._deletedCache.items()]) for cls, ids in subCaches: for id in ids: inst = self._dbConnection.cache.tryGetByName(id, cls) if inst is not None: inst.expire() def rollback(self): if self._obsolete: # @@: is it okay to get extraneous rollbacks? return if self._dbConnection.debug: self._dbConnection.printDebug(self._connection, '', 'ROLLBACK') subCaches = [(sub, sub.allIDs()) for sub in self.cache.allSubCaches()] self._connection.rollback() for subCache, ids in subCaches: for id in ids: inst = subCache.tryGet(id) if inst is not None: inst.expire() self._makeObsolete() def __getattr__(self, attr): """ If nothing else works, let the parent connection handle it. Except with this transaction as 'self'. Poor man's acquisition? Bad programming? Okay, maybe. """ self.assertActive() attr = getattr(self._dbConnection, attr) try: func = attr.im_func except AttributeError: if isinstance(attr, ConnWrapper): return ConnWrapper(attr._soClass, self) else: return attr else: meth = new.instancemethod(func, self, self.__class__) return meth def _makeObsolete(self): self._obsolete = True if self._dbConnection.autoCommit: self._dbConnection._setAutoCommit(self._connection, 1) self._dbConnection.releaseConnection(self._connection, explicit=True) self._connection = None self._deletedCache = {} def begin(self): # @@: Should we do this, or should begin() be a no-op when we're # not already obsolete? assert self._obsolete, "You cannot begin a new transaction session without rolling back this one" self._obsolete = False self._connection = self._dbConnection.getConnection() self._dbConnection._setAutoCommit(self._connection, 0) def __del__(self): if self._obsolete: return self.rollback() class ConnectionHub(object): """ This object serves as a hub for connections, so that you can pass in a ConnectionHub to a SQLObject subclass as though it was a connection, but actually bind a real database connection later. You can also bind connections on a per-thread basis. You must hang onto the original ConnectionHub instance, as you cannot retrieve it again from the class or instance. To use the hub, do something like:: hub = ConnectionHub() class MyClass(SQLObject): _connection = hub hub.threadConnection = connectionFromURI('...') """ def __init__(self): self.threadingLocal = threading_local() def __get__(self, obj, type=None): # I'm a little surprised we have to do this, but apparently # the object's private dictionary of attributes doesn't # override this descriptor. if obj and obj.__dict__.has_key('_connection'): return obj.__dict__['_connection'] return self.getConnection() def __set__(self, obj, value): obj.__dict__['_connection'] = value def getConnection(self): try: return self.threadingLocal.connection except AttributeError: try: return self.processConnection except AttributeError: raise AttributeError( "No connection has been defined for this thread " "or process") def _set_threadConnection(self, value): self.threadingLocal.connection = value def _get_threadConnection(self): return self.threadingLocal.connection def _del_threadConnection(self): del self.threadingLocal.connection threadConnection = property(_get_threadConnection, _set_threadConnection, _del_threadConnection) class ConnectionURIOpener(object): def __init__(self): self.schemeBuilders = {} self.schemeSupported = {} self.instanceNames = {} self.cachedURIs = {} def registerConnection(self, schemes, builder, isSupported): for uriScheme in schemes: assert not self.schemeBuilders.has_key(uriScheme) \ or self.schemeBuilders[uriScheme] is builder, \ "A driver has already been registered for the URI scheme %s" % uriScheme self.schemeBuilders[uriScheme] = builder self.schemeSupported = isSupported def registerConnectionInstance(self, inst): if inst.name: assert not self.instanceNames.has_key(inst.name) \ or self.instanceNames[inst.name] is cls, \ "A instance has already been registered with the name %s" % inst.name assert inst.name.find(':') == -1, "You cannot include ':' in your class names (%r)" % cls.name self.instanceNames[inst.name] = inst def connectionForURI(self, uri, **args): if args: if '?' not in uri: uri += '?' uri += urllib.urlencode(args) if self.cachedURIs.has_key(uri): return self.cachedURIs[uri] if uri.find(':') != -1: scheme, rest = uri.split(':', 1) assert self.schemeBuilders.has_key(scheme), ( "No SQLObject driver exists for %s (only %s)" % (scheme, ', '.join(self.schemeBuilders.keys()))) conn = self.schemeBuilders[scheme]().connectionFromURI(uri) else: # We just have a name, not a URI assert self.instanceNames.has_key(uri), \ "No SQLObject driver exists under the name %s" % uri conn = self.instanceNames[uri] # @@: Do we care if we clobber another connection? self.cachedURIs[uri] = conn return conn TheURIOpener = ConnectionURIOpener() registerConnection = TheURIOpener.registerConnection registerConnectionInstance = TheURIOpener.registerConnectionInstance connectionForURI = TheURIOpener.connectionForURI PKa95[ gςςsqlobject/sqlbuilder.py""" sqlobject.sqlbuilder -------------------- :author: Ian Bicking Builds SQL expressions from normal Python expressions. Disclaimer ---------- This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Instructions ------------ To begin a SQL expression, you must use some sort of SQL object -- a field, table, or SQL statement (``SELECT``, ``INSERT``, etc.) You can then use normal operators, with the exception of: `and`, `or`, `not`, and `in`. You can use the `AND`, `OR`, `NOT`, and `IN` functions instead, or you can also use `&`, `|`, and `~` for `and`, `or`, and `not` respectively (however -- the precidence for these operators doesn't work as you would want, so you must use many parenthesis). To create a sql field, table, or constant/function, use the namespaces `table`, `const`, and `func`. For instance, ``table.address`` refers to the ``address`` table, and ``table.address.state`` refers to the ``state`` field in the address table. ``const.NULL`` is the ``NULL`` SQL constant, and ``func.NOW()`` is the ``NOW()`` function call (`const` and `func` are actually identicle, but the two names are provided for clarity). Once you create this object, expressions formed with it will produce SQL statements. The ``sqlrepr(obj)`` function gets the SQL representation of these objects, as well as the proper SQL representation of basic Python types (None==NULL). There are a number of DB-specific SQL features that this does not implement. There are a bunch of normal ANSI features also not present -- particularly left joins, among others. You may wish to only use this to generate ``WHERE`` clauses. See the bottom of this module for some examples, and run it (i.e. ``python sql.py``) to see the results of those examples. """ ######################################## ## Constants ######################################## class VersionError(Exception): pass class NoDefault: pass True, False = (1==1), (0==1) import re, fnmatch import operator import threading from converters import sqlrepr, registerConverter, TRUE, FALSE safeSQLRE = re.compile(r'^[a-zA-Z_][a-zA-Z0-9_\.]*$') def sqlIdentifier(obj): return type(obj) is type("") and not not safeSQLRE.search(obj.strip()) def execute(expr, executor): if hasattr(expr, 'execute'): return expr.execute(executor) else: return expr ######################################## ## Expression generation ######################################## class SQLExpression: def __add__(self, other): return SQLOp("+", self, other) def __radd__(self, other): return SQLOp("+", other, self) def __sub__(self, other): return SQLOp("-", self, other) def __rsub__(self, other): return SQLOp("-", other, self) def __mul__(self, other): return SQLOp("*", self, other) def __rmul__(self, other): return SQLOp("*", other, self) def __div__(self, other): return SQLOp("/", self, other) def __rdiv__(self, other): return SQLOp("/", other, self) def __pos__(self): return SQLPrefix("+", self) def __neg__(self): return SQLPrefix("-", self) def __pow__(self, other): return SQLConstant("POW")(self, other) def __rpow__(self, other): return SQLConstant("POW")(other, self) def __abs__(self): return SQLConstant("ABS")(self) def __mod__(self, other): return SQLConstant("MOD")(self, other) def __rmod__(self, other): return SQLConstant("MOD")(other, self) def __lt__(self, other): return SQLOp("<", self, other) def __le__(self, other): return SQLOp("<=", self, other) def __gt__(self, other): return SQLOp(">", self, other) def __ge__(self, other): return SQLOp(">=", self, other) def __eq__(self, other): if other is None: return ISNULL(self) else: return SQLOp("=", self, other) def __ne__(self, other): if other is None: return ISNOTNULL(self) else: return SQLOp("<>", self, other) def __and__(self, other): return SQLOp("AND", self, other) def __rand__(self, other): return SQLOp("AND", other, self) def __or__(self, other): return SQLOp("OR", self, other) def __ror__(self, other): return SQLOp("OR", other, self) def __invert__(self): return SQLPrefix("NOT", self) def __call__(self, *args): return SQLCall(self, args) def __repr__(self): try: return self.__sqlrepr__(None) except AssertionError: return '<%s %s>' % ( self.__class__.__name__, hex(id(self))[2:]) def __str__(self): return repr(self) def __cmp__(self, other): raise VersionError, "Python 2.1+ required" def __rcmp__(self, other): raise VersionError, "Python 2.1+ required" def startswith(self, s): return STARTSWITH(self, s) def endswith(self, s): return ENDSWITH(self, s) def contains(self, s): return CONTAINSSTRING(self, s) def components(self): return [] def tablesUsed(self): return self.tablesUsedDict().keys() def tablesUsedDict(self): tables = {} for table in self.tablesUsedImmediate(): tables[table] = 1 for component in self.components(): tables.update(tablesUsedDict(component)) return tables def tablesUsedImmediate(self): return [] ####################################### # Converter for SQLExpression instances ####################################### def SQLExprConverter(value, db): return value.__sqlrepr__() registerConverter(SQLExpression, SQLExprConverter) def tablesUsedDict(obj): if hasattr(obj, "tablesUsedDict"): return obj.tablesUsedDict() else: return {} operatorMap = { "+": operator.add, "/": operator.div, "-": operator.sub, "*": operator.mul, "<": operator.lt, "<=": operator.le, "=": operator.eq, "!=": operator.ne, ">=": operator.ge, ">": operator.gt, "IN": operator.contains, "IS": operator.eq, } class SQLOp(SQLExpression): def __init__(self, op, expr1, expr2): self.op = op.upper() self.expr1 = expr1 self.expr2 = expr2 def __sqlrepr__(self, db): s1 = sqlrepr(self.expr1, db) s2 = sqlrepr(self.expr2, db) if s1[0] != '(' and s1 != 'NULL': s1 = '(' + s1 + ')' if s2[0] != '(' and s2 != 'NULL': s2 = '(' + s2 + ')' return "(%s %s %s)" % (s1, self.op, s2) def components(self): return [self.expr1, self.expr2] def execute(self, executor): if self.op == "AND": return execute(self.expr1, executor) \ and execute(self.expr2, executor) elif self.op == "OR": return execute(self.expr1, executor) \ or execute(self.expr2, executor) else: return operatorMap[self.op.upper()](execute(self.expr1, executor), execute(self.expr2, executor)) registerConverter(SQLOp, SQLExprConverter) class SQLCall(SQLExpression): def __init__(self, expr, args): self.expr = expr self.args = args def __sqlrepr__(self, db): return "%s%s" % (sqlrepr(self.expr, db), sqlrepr(self.args, db)) def components(self): return [self.expr] + list(self.args) def execute(self, executor): raise ValueError, "I don't yet know how to locally execute functions" registerConverter(SQLCall, SQLExprConverter) class SQLPrefix(SQLExpression): def __init__(self, prefix, expr): self.prefix = prefix self.expr = expr def __sqlrepr__(self, db): return "%s %s" % (self.prefix, sqlrepr(self.expr, db)) def components(self): return [self.expr] def execute(self, executor): expr = execute(self.expr, executor) if prefix == "+": return expr elif prefix == "-": return -expr elif prefix.upper() == "NOT": return not expr registerConverter(SQLPrefix, SQLExprConverter) class SQLConstant(SQLExpression): def __init__(self, const): self.const = const def __sqlrepr__(self, db): return self.const def execute(self, executor): raise ValueError, "I don't yet know how to execute SQL constants" registerConverter(SQLConstant, SQLExprConverter) class SQLTrueClauseClass(SQLExpression): def __sqlrepr__(self, db): return "1 = 1" def execute(self, executor): return 1 SQLTrueClause = SQLTrueClauseClass() registerConverter(SQLTrueClauseClass, SQLExprConverter) ######################################## ## Namespaces ######################################## class Field(SQLExpression): def __init__(self, tableName, fieldName): self.tableName = tableName self.fieldName = fieldName def __sqlrepr__(self, db): return self.tableName + "." + self.fieldName def tablesUsedImmediate(self): return [self.tableName] def execute(self, executor): return executor.field(self.tableName, self.fieldName) class SQLObjectField(Field): def __init__(self, tableName, fieldName, original): self.original = original Field.__init__(self, tableName, fieldName) registerConverter(SQLObjectField, SQLExprConverter) class UnicodeField(SQLObjectField): def __init__(self, tableName, fieldName, original, column): SQLObjectField.__init__(self, tableName, fieldName, original) self.column = column def __eq__(self, other): if isinstance(other, unicode): other = other.encode(self.column.dbEncoding) return SQLOp('=', self, other) def __ne__(self, other): if isinstance(other, unicode): other = other.encode(self.column.dbEncoding) return SQLOp('<>', self, other) registerConverter(UnicodeField, SQLExprConverter) class Table(SQLExpression): FieldClass = Field def __init__(self, tableName): self.tableName = tableName def __getattr__(self, attr): if attr.startswith('__'): raise AttributeError return self.FieldClass(self.tableName, attr) def __sqlrepr__(self, db): return str(self.tableName) def execute(self, executor): raise ValueError, "Tables don't have values" class SQLObjectTable(Table): FieldClass = SQLObjectField UnicodeFieldClass = UnicodeField def __init__(self, soClass): self.soClass = soClass assert soClass.sqlmeta.table, ( "Bad table name in class %r: %r" % (soClass, soClass.sqlmeta.table)) Table.__init__(self, soClass.sqlmeta.table) def __getattr__(self, attr): if attr.startswith('__'): raise AttributeError if attr == 'id': return self.FieldClass(self.tableName, self.soClass.sqlmeta.idName, attr) elif attr not in self.soClass.sqlmeta.columns: raise AttributeError("%s instance has no attribute '%s'" % (self.soClass.__name__, attr)) else: column = self.soClass.sqlmeta.columns[attr] if hasattr(column, "dbEncoding"): return self.UnicodeFieldClass(self.tableName, column.dbName, attr, column) else: return self.FieldClass(self.tableName, column.dbName, attr) class TableSpace: TableClass = Table def __getattr__(self, attr): if attr.startswith('__'): raise AttributeError return self.TableClass(attr) class ConstantSpace: def __getattr__(self, attr): if attr.startswith('__'): raise AttributeError return SQLConstant(attr) ######################################## ## Table aliases ######################################## class AliasField(Field): as_string = '' # set it to "AS" if your database requires it def __init__(self, tableName, fieldName, alias): Field.__init__(self, tableName, fieldName) self.alias = alias def __sqlrepr__(self, db): return self.alias + "." + self.fieldName def tablesUsedImmediate(self): return ["%s %s %s" % (self.tableName, self.as_string, self.alias)] class AliasTable(Table): FieldClass = AliasField _alias_lock = threading.Lock() _alias_counter = 0 def __init__(self, table, alias=None): if hasattr(table, "sqlmeta"): tableName = table.sqlmeta.table else: tableName = table table = None Table.__init__(self, tableName) self.table = table if alias is None: self._alias_lock.acquire() try: AliasTable._alias_counter += 1 alias = "%s_alias%d" % (tableName, AliasTable._alias_counter) finally: self._alias_lock.release() self.alias = alias def __getattr__(self, attr): if attr.startswith('__'): raise AttributeError if self.table: attr = getattr(self.table.q, attr).fieldName return self.FieldClass(self.tableName, attr, self.alias) class Alias: def __init__(self, table, alias=None): self.q = AliasTable(table, alias) ######################################## ## SQL Statements ######################################## class Select(SQLExpression): def __init__(self, items, where=NoDefault, groupBy=NoDefault, having=NoDefault, orderBy=NoDefault, limit=NoDefault): if type(items) is not type([]) and type(items) is not type(()): items = [items] self.items = items self.whereClause = where self.groupBy = groupBy self.having = having self.orderBy = orderBy self.limit = limit def __sqlrepr__(self, db): select = "SELECT %s" % ", ".join([sqlrepr(v, db) for v in self.items]) tables = {} things = list(self.items) if self.whereClause is not NoDefault: things.append(self.whereClause) for thing in things: if isinstance(thing, SQLExpression): tables.update(tablesUsedDict(thing)) tables = tables.keys() if tables: select += " FROM %s" % ", ".join(tables) if self.whereClause is not NoDefault: select += " WHERE %s" % sqlrepr(self.whereClause, db) if self.groupBy is not NoDefault: select += " GROUP BY %s" % sqlrepr(self.groupBy, db) if self.having is not NoDefault: select += " HAVING %s" % sqlrepr(self.having, db) if self.orderBy is not NoDefault: select += " ORDER BY %s" % sqlrepr(self.orderBy, db) if self.limit is not NoDefault: select += " LIMIT %s" % sqlrepr(self.limit, db) return select registerConverter(Select, SQLExprConverter) class Insert(SQLExpression): def __init__(self, table, valueList=None, values=None, template=NoDefault): self.template = template self.table = table if valueList: if values: raise TypeError, "You may only give valueList *or* values" self.valueList = valueList else: self.valueList = [values] def __sqlrepr__(self, db): if not self.valueList: return '' insert = "INSERT INTO %s" % self.table allowNonDict = True template = self.template if template is NoDefault and type(self.valueList[0]) is type({}): template = self.valueList[0].keys() allowNonDict = False if template is not NoDefault: insert += " (%s)" % ", ".join(template) insert += " VALUES " listToJoin = [] listToJoin_app = listToJoin.append for value in self.valueList: if type(value) is type({}): if template is NoDefault: raise TypeError, "You can't mix non-dictionaries with dictionaries in an INSERT if you don't provide a template (%s)" % repr(value) value = dictToList(template, value) elif not allowNonDict: raise TypeError, "You can't mix non-dictionaries with dictionaries in an INSERT if you don't provide a template (%s)" % repr(value) listToJoin_app("(%s)" % ", ".join([sqlrepr(v, db) for v in value])) insert = "%s%s" % (insert, ", ".join(listToJoin)) return insert registerConverter(Insert, SQLExprConverter) def dictToList(template, dict): list = [] for key in template: list.append(dict[key]) if len(dict.keys()) > len(template): raise TypeError, "Extra entries in dictionary that aren't asked for in template (template=%s, dict=%s)" % (repr(template), repr(dict)) return list class Update(SQLExpression): def __init__(self, table, values, template=NoDefault, where=NoDefault): self.table = table self.values = values self.template = template self.whereClause = where def __sqlrepr__(self, db): update = "%s %s" % (self.sqlName(), self.table) update += " SET" first = True if self.template is not NoDefault: for i in range(len(self.template)): if first: first = False else: update += "," update += " %s=%s" % (self.template[i], sqlrepr(self.values[i], db)) else: for key, value in self.values.items(): if first: first = False else: update += "," update += " %s=%s" % (key, sqlrepr(value, db)) if self.whereClause is not NoDefault: update += " WHERE %s" % sqlrepr(self.whereClause, db) return update def sqlName(self): return "UPDATE" registerConverter(Update, SQLExprConverter) class Delete(SQLExpression): """To be safe, this will signal an error if there is no where clause, unless you pass in where=None to the constructor.""" def __init__(self, table, where=NoDefault): self.table = table if where is NoDefault: raise TypeError, "You must give a where clause or pass in None to indicate no where clause" self.whereClause = where def __sqlrepr__(self, db): if self.whereClause is None: return "DELETE FROM %s" % self.table return "DELETE FROM %s WHERE %s" \ % (self.table, sqlrepr(self.whereClause, db)) registerConverter(Delete, SQLExprConverter) class Replace(Update): def sqlName(self): return "REPLACE" registerConverter(Replace, SQLExprConverter) ######################################## ## SQL Builtins ######################################## class DESC(SQLExpression): def __init__(self, expr): self.expr = expr def __sqlrepr__(self, db): if isinstance(self.expr, DESC): return sqlrepr(self.expr.expr, db) return '%s DESC' % sqlrepr(self.expr, db) def AND(*ops): op1 = ops[0] ops = ops[1:] if ops: return SQLOp("AND", op1, AND(*ops)) else: return op1 def OR(*ops): op1 = ops[0] ops = ops[1:] if ops: return SQLOp("OR", op1, OR(*ops)) else: return op1 def NOT(op): return SQLPrefix("NOT", op) def _IN(item, list): return SQLOp("IN", item, list) def IN(item, list): if isinstance(list, Select): return INSubquery(item, list) else: return _IN(item, list) def NOTIN(item, list): if isinstance(list, Select): return NOTINSubquery(item, list) else: return NOT(_IN(item, list)) def STARTSWITH(expr, string): return SQLOp("LIKE", expr, _LikeQuoted(string) + '%') def ENDSWITH(expr, string): return SQLOp("LIKE", expr, '%' + _LikeQuoted(string)) def CONTAINSSTRING(expr, string): return SQLOp("LIKE", expr, '%' + _LikeQuoted(string) + '%') def ISNULL(expr): return SQLOp("IS", expr, None) def ISNOTNULL(expr): return SQLOp("IS NOT", expr, None) class _LikeQuoted: # @@: I'm not sure what the quoting rules really are for all the # databases def __init__(self, expr): self.expr = expr self.prefix = '' self.postfix = '' def __radd__(self, s): self.prefix = s + self.prefix return self def __add__(self, s): self.postfix += s return self def __sqlrepr__(self, db): s = sqlrepr(self.expr, db)[1:-1] # remove quotes if db in ('postgres', 'mysql'): s = s.replace('%', '\\%') else: s = s.replace('%', '%%') return "'%s%s%s'" % (self.prefix, s, self.postfix) ######################################## ## SQL JOINs ######################################## class SQLJoin(SQLExpression): def __init__(self, table1, table2, op=','): if table1 and type(table1) <> str: if isinstance(table1, Alias): table1 = "%s AS %s" % (table1.q.tableName, table1.q.alias) else: table1 = table1.sqlmeta.table if type(table2) <> str: if isinstance(table2, Alias): table2 = "%s AS %s" % (table2.q.tableName, table2.q.alias) else: table2 = table2.sqlmeta.table self.table1 = table1 self.table2 = table2 self.op = op def __sqlrepr__(self, db): if self.table1: return "%s%s %s" % (self.table1, self.op, self.table2) else: return "%s %s" % (self.op, self.table2) registerConverter(SQLJoin, SQLExprConverter) def JOIN(table1, table2): return SQLJoin(table1, table2, " JOIN") def INNERJOIN(table1, table2): return SQLJoin(table1, table2, " INNER JOIN") def CROSSJOIN(table1, table2): return SQLJoin(table1, table2, " CROSS JOIN") def STRAIGHTJOIN(table1, table2): return SQLJoin(table1, table2, " STRAIGHT JOIN") def LEFTJOIN(table1, table2): return SQLJoin(table1, table2, " LEFT JOIN") def LEFTOUTERJOIN(table1, table2): return SQLJoin(table1, table2, " LEFT OUTER JOIN") def NATURALJOIN(table1, table2): return SQLJoin(table1, table2, " NATURAL JOIN") def NATURALLEFTJOIN(table1, table2): return SQLJoin(table1, table2, " NATURAL LEFT JOIN") def NATURALLEFTOUTERJOIN(table1, table2): return SQLJoin(table1, table2, " NATURAL LEFT OUTER JOIN") def RIGHTJOIN(table1, table2): return SQLJoin(table1, table2, " RIGHT JOIN") def RIGHTOUTERJOIN(table1, table2): return SQLJoin(table1, table2, " RIGHT OUTER JOIN") def NATURALRIGHTJOIN(table1, table2): return SQLJoin(table1, table2, " NATURAL RIGHT JOIN") def NATURALRIGHTOUTERJOIN(table1, table2): return SQLJoin(table1, table2, " NATURAL RIGHT OUTER JOIN") def FULLJOIN(table1, table2): return SQLJoin(table1, table2, " FULL JOIN") def FULLOUTERJOIN(table1, table2): return SQLJoin(table1, table2, " FULL OUTER JOIN") def NATURALFULLJOIN(table1, table2): return SQLJoin(table1, table2, " NATURAL FULL JOIN") def NATURALFULLOUTERJOIN(table1, table2): return SQLJoin(table1, table2, " NATURAL FULL OUTER JOIN") class SQLJoinConditional(SQLJoin): """Conditional JOIN""" def __init__(self, table1, table2, op, on_condition=None, using_columns=None): """For condition you must give on_condition or using_columns but not both on_condition can be a string or SQLExpression, for example Table1.q.col1 == Table2.q.col2 using_columns can be a string or a list of columns, e.g. (Table1.q.col1, Table2.q.col2) """ if not on_condition and not using_columns: raise TypeError, "You must give ON condition or USING columns" if on_condition and using_columns: raise TypeError, "You must give ON condition or USING columns but not both" SQLJoin.__init__(self, table1, table2, op) self.on_condition = on_condition self.using_columns = using_columns def __sqlrepr__(self, db): if self.on_condition: on_condition = self.on_condition if hasattr(on_condition, "__sqlrepr__"): on_condition = sqlrepr(on_condition, db) join = "%s %s ON %s" % (self.op, self.table2, on_condition) if self.table1: join = "%s %s" % (self.table1, join) return join elif self.using_columns: using_columns = [] for col in self.using_columns: if hasattr(col, "__sqlrepr__"): col = sqlrepr(col, db) using_columns.append(col) using_columns = ", ".join(using_columns) join = "%s %s USING (%s)" % (self.op, self.table2, using_columns) if self.table1: join = "%s %s" % (self.table1, join) return join else: RuntimeError, "Impossible error" registerConverter(SQLJoinConditional, SQLExprConverter) def INNERJOINConditional(table1, table2, on_condition=None, using_columns=None): return SQLJoinConditional(table1, table2, "INNER JOIN", on_condition, using_columns) def LEFTJOINConditional(table1, table2, on_condition=None, using_columns=None): return SQLJoinConditional(table1, table2, "LEFT JOIN", on_condition, using_columns) def LEFTOUTERJOINConditional(table1, table2, on_condition=None, using_columns=None): return SQLJoinConditional(table1, table2, "LEFT OUTER JOIN", on_condition, using_columns) def RIGHTJOINConditional(table1, table2, on_condition=None, using_columns=None): return SQLJoinConditional(table1, table2, "RIGHT JOIN", on_condition, using_columns) def RIGHTOUTERJOINConditional(table1, table2, on_condition=None, using_columns=None): return SQLJoinConditional(table1, table2, "RIGHT OUTER JOIN", on_condition, using_columns) def FULLJOINConditional(table1, table2, on_condition=None, using_columns=None): return SQLJoinConditional(table1, table2, "FULL JOIN", on_condition, using_columns) def FULLOUTERJOINConditional(table1, table2, on_condition=None, using_columns=None): return SQLJoinConditional(table1, table2, "FULL OUTER JOIN", on_condition, using_columns) class SQLJoinOn(SQLJoinConditional): """Conditional JOIN ON""" def __init__(self, table1, table2, op, on_condition): SQLJoinConditional.__init__(self, table1, table2, op, on_condition) registerConverter(SQLJoinOn, SQLExprConverter) class SQLJoinUsing(SQLJoinConditional): """Conditional JOIN USING""" def __init__(self, table1, table2, op, using_columns): SQLJoinConditional.__init__(self, table1, table2, op, None, using_columns) registerConverter(SQLJoinUsing, SQLExprConverter) def INNERJOINOn(table1, table2, on_condition): return SQLJoinOn(table1, table2, "INNER JOIN", on_condition) def LEFTJOINOn(table1, table2, on_condition): return SQLJoinOn(table1, table2, "LEFT JOIN", on_condition) def LEFTOUTERJOINOn(table1, table2, on_condition): return SQLJoinOn(table1, table2, "LEFT OUTER JOIN", on_condition) def RIGHTJOINOn(table1, table2, on_condition): return SQLJoinOn(table1, table2, "RIGHT JOIN", on_condition) def RIGHTOUTERJOINOn(table1, table2, on_condition): return SQLJoinOn(table1, table2, "RIGHT OUTER JOIN", on_condition) def FULLJOINOn(table1, table2, on_condition): return SQLJoinOn(table1, table2, "FULL JOIN", on_condition) def FULLOUTERJOINOn(table1, table2, on_condition): return SQLJoinOn(table1, table2, "FULL OUTER JOIN", on_condition) def INNERJOINUsing(table1, table2, using_columns): return SQLJoinUsing(table1, table2, "INNER JOIN", using_columns) def LEFTJOINUsing(table1, table2, using_columns): return SQLJoinUsing(table1, table2, "LEFT JOIN", using_columns) def LEFTOUTERJOINUsing(table1, table2, using_columns): return SQLJoinUsing(table1, table2, "LEFT OUTER JOIN", using_columns) def RIGHTJOINUsing(table1, table2, using_columns): return SQLJoinUsing(table1, table2, "RIGHT JOIN", using_columns) def RIGHTOUTERJOINUsing(table1, table2, using_columns): return SQLJoinUsing(table1, table2, "RIGHT OUTER JOIN", using_columns) def FULLJOINUsing(table1, table2, using_columns): return SQLJoinUsing(table1, table2, "FULL JOIN", using_columns) def FULLOUTERJOINUsing(table1, table2, using_columns): return SQLJoinUsing(table1, table2, "FULL OUTER JOIN", using_columns) ######################################## ## Subqueries (subselects) ######################################## class OuterField(Field): def tablesUsedImmediate(self): return [] class OuterTable(Table): FieldClass = OuterField def __init__(self, table): if hasattr(table, "sqlmeta"): tableName = table.sqlmeta.table else: tableName = table table = None Table.__init__(self, tableName) self.table = table class Outer: def __init__(self, table): self.q = OuterTable(table) class LIKE(SQLExpression): op = "LIKE" def __init__(self, expr, string): self.expr = expr self.string = string def __sqlrepr__(self, db): return "(%s %s (%s))" % (sqlrepr(self.expr, db), self.op, sqlrepr(self.string, db)) def components(self): return [self.expr, self.string] def execute(self, executor): if not hasattr(self, '_regex'): # @@: Crude, not entirely accurate dest = self.string dest = dest.replace("%%", "\001") dest = dest.replace("*", "\002") dest = dest.replace("%", "*") dest = dest.replace("\001", "%") dest = dest.replace("\002", "[*]") self._regex = re.compile(fnmatch.translate(dest), re.I) return self._regex.search(execute(self.expr, executor)) class RLIKE(LIKE): op = "RLIKE" def _get_op(self, db): if db in ('mysql', 'maxdb', 'firebird'): return "RLIKE" elif db == 'sqlite': return "REGEXP" elif db == 'postgres': return "~" else: return "LIKE" def __sqlrepr__(self, db): return "(%s %s (%s))" % ( sqlrepr(self.expr, db), self._get_op(db), sqlrepr(self.string, db) ) def execute(self, executor): self.op = self._get_op(self.db) return LIKE.execute(self, executor) class INSubquery(SQLExpression): op = "IN" def __init__(self, item, subquery): self.item = item self.subquery = subquery def components(self): return [self.item] def __sqlrepr__(self, db): return "%s %s (%s)" % (sqlrepr(self.item, db), self.op, sqlrepr(self.subquery, db)) class NOTINSubquery(INSubquery): op = "NOT IN" class Subquery(SQLExpression): def __init__(self, op, subquery): self.op = op self.subquery = subquery def __sqlrepr__(self, db): return "%s (%s)" % (self.op, sqlrepr(self.subquery, db)) def EXISTS(subquery): return Subquery("EXISTS", subquery) def NOTEXISTS(subquery): return Subquery("NOT EXISTS", subquery) def SOME(subquery): return Subquery("SOME", subquery) def ANY(subquery): return Subquery("ANY", subquery) def ALL(subquery): return Subquery("ALL", subquery) ######################################## ## Global initializations ######################################## table = TableSpace() const = ConstantSpace() func = const ######################################## ## Testing ######################################## if __name__ == "__main__": tests = """ >>> AND(table.address.name == "Ian Bicking", table.address.zip > 30000) >>> table.address.name >>> AND(LIKE(table.address.name, "this"), IN(table.address.zip, [100, 200, 300])) >>> Select([table.address.name, table.address.state], where=LIKE(table.address.name, "%ian%")) >>> Select([table.user.name], where=AND(table.user.state == table.states.abbrev)) >>> Insert(table.address, [{"name": "BOB", "address": "3049 N. 18th St."}, {"name": "TIM", "address": "409 S. 10th St."}]) >>> Insert(table.address, [("BOB", "3049 N. 18th St."), ("TIM", "409 S. 10th St.")], template=('name', 'address')) >>> Delete(table.address, where="BOB"==table.address.name) >>> Update(table.address, {"lastModified": const.NOW()}) >>> Replace(table.address, [("BOB", "3049 N. 18th St."), ("TIM", "409 S. 10th St.")], template=('name', 'address')) """ for expr in tests.split('\n'): if not expr.strip(): continue if expr.startswith('>>> '): expr = expr[4:] PKa95ecsqlobject/index.pyfrom types import * import col from converters import sqlrepr class SODatabaseIndex(object): def __init__(self, soClass, name, columns, unique=False): self.soClass = soClass self.name = name self.descriptions = self.convertColumns(columns) self.unique = unique def convertColumns(self, columns): """ Converts all the columns to dictionary descriptors; dereferences string column names. """ new = [] for desc in columns: if not isinstance(desc, dict): desc = {'column': desc} if desc.has_key('expression'): assert not desc.has_key('column'), ( 'You cannot provide both an expression and a column ' '(for %s in index %s in %s)' % (desc, self.name, self.soClass)) assert not desc.has_key('length'), ( 'length does not apply to expressions (for %s in ' 'index %s in %s)' % (desc, self.name, self.soClass)) new.append(desc) continue columnName = desc['column'] if not isinstance(columnName, str): columnName = columnName.name colDict = self.soClass.sqlmeta.columns if not colDict.has_key(columnName): for possible in colDict.values(): if possible.origName == columnName: column = possible break else: # None found raise ValueError, "The column by the name %r was not found in the class %r" % (columnName, self.soClass) else: column = colDict[columnName] desc['column'] = column new.append(desc) return new def getExpression(self, desc, db): if isinstance(desc['expression'], str): return desc['expression'] else: return sqlrepr(desc['expression'], db) def sqliteCreateIndexSQL(self, soClass): if self.unique: uniqueOrIndex = 'UNIQUE INDEX' else: uniqueOrIndex = 'INDEX' spec = [] for desc in self.descriptions: if desc.has_key('expression'): spec.append(self.getExpression(desc, 'sqlite')) else: spec.append(desc['column'].dbName) ret = 'CREATE %s %s_%s ON %s (%s)' % \ (uniqueOrIndex, self.soClass.sqlmeta.table, self.name, self.soClass.sqlmeta.table, ', '.join(spec)) return ret postgresCreateIndexSQL = maxdbCreateIndexSQL = mssqlCreateIndexSQL = sybaseCreateIndexSQL = firebirdCreateIndexSQL = sqliteCreateIndexSQL def mysqlCreateIndexSQL(self, soClass): if self.unique: uniqueOrIndex = 'UNIQUE' else: uniqueOrIndex = 'INDEX' spec = [] for desc in self.descriptions: if desc.has_key('expression'): spec.append(self.getExpression(desc, 'mysql')) elif desc.has_key('length'): spec.append('%s(%d)' % (desc['column'].dbName, desc['length'])) else: spec.append(desc['column'].dbName) return 'ALTER TABLE %s ADD %s %s (%s)' % \ (soClass.sqlmeta.table, uniqueOrIndex, self.name, ', '.join(spec)) class DatabaseIndex(object): """ This takes a variable number of parameters, each of which is a column for indexing. Each column may be a column object or the string name of the column (*not* the database name). You may also use dictionaries, to further customize the indexing of the column. The dictionary may have certain keys: 'column': The column object or string identifier. 'length': MySQL will only index the first N characters if this is given. For other databases this is ignored. 'expression': You can create an index based on an expression, e.g., 'lower(column)'. This can either be a string or a sqlbuilder expression. Further keys may be added to the column specs in the future. The class also take the keyword argument `unique`; if true then a UNIQUE index is created. """ baseClass = SODatabaseIndex def __init__(self, *columns, **kw): kw['columns'] = columns self.kw = kw def setName(self, value): assert self.kw.get('name') is None, "You cannot change a name after it has already been set (from %s to %s)" % (self.kw['name'], value) self.kw['name'] = value def _get_name(self): return self.kw['name'] def _set_name(self, value): self.setName(value) name = property(_get_name, _set_name) def withClass(self, soClass): return self.baseClass(soClass=soClass, **self.kw) def __repr__(self): return '<%s %s %s>' % ( self.__class__.__name__, hex(abs(id(self)))[2:], self.kw) __all__ = ['DatabaseIndex'] PKa951||sqlobject/constraints.py""" Constraints """ True, False = (1==1), (0==1) class BadValue(ValueError): def __init__(self, desc, obj, col, value, *args): self.desc = desc self.col = col # I want these objects to be garbage-collectable, so # I just keep their repr: self.obj = repr(obj) self.value = repr(value) fullDesc = "%s.%s %s (you gave: %s)" \ % (obj, col.name, desc, value) ValueError.__init__(self, fullDesc, *args) def isString(obj, col, value): if type(value) is not type(""): raise BadValue("only allows strings", obj, col, value) def notNull(obj, col, value): if value is None: raise BadValue("is defined NOT NULL", obj, col, value) def isInt(obj, col, value): if type(value) not in (type(1), type(1L)): raise BadValue("only allows integers", obj, col, value) def isFloat(obj, col, value): if type(value) not in (type(1), type(1L), type(1.1)): raise BadValue("only allows floating point numbers", obj, col, value) def isBool(obj, col, value): if type(value) not in (type(True),): raise BadValue("only allows booleans", obj, col, value) class InList: def __init__(self, l): self.list = l def __call__(self, obj, col, value): if value not in self.list: raise BadValue("accepts only values in %s" % repr(self.list), obj, col, value) class MaxLength: def __init__(self, length): self.length = length def __call__(self, obj, col, value): try: length = len(value) except TypeError: raise BadValue("object does not have a length", obj, col, value) if length > self.length: raise BadValue("must be shorter in length than %s" % self.length, obj, col, value) PKa95msqlobject/col.py""" Col -- SQLObject columns Note that each column object is named BlahBlahCol, and these are used in class definitions. But there's also a corresponding SOBlahBlahCol object, which is used in SQLObject *classes*. An explanation: when a SQLObject subclass is created, the metaclass looks through your class definition for any subclasses of Col. It collects them together, and indexes them to do all the database stuff you like, like the magic attributes and whatnot. It then asks the Col object to create an SOCol object (usually a subclass, actually). The SOCol object contains all the interesting logic, as well as a record of the attribute name you used and the class it is bound to (set by the metaclass). So, in summary: Col objects are what you define, but SOCol objects are what gets used. """ import re, time try: import cPickle as pickle except ImportError: import pickle import sqlbuilder # Sadly the name "constraints" conflicts with many of the function # arguments in this module, so we rename it: import constraints as consts from formencode import compound from formencode import validators from classregistry import findClass from converters import array_type, buffer_type from util.backports import count NoDefault = sqlbuilder.NoDefault True, False = 1==1, 0==1 try: import datetime except ImportError: # Python 2.2 datetime_available = False else: datetime_available = True try: from mx import DateTime except ImportError: try: import DateTime # old version of mxDateTime, or Zope's Version if we're running with Zope except ImportError: mxdatetime_available = False else: mxdatetime_available = True else: mxdatetime_available = True DATETIME_IMPLEMENTATION = "datetime" MXDATETIME_IMPLEMENTATION = "mxDateTime" if mxdatetime_available: DateTimeType = type(DateTime.now()) if hasattr(DateTime, "Time"): TimeType = type(DateTime.Time()) else: # Zope TimeType = type(DateTime.DateTime.Time(DateTime.DateTime())) if datetime_available: default_datetime_implementation = DATETIME_IMPLEMENTATION elif mxdatetime_available: default_datetime_implementation = MXDATETIME_IMPLEMENTATION else: default_datetime_implementation = None __all__ = ["datetime_available", "mxdatetime_available", "default_datetime_implementation" ] if datetime_available: __all__.append("DATETIME_IMPLEMENTATION") if mxdatetime_available: __all__.append("MXDATETIME_IMPLEMENTATION") creationOrder = count() class SQLValidator(compound.All): def attemptConvert(self, value, state, validate): if validate is validators.to_python: vlist = list(self.validators[:]) vlist.reverse() elif validate is validators.from_python: vlist = self.validators else: raise RuntimeError for validator in vlist: value = validate(validator, value, state) return value ######################################## ## Columns ######################################## # Col is essentially a column definition, it doesn't have # much logic to it. class SOCol(object): def __init__(self, name, soClass, creationOrder, dbName=None, default=NoDefault, foreignKey=None, alternateID=False, alternateMethodName=None, constraints=None, notNull=NoDefault, notNone=NoDefault, unique=NoDefault, sqlType=None, columnDef=None, validator=None, immutable=False, cascade=None, lazy=False, noCache=False, forceDBName=False, title=None, tags=[], origName=None, extra_vars=None): super(SOCol, self).__init__() # This isn't strictly true, since we *could* use backquotes or # " or something (database-specific) around column names, but # why would anyone *want* to use a name like that? # @@: I suppose we could actually add backquotes to the # dbName if we needed to... if not forceDBName: assert sqlbuilder.sqlIdentifier(name), 'Name must be SQL-safe (letters, numbers, underscores): %s (or use forceDBName=True)' \ % repr(name) assert name != 'id', 'The column name "id" is reserved for SQLObject use (and is implicitly created).' assert name, "You must provide a name for all columns" self.columnDef = columnDef self.creationOrder = creationOrder self.immutable = immutable # cascade can be one of: # None: no constraint is generated # True: a CASCADE constraint is generated # False: a RESTRICT constraint is generated # 'null': a SET NULL trigger is generated if isinstance(cascade, str): assert cascade == 'null', ( "The only string value allowed for cascade is 'null' (you gave: %r)" % cascade) self.cascade = cascade if type(constraints) not in (type([]), type(())): constraints = [constraints] self.constraints = self.autoConstraints() + constraints self.notNone = False if notNull is not NoDefault: self.notNone = notNull assert notNone is NoDefault or \ (not notNone) == (not notNull), \ "The notNull and notNone arguments are aliases, and must not conflict. You gave notNull=%r, notNone=%r" % (notNull, notNone) elif notNone is not NoDefault: self.notNone = notNone if self.notNone: self.constraints = [consts.notNull] + self.constraints self.name = name self.soClass = soClass self._default = default self.customSQLType = sqlType self.foreignKey = foreignKey if self.foreignKey: #assert self.name.upper().endswith('ID'), "All foreign key columns must end with 'ID' (%s)" % repr(self.name) if not self.name.upper().endswith('ID'): self.foreignName = self.name self.name = self.name + "ID" else: self.foreignName = self.name[:-2] else: self.foreignName = None # if they don't give us a specific database name for # the column, we separate the mixedCase into mixed_case # and assume that. if dbName is None: self.dbName = soClass.sqlmeta.style.pythonAttrToDBColumn(self.name) else: self.dbName = dbName # alternateID means that this is a unique column that # can be used to identify rows self.alternateID = alternateID if self.alternateID and alternateMethodName is None: self.alternateMethodName = 'by' + self.name[0].capitalize() + self.name[1:] else: self.alternateMethodName = alternateMethodName if unique is NoDefault: self.unique = alternateID else: self.unique = unique _validators = self.createValidators() if _validators: if validator: _validators.append(validator) self.validator = SQLValidator.join(_validators[0], *_validators[1:]) else: self.validator = validator self.noCache = noCache self.lazy = lazy # this is in case of ForeignKey, where we rename the column # and append an ID self.origName = origName or name self.title = title self.tags = tags if extra_vars: for name, value in extra_vars.items(): setattr(self, name, value) def _set_validator(self, value): self._validator = value if self._validator: self.to_python = self._validator.to_python self.from_python = self._validator.from_python else: self.to_python = None self.from_python = None def _get_validator(self): return self._validator validator = property(_get_validator, _set_validator) def createValidators(self): """Create a list of validators for the column.""" return [] def autoConstraints(self): return [] def _get_default(self): # A default can be a callback or a plain value, # here we resolve the callback if self._default is NoDefault: return NoDefault elif hasattr(self._default, '__sqlrepr__'): return self._default elif callable(self._default): return self._default() else: return self._default default = property(_get_default, None, None) def _get_joinName(self): assert self.name[-2:] == 'ID' return self.name[:-2] joinName = property(_get_joinName, None, None) def __repr__(self): r = '<%s %s' % (self.__class__.__name__, self.name) if self.default is not NoDefault: r += ' default=%s' % repr(self.default) if self.foreignKey: r += ' connected to %s' % self.foreignKey if self.alternateID: r += ' alternate ID' if self.notNone: r += ' not null' return r + '>' def createSQL(self): return ' '.join([self._sqlType() + self._extraSQL()]) def _extraSQL(self): result = [] if self.notNone or self.alternateID: result.append('NOT NULL') if self.unique or self.alternateID: result.append('UNIQUE') return result def _sqlType(self): if self.customSQLType is None: raise ValueError, ("Col %s (%s) cannot be used for automatic " "schema creation (too abstract)" % (self.name, self.__class__)) else: return self.customSQLType def _mysqlType(self): return self._sqlType() def _postgresType(self): return self._sqlType() def _sqliteType(self): # SQLite is naturally typeless, so as a fallback it uses # no type. try: return self._sqlType() except ValueError: return '' def _sybaseType(self): return self._sqlType() def _mssqlType(self): return self._sqlType() def _firebirdType(self): return self._sqlType() def _maxdbType(self): return self._sqlType() def mysqlCreateSQL(self): return ' '.join([self.dbName, self._mysqlType()] + self._extraSQL()) def postgresCreateSQL(self): return ' '.join([self.dbName, self._postgresType()] + self._extraSQL()) def sqliteCreateSQL(self): return ' '.join([self.dbName, self._sqliteType()] + self._extraSQL()) def sybaseCreateSQL(self): return ' '.join([self.dbName, self._sybaseType()] + self._extraSQL()) def mssqlCreateSQL(self): return ' '.join([self.dbName, self._mssqlType()] + self._extraSQL()) def firebirdCreateSQL(self): # Ian Sparks pointed out that fb is picky about the order # of the NOT NULL clause in a create statement. So, we handle # them differently for Enum columns. if not isinstance(self, SOEnumCol): return ' '.join([self.dbName, self._firebirdType()] + self._extraSQL()) else: return ' '.join([self.dbName] + [self._firebirdType()[0]] + self._extraSQL() + [self._firebirdType()[1]]) def maxdbCreateSQL(self): return ' '.join([self.dbName, self._maxdbType()] + self._extraSQL()) def __get__(self, obj, type=None): if obj is None: # class attribute, return the descriptor itself return self if obj.sqlmeta.obsolete: raise '@@: figure out the exception for a delete' if obj.sqlmeta.cacheColumns: columns = obj.sqlmeta._columnCache if columns is None: obj.sqlmeta.loadValues() try: return columns[name] except KeyError: return obj.sqlmeta.loadColumn(self) else: return obj.sqlmeta.loadColumn(self) def __set__(self, obj, value): if self.immutable: raise AttributeError("The column %s.%s is immutable" % (obj.__class__.__name__, self.name)) obj.sqlmeta.setColumn(self, value) def __delete__(self, obj): raise AttributeError("I can't be deleted from %r" % obj) class Col(object): baseClass = SOCol def __init__(self, name=None, **kw): super(Col, self).__init__() self.__dict__['_name'] = name self.__dict__['_kw'] = kw self.__dict__['creationOrder'] = creationOrder.next() self.__dict__['_extra_vars'] = {} def _set_name(self, value): assert self._name is None or self._name == value, ( "You cannot change a name after it has already been set " "(from %s to %s)" % (self.name, value)) self.__dict__['_name'] = value def _get_name(self): return self._name name = property(_get_name, _set_name) def withClass(self, soClass): return self.baseClass(soClass=soClass, name=self._name, creationOrder=self.creationOrder, columnDef=self, extra_vars=self._extra_vars, **self._kw) def __setattr__(self, var, value): if var == 'name': super(Col, self).__setattr__(var, value) return self._extra_vars[var] = value def __repr__(self): return '<%s %s %s>' % ( self.__class__.__name__, hex(abs(id(self)))[2:], self._name or '(unnamed)') class SOStringLikeCol(SOCol): """A common ancestor for SOStringCol and SOUnicodeCol""" def __init__(self, **kw): self.length = popKey(kw, 'length') self.varchar = popKey(kw, 'varchar', 'auto') self.char_binary = popKey(kw, 'char_binary', None) # A hack for MySQL if not self.length: assert self.varchar == 'auto' or not self.varchar, \ "Without a length strings are treated as TEXT, not varchar" self.varchar = False elif self.varchar == 'auto': self.varchar = True super(SOStringLikeCol, self).__init__(**kw) def autoConstraints(self): constraints = [consts.isString] if self.length is not None: constraints += [consts.MaxLength(self.length)] return constraints def _sqlType(self): if self.customSQLType is not None: return self.customSQLType if not self.length: return 'TEXT' elif self.varchar: return 'VARCHAR(%i)' % self.length else: return 'CHAR(%i)' % self.length def _check_case_sensitive(self, db): if self.char_binary: raise ValueError, "%s does not support binary character columns" % db def _mysqlType(self): type = self._sqlType() if self.char_binary: type += " BINARY" return type def _postgresType(self): self._check_case_sensitive("PostgreSQL") return super(SOStringLikeCol, self)._postgresType() def _sqliteType(self): self._check_case_sensitive("SQLite") return super(SOStringLikeCol, self)._sqliteType() def _sybaseType(self): self._check_case_sensitive("SYBASE") type = self._sqlType() if not self.notNone and not self.alternateID: type += ' NULL' return type def _mssqlType(self): if not self.length: type = 'varchar(4000)' elif self.varchar: type = 'VARCHAR(%i)' % self.length else: type = 'CHAR(%i)' % self.length if not self.notNone and not self.alternateID: type += ' NULL' return type def _firebirdType(self): self._check_case_sensitive("FireBird") if not self.length: return 'BLOB SUB_TYPE TEXT' else: return self._sqlType() def _maxdbType(self): self._check_case_sensitive("SAP DB/MaxDB") if not self.length: return 'LONG ASCII' else: return self._sqlType() class StringValidator(validators.Validator): def to_python(self, value, state): if value is None: return None if isinstance(value, unicode): return value.encode("ascii") return value def from_python(self, value, state): if value is None: return None if isinstance(value, str): return value if isinstance(value, unicode): return value.encode("ascii") return value class SOStringCol(SOStringLikeCol): def createValidators(self): return [StringValidator()] + \ super(SOStringCol, self).createValidators() class StringCol(Col): baseClass = SOStringCol class UnicodeStringValidator(validators.Validator): def to_python(self, value, state): if value is None: return None if isinstance(value, unicode): return value if isinstance(value, array_type): # MySQL return unicode(value.tostring(), self.db_encoding) return unicode(value, self.db_encoding) def from_python(self, value, state): if value is None: return None if isinstance(value, str): return value return value.encode(self.db_encoding) class SOUnicodeCol(SOStringLikeCol): def __init__(self, **kw): self.dbEncoding = popKey(kw, 'dbEncoding', 'UTF-8') super(SOUnicodeCol, self).__init__(**kw) def createValidators(self): return [UnicodeStringValidator(db_encoding=self.dbEncoding)] + \ super(SOUnicodeCol, self).createValidators() class UnicodeCol(Col): baseClass = SOUnicodeCol class IntValidator(validators.Validator): def to_python(self, value, state): if value is None: return None if isinstance(value, (int, long, sqlbuilder.SQLExpression)): return value try: try: return int(value) except OverflowError: # for Python 2.2 return long(value) except: raise validators.Invalid("expected an int in the IntCol '%s', got %s %r instead" % \ (self.name, type(value), value), value, state) def from_python(self, value, state): if value is None: return None if not isinstance(value, (int, long, sqlbuilder.SQLExpression)): raise validators.Invalid("expected an int in the IntCol '%s', got %s %r instead" % \ (self.name, type(value), value), value, state) return value class SOIntCol(SOCol): # 3-03 @@: support precision, maybe max and min directly def autoConstraints(self): return [consts.isInt] def createValidators(self): return [IntValidator(name=self.name)] + \ super(SOIntCol, self).createValidators() def _sqlType(self): return 'INT' class IntCol(Col): baseClass = SOIntCol class BoolValidator(validators.Validator): def to_python(self, value, state): if value is None: return None elif not value: return sqlbuilder.FALSE else: return sqlbuilder.TRUE def from_python(self, value, state): if value is None: return None elif value: return sqlbuilder.TRUE else: return sqlbuilder.FALSE class SOBoolCol(SOCol): def autoConstraints(self): return [consts.isBool] def createValidators(self): return [BoolValidator()] + \ super(SOBoolCol, self).createValidators() def _postgresType(self): return 'BOOL' def _mysqlType(self): return "TINYINT" def _sybaseType(self): return "BIT" def _mssqlType(self): return "BIT" def _firebirdType(self): return 'INT' def _maxdbType(self): return "BOOLEAN" def _sqliteType(self): return "TINYINT" class BoolCol(Col): baseClass = SOBoolCol class FloatValidator(validators.Validator): def to_python(self, value, state): if value is None: return None if isinstance(value, (int, long, float, sqlbuilder.SQLExpression)): return value try: return float(value) except: raise validators.Invalid("expected a float in the FloatCol '%s', got %s %r instead" % \ (self.name, type(value), value), value, state) def from_python(self, value, state): if value is None: return None if not isinstance(value, (int, long, float, sqlbuilder.SQLExpression)): raise validators.Invalid("expected a float in the FloatCol '%s', got %s %r instead" % \ (self.name, type(value), value), value, state) return value class SOFloatCol(SOCol): # 3-03 @@: support precision (e.g., DECIMAL) def autoConstraints(self): return [consts.isFloat] def createValidators(self): return [FloatValidator(name=self.name)] + \ super(SOFloatCol, self).createValidators() def _sqlType(self): return 'FLOAT' def _mysqlType(self): return "DOUBLE PRECISION" class FloatCol(Col): baseClass = SOFloatCol class SOKeyCol(SOCol): # 3-03 @@: this should have a simplified constructor # Should provide foreign key information for other DBs. def _mysqlType(self): return 'INT' def _sqliteType(self): return 'INT' def _postgresType(self): return 'INT' def _sybaseType(self): return 'NUMERIC(18,0) NULL' def _mssqlType(self): return 'INT NULL' def _firebirdType(self): return 'INT' def _maxdbType(self): return 'INT' class KeyCol(Col): baseClass = SOKeyCol class SOForeignKey(SOKeyCol): def __init__(self, **kw): foreignKey = kw['foreignKey'] style = kw['soClass'].sqlmeta.style if not kw.get('name'): kw['name'] = style.instanceAttrToIDAttr(style.pythonClassToAttr(foreignKey)) else: kw['origName'] = kw['name'] if not kw['name'].upper().endswith('ID'): kw['name'] = style.instanceAttrToIDAttr(kw['name']) super(SOForeignKey, self).__init__(**kw) def sqliteCreateSQL(self): sql = SOKeyCol.sqliteCreateSQL(self) other = findClass(self.foreignKey) tName = other.sqlmeta.table idName = other.sqlmeta.idName if self.cascade is not None: if self.cascade == 'null': action = 'ON DELETE SET NULL' elif self.cascade: action = 'ON DELETE CASCADE' else: action = 'ON DELETE RESTRICT' else: action = '' constraint = ('CONSTRAINT %(colName)s_exists ' #'FOREIGN KEY(%(colName)s) ' 'REFERENCES %(tName)s(%(idName)s) ' '%(action)s' % {'tName': tName, 'colName': self.dbName, 'idName': idName, 'action': action}) sql = ' '.join([sql, constraint]) return sql def postgresCreateSQL(self): sql = SOKeyCol.postgresCreateSQL(self) other = findClass(self.foreignKey, self.soClass.sqlmeta.registry) tName = other.sqlmeta.table idName = other.sqlmeta.idName if self.cascade is not None: if self.cascade == 'null': action = 'ON DELETE SET NULL' elif self.cascade: action = 'ON DELETE CASCADE' else: action = 'ON DELETE RESTRICT' else: action = '' constraint = ('CONSTRAINT %(colName)s_exists ' 'FOREIGN KEY (%(colName)s) ' 'REFERENCES %(tName)s (%(idName)s) ' '%(action)s' % {'tName': tName, 'colName': self.dbName, 'idName': idName, 'action': action}) sql = ', '.join([sql, constraint]) return sql def postgresCreateColumnSQL(self): sql = SOKeyCol.postgresCreateSQL(self) other = findClass(self.foreignKey, self.soClass.sqlmeta.registry) tName = other.sqlmeta.table idName = other.sqlmeta.idName if self.cascade is not None: if self.cascade == 'null': action = 'ON DELETE SET NULL' elif self.cascade: action = 'ON DELETE CASCADE' else: action = 'ON DELETE RESTRICT' else: action = '' constraint = ('CONSTRAINT %(colName)s_exists ' 'REFERENCES %(tName)s (%(idName)s) ' '%(action)s' % {'tName': tName, 'colName': self.dbName, 'idName': idName, 'action': action}) sql = ' '.join([sql, constraint]) return sql def sybaseCreateSQL(self): sql = SOKeyCol.sybaseCreateSQL(self) other = findClass(self.foreignKey) tName = other.sqlmeta.table idName = other.sqlmeta.idName reference = ('REFERENCES %(tName)s(%(idName)s) ' % {'tName':tName, 'idName':idName}) sql = ' '.join([sql, reference]) return sql def mssqlCreateSQL(self): sql = SOKeyCol.mssqlCreateSQL(self) other = findClass(self.foreignKey) tName = other.sqlmeta.table idName = other.sqlmeta.idName reference = ('REFERENCES %(tName)s(%(idName)s) ' % {'tName':tName, 'idName':idName}) sql = ' '.join([sql, reference]) return sql def maxdbCreateSQL(self): other = findClass(self.foreignKey) fidName = self.dbName #I assume that foreign key name is identical to the id of the reference table sql = ' '.join([fidName, self._maxdbType()]) tName = other.sqlmeta.table idName = other.sqlmeta.idName sql=sql + ',' + '\n' sql=sql + 'FOREIGN KEY (%s) REFERENCES %s(%s)'%(fidName,tName,idName) return sql class ForeignKey(KeyCol): baseClass = SOForeignKey def __init__(self, foreignKey=None, **kw): super(ForeignKey, self).__init__(foreignKey=foreignKey, **kw) class SOEnumCol(SOCol): def __init__(self, **kw): self.enumValues = popKey(kw, 'enumValues', None) assert self.enumValues is not None, \ 'You must provide an enumValues keyword argument' super(SOEnumCol, self).__init__(**kw) def autoConstraints(self): return [consts.isString, consts.InList(self.enumValues)] def createValidators(self): return [EnumValidator(name = self.name, enumValues = self.enumValues)] + \ super(SOEnumCol, self).createValidators() def _mysqlType(self): return "ENUM(%s)" % ', '.join([sqlbuilder.sqlrepr(v, 'mysql') for v in self.enumValues]) def _postgresType(self): length = max(map(self._getlength, self.enumValues)) enumValues = ', '.join([sqlbuilder.sqlrepr(v, 'postgres') for v in self.enumValues]) checkConstraint = "CHECK (%s in (%s))" % (self.dbName, enumValues) return "VARCHAR(%i) %s" % (length, checkConstraint) def _sqliteType(self): return self._postgresType() def _sybaseType(self): return self._postgresType() def _mssqlType(self): return self._postgresType() def _firebirdType(self): length = max(map(self._getlength, self.enumValues)) enumValues = ', '.join([sqlbuilder.sqlrepr(v, 'firebird') for v in self.enumValues]) checkConstraint = "CHECK (%s in (%s))" % (self.dbName, enumValues) #NB. Return a tuple, not a string here return "VARCHAR(%i)" % (length), checkConstraint def _maxdbType(self): raise "Enum type is not supported" def _getlength(self, obj): """ None counts as 0; everything else uses len() """ if obj is None: return 0 else: return len(obj) class EnumValidator(validators.Validator): def to_python(self, value, state): if value in self.enumValues: return value else: raise validators.Invalid("expected a member of %r in the EnumCol '%s', got %r instead" % \ (self.enumValues, self.name, value), value, state) def from_python(self, value, state): return self.to_python(value, state) class EnumCol(Col): baseClass = SOEnumCol if datetime_available: class DateTimeValidator(validators.DateValidator): def to_python(self, value, state): if value is None: return None if isinstance(value, (datetime.datetime, datetime.date, datetime.time, sqlbuilder.SQLExpression)): return value if mxdatetime_available: if isinstance(value, DateTimeType): # convert mxDateTime instance to datetime if (self.format.find("%H") >= 0) or (self.format.find("%T")) >= 0: return datetime.datetime(value.year, value.month, value.day, value.hour, value.minute, int(value.second)) else: return datetime.date(value.year, value.month, value.day) elif isinstance(value, TimeType): # convert mxTime instance to time if self.format.find("%d") >= 0: return datetime.timedelta(seconds=value.seconds) else: return datetime.time(value.hour, value.minute, int(value.second)) try: stime = time.strptime(value, self.format) except: raise validators.Invalid("expected an date/time string of the '%s' format in the DateTimeCol '%s', got %s %r instead" % \ (self.format, self.name, type(value), value), value, state) return datetime.datetime(*stime[:6]) def from_python(self, value, state): if value is None: return None if isinstance(value, (datetime.datetime, datetime.date, datetime.time, sqlbuilder.SQLExpression)): return value if hasattr(value, "strftime"): return value.strftime(self.format) raise validators.Invalid("expected a datetime in the DateTimeCol '%s', got %s %r instead" % \ (self.name, type(value), value), value, state) if mxdatetime_available: class MXDateTimeValidator(validators.DateValidator): def to_python(self, value, state): if value is None: return None if isinstance(value, (DateTimeType, TimeType, sqlbuilder.SQLExpression)): return value if datetime_available: # convert datetime instance to mxDateTime if isinstance(value, datetime.datetime): return DateTime.DateTime(value.year, value.month, value.day, value.hour, value.minute, value.second) elif isinstance(value, datetime.date): return DateTime.Date(value.year, value.month, value.day) elif isinstance(value, datetime.time): return DateTime.Time(value.hour, value.minute, value.second) try: stime = time.strptime(value, self.format) except: raise validators.Invalid("expected an date/time string of the '%s' format in the DateTimeCol '%s', got %s %r instead" % \ (self.format, self.name, type(value), value), value, state) return DateTime.mktime(stime) def from_python(self, value, state): if value is None: return None if isinstance(value, (DateTimeType, TimeType, sqlbuilder.SQLExpression)): return value if hasattr(value, "strftime"): return value.strftime(self.format) raise validators.Invalid("expected a mxDateTime in the DateTimeCol '%s', got %s %r instead" % \ (self.name, type(value), value), value, state) class SODateTimeCol(SOCol): datetimeFormat = '%Y-%m-%d %H:%M:%S' def __init__(self, **kw): datetimeFormat = popKey(kw, 'datetimeFormat') if datetimeFormat: self.datetimeFormat = datetimeFormat super(SODateTimeCol, self).__init__(**kw) def createValidators(self): _validators = super(SODateTimeCol, self).createValidators() if default_datetime_implementation == DATETIME_IMPLEMENTATION: validatorClass = DateTimeValidator elif default_datetime_implementation == MXDATETIME_IMPLEMENTATION: validatorClass = MXDateTimeValidator if default_datetime_implementation: _validators.insert(0, validatorClass(name=self.name, format=self.datetimeFormat)) return _validators def _mysqlType(self): return 'DATETIME' def _postgresType(self): return 'TIMESTAMP' def _sybaseType(self): return 'DATETIME' def _mssqlType(self): return 'DATETIME' def _sqliteType(self): return 'TIMESTAMP' def _firebirdType(self): return 'TIMESTAMP' def _maxdbType(self): return 'TIMESTAMP' class DateTimeCol(Col): baseClass = SODateTimeCol def now(): if default_datetime_implementation == DATETIME_IMPLEMENTATION: return datetime.datetime.now() elif default_datetime_implementation == MXDATETIME_IMPLEMENTATION: return DateTime.now() else: assert 0, ("No datetime implementation available " "(DATETIME_IMPLEMENTATION=%r)" % DATETIME_IMPLEMENTATION) now = staticmethod(now) if datetime_available: class DateValidator(DateTimeValidator): def to_python(self, value, state): if isinstance(value, datetime.date): return value value = super(DateValidator, self).to_python(value, state) if isinstance(value, datetime.datetime): value = value.date() return value from_python = to_python class SODateCol(SOCol): dateFormat = '%Y-%m-%d' def __init__(self, **kw): dateFormat = popKey(kw, 'dateFormat') if dateFormat: self.dateFormat = dateFormat super(SODateCol, self).__init__(**kw) def createValidators(self): """Create a validator for the column. Can be overriden in descendants.""" _validators = super(SODateCol, self).createValidators() if default_datetime_implementation == DATETIME_IMPLEMENTATION: validatorClass = DateValidator elif default_datetime_implementation == MXDATETIME_IMPLEMENTATION: validatorClass = MXDateTimeValidator if default_datetime_implementation: _validators.insert(0, validatorClass(name=self.name, format=self.dateFormat)) return _validators def _mysqlType(self): return 'DATE' def _postgresType(self): return 'DATE' def _sybaseType(self): return self._postgresType() def _mssqlType(self): """ SQL Server doesn't have a DATE data type, to emulate we use a vc(10) """ return 'VARCHAR(10)' def _firebirdType(self): return 'DATE' def _maxdbType(self): return 'DATE' def _sqliteType(self): return 'DATE' class DateCol(Col): baseClass = SODateCol if datetime_available: class TimeValidator(DateTimeValidator): def to_python(self, value, state): if isinstance(value, datetime.time): return value value = super(TimeValidator, self).to_python(value, state) if isinstance(value, datetime.datetime): value = value.time() return value class SOTimeCol(SOCol): timeFormat = '%H:%M:%S' def __init__(self, **kw): timeFormat = popKey(kw, 'timeFormat') if timeFormat: self.timeFormat = timeFormat super(SOTimeCol, self).__init__(**kw) def createValidators(self): _validators = super(SOTimeCol, self).createValidators() if default_datetime_implementation == DATETIME_IMPLEMENTATION: validatorClass = TimeValidator elif default_datetime_implementation == MXDATETIME_IMPLEMENTATION: validatorClass = MXDateTimeValidator if default_datetime_implementation: _validators.insert(0, validatorClass(name=self.name, format=self.timeFormat)) return _validators def _mysqlType(self): return 'TIME' def _postgresType(self): return 'TIME' def _sybaseType(self): return 'TIME' def _sqliteType(self): return 'TIME' def _firebirdType(self): return 'TIME' def _maxdbType(self): return 'TIME' class TimeCol(Col): baseClass = SOTimeCol class SODecimalCol(SOCol): def __init__(self, **kw): self.size = popKey(kw, 'size', NoDefault) assert self.size is not NoDefault, \ "You must give a size argument" self.precision = popKey(kw, 'precision', NoDefault) assert self.precision is not NoDefault, \ "You must give a precision argument" super(SODecimalCol, self).__init__(**kw) def _sqlType(self): return 'DECIMAL(%i, %i)' % (self.size, self.precision) class DecimalCol(Col): baseClass = SODecimalCol class SOCurrencyCol(SODecimalCol): def __init__(self, **kw): pushKey(kw, 'size', 10) pushKey(kw, 'precision', 2) super(SOCurrencyCol, self).__init__(**kw) class CurrencyCol(DecimalCol): baseClass = SOCurrencyCol class BinaryValidator(validators.Validator): """ Validator for binary types. We're assuming that the per-database modules provide some form of wrapper type for binary conversion. """ _cachedValue = None def to_python(self, value, state): if value is None: return None if isinstance(value, str): module = state.soObject._connection.module if module.__name__ in ("sqlite", "pysqlite2.dbapi2"): value = module.decode(value) return value if isinstance(value, (buffer_type, state.soObject._connection._binaryType)): cachedValue = self._cachedValue if cachedValue and cachedValue[1] == value: return cachedValue[0] if isinstance(value, array_type): # MySQL return value.tostring() return str(value) # buffer => string raise validators.Invalid("expected a string in the BLOBCol '%s', got %s %r instead" % \ (self.name, type(value), value), value, state) def from_python(self, value, state): if value is None: return None binary = state.soObject._connection.createBinary(value) self._cachedValue = (value, binary) return binary class SOBLOBCol(SOStringCol): def createValidators(self): return [BinaryValidator(name=self.name)] + \ super(SOBLOBCol, self).createValidators() def _mysqlType(self): length = self.length varchar = self.varchar if length >= 2**24: return varchar and "LONGTEXT" or "LONGBLOB" if length >= 2**16: return varchar and "MEDIUMTEXT" or "MEDIUMBLOB" if length >= 2**8: return varchar and "TEXT" or "BLOB" return varchar and "TINYTEXT" or "TINYBLOB" def _postgresType(self): return 'BYTEA' def _mssqlType(self): return "IMAGE" class BLOBCol(StringCol): baseClass = SOBLOBCol class PickleValidator(BinaryValidator): """ Validator for pickle types. A pickle type is simply a binary type with hidden pickling, so that we can simply store any kind of stuff in a particular column. The support for this relies directly on the support for binary for your database. """ def to_python(self, value, state): if value is None: return None if isinstance(value, unicode): value = value.encode("ascii") if isinstance(value, str): return pickle.loads(value) raise validators.Invalid("expected a pickle string in the PickleCol '%s', got %s %r instead" % \ (self.name, type(value), value), value, state) def from_python(self, value, state): if value is None: return None return pickle.dumps(value) class SOPickleCol(SOBLOBCol): def __init__(self, **kw): self.pickleProtocol = popKey(kw, 'pickleProtocol', 1) super(SOPickleCol, self).__init__(**kw) def createValidators(self): return [PickleValidator( name=self.name, pickleProtocol=self.pickleProtocol)] + \ super(SOPickleCol, self).createValidators() class PickleCol(BLOBCol): baseClass = SOPickleCol def popKey(kw, name, default=None): if not kw.has_key(name): return default value = kw[name] del kw[name] return value def pushKey(kw, name, value): if not kw.has_key(name): kw[name] = value all = [] for key, value in globals().items(): if isinstance(value, type) and (issubclass(value, Col) or issubclass(value, SOCol)): all.append(key) __all__.extend(all) del all PKa95o·sqlobject/styles.pyimport re __all__ = ["Style", "MixedCaseUnderscoreStyle", "DefaultStyle", "MixedCaseStyle"] True, False = 1==1, 0==1 class Style(object): """ The base Style class, and also the simplest implementation. No translation occurs -- column names and attribute names match, as do class names and table names (when using auto class or schema generation). """ def __init__(self, pythonAttrToDBColumn=None, dbColumnToPythonAttr=None, pythonClassToDBTable=None, dbTableToPythonClass=None, idForTable=None, longID=False): if pythonAttrToDBColumn: self.pythonAttrToDBColumn = lambda a, s=self: pythonAttrToDBColumn(s, a) if dbColumnToPythonAttr: self.dbColumnToPythonAttr = lambda a, s=self: dbColumnToPythonAttr(s, a) if pythonClassToDBTable: self.pythonClassToDBTable = lambda a, s=self: pythonClassToDBTable(s, a) if dbTableToPythonClass: self.dbTableToPythonClass = lambda a, s=self: dbTableToPythonClass(s, a) if idForTable: self.idForTable = lambda a, s=self: idForTable(s, a) self.longID = longID def pythonAttrToDBColumn(self, attr): return attr def dbColumnToPythonAttr(self, col): return col def pythonClassToDBTable(self, className): return className def dbTableToPythonClass(self, table): return table def idForTable(self, table): if self.longID: return self.tableReference(table) else: return 'id' def pythonClassToAttr(self, className): return lowerword(className) def instanceAttrToIDAttr(self, attr): # @@: Right now, because of how names are created for foreign # keys, you can't really change this style. return attr + "ID" def tableReference(self, table): return table + "_id" class MixedCaseUnderscoreStyle(Style): """ This is the default style. Python attributes use mixedCase, while database columns use underscore_separated. """ def pythonAttrToDBColumn(self, attr): return mixedToUnder(attr) def dbColumnToPythonAttr(self, col): return underToMixed(col) def pythonClassToDBTable(self, className): return className[0].lower() \ + mixedToUnder(className[1:]) def dbTableToPythonClass(self, table): return table[0].upper() \ + underToMixed(table[1:]) def pythonClassToDBTableReference(self, className): return self.tableReference(self.pythonClassToDBTable(className)) def tableReference(self, table): return table + "_id" DefaultStyle = MixedCaseUnderscoreStyle class MixedCaseStyle(Style): """ This style leaves columns as mixed-case, and uses long ID names (like ProductID instead of simply id). """ def pythonAttrToDBColumn(self, attr): return capword(attr) def dbColumnToPythonAttr(self, col): return lowerword(col) def dbTableToPythonClass(self, table): return capword(table) def tableReference(self, table): return table + "ID" defaultStyle = DefaultStyle() def getStyle(soClass, dbConnection=None): if dbConnection is None: if hasattr(soClass, '_connection'): dbConnection = soClass._connection if hasattr(soClass.sqlmeta, 'style') and soClass.sqlmeta.style: return soClass.sqlmeta.style elif dbConnection and dbConnection.style: return dbConnection.style else: return defaultStyle ############################################################ ## Text utilities ############################################################ _mixedToUnderRE = re.compile(r'[A-Z]+') def mixedToUnder(s): if s.endswith('ID'): return mixedToUnder(s[:-2] + "_id") trans = _mixedToUnderRE.sub(mixedToUnderSub, s) if trans.startswith('_'): trans = trans[1:] return trans def mixedToUnderSub(match): m = match.group(0).lower() if len(m) > 1: return '_%s_%s' % (m[:-1], m[-1]) else: return '_%s' % m def capword(s): return s[0].upper() + s[1:] def lowerword(s): return s[0].lower() + s[1:] _underToMixedRE = re.compile('_.') def underToMixed(name): if name.endswith('_id'): return underToMixed(name[:-3] + "ID") return _underToMixedRE.sub(lambda m: m.group(0)[1].upper(), name) PKa95N}c}**sqlobject/joins.pyimport sqlbuilder NoDefault = sqlbuilder.NoDefault import styles import classregistry from col import popKey __all__ = ['MultipleJoin', 'SQLMultipleJoin', 'RelatedJoin', 'SQLRelatedJoin', 'SingleJoin'] def getID(obj): try: return obj.id except AttributeError: return int(obj) class Join(object): def __init__(self, otherClass=None, **kw): kw['otherClass'] = otherClass self.kw = kw if self.kw.has_key('joinMethodName'): self._joinMethodName = popKey(self.kw, 'joinMethodName') else: self._joinMethodName = None def _set_joinMethodName(self, value): assert self._joinMethodName == value or self._joinMethodName is None, "You have already given an explicit joinMethodName (%s), and you are now setting it to %s" % (self._joinMethodName, value) self._joinMethodName = value def _get_joinMethodName(self): return self._joinMethodName joinMethodName = property(_get_joinMethodName, _set_joinMethodName) name = joinMethodName def withClass(self, soClass): if self.kw.has_key('joinMethodName'): self._joinMethodName = self.kw['joinMethodName'] del self.kw['joinMethodName'] return self.baseClass(soClass=soClass, joinDef=self, joinMethodName=self._joinMethodName, **self.kw) # A join is separate from a foreign key, i.e., it is # many-to-many, or one-to-many where the *other* class # has the foreign key. class SOJoin(object): def __init__(self, soClass=None, otherClass=None, joinColumn=None, joinMethodName=None, orderBy=NoDefault, joinDef=None): self.soClass = soClass self.joinDef = joinDef self.otherClassName = otherClass classregistry.registry(soClass.sqlmeta.registry).addClassCallback( otherClass, self._setOtherClass) self.joinColumn = joinColumn self.joinMethodName = joinMethodName self.orderBy = orderBy if not self.joinColumn: # Here we set up the basic join, which is # one-to-many, where the other class points to # us. self.joinColumn = styles.getStyle( self.soClass).tableReference(self.soClass.sqlmeta.table) def _setOtherClass(self, cls): self.otherClass = cls def hasIntermediateTable(self): return False def _applyOrderBy(self, results, defaultSortClass): if self.orderBy is NoDefault: self.orderBy = defaultSortClass.sqlmeta.defaultOrder if self.orderBy is not None: results.sort(sorter(self.orderBy)) return results def sorter(orderBy): if isinstance(orderBy, tuple) or isinstance(orderBy, list): if len(orderBy) == 1: orderBy = orderBy[0] else: fhead = sorter(orderBy[0]) frest = sorter(orderBy[1:]) return lambda a, b, fhead=fhead, frest=frest: fhead(a, b) or frest(a, b) if isinstance(orderBy, sqlbuilder.DESC) \ and isinstance(orderBy.expr, sqlbuilder.SQLObjectField): orderBy = '-' + orderBy.expr.original elif isinstance(orderBy, sqlbuilder.SQLObjectField): orderBy = orderBy.original # @@: but we don't handle more complex expressions for orderings if orderBy.startswith('-'): orderBy = orderBy[1:] reverse = True else: reverse = False def cmper(a, b, attr=orderBy, rev=reverse): a = getattr(a, attr) b = getattr(b, attr) if rev: a, b = b, a if a is None: if b is None: return 0 return -1 if b is None: return 1 return cmp(a, b) return cmper # This is a one-to-many class SOMultipleJoin(SOJoin): def __init__(self, addRemoveName=None, **kw): # addRemovePrefix is something like @@ SOJoin.__init__(self, **kw) # Here we generate the method names if not self.joinMethodName: name = self.otherClassName[0].lower() + self.otherClassName[1:] if name.endswith('s'): name = name + "es" else: name = name + "s" self.joinMethodName = name if not addRemoveName: self.addRemoveName = capitalize(self.otherClassName) else: self.addRemoveName = addRemoveName def performJoin(self, inst): ids = inst._connection._SO_selectJoin( self.otherClass, self.joinColumn, inst.id) if inst.sqlmeta._perConnection: conn = inst._connection else: conn = None return self._applyOrderBy([self.otherClass.get(id, conn) for (id,) in ids if id is not None], self.otherClass) class MultipleJoin(Join): baseClass = SOMultipleJoin class SOSQLMultipleJoin(SOMultipleJoin): def performJoin(self, inst): if inst.sqlmeta._perConnection: conn = inst._connection else: conn = None results = self.otherClass.select(getattr(self.otherClass.q, self.soClass.sqlmeta.style.dbColumnToPythonAttr(self.joinColumn)) == inst.id, connection=conn) if self.orderBy is NoDefault: self.orderBy = self.otherClass.sqlmeta.defaultOrder return results.orderBy(self.orderBy) class SQLMultipleJoin(Join): baseClass = SOSQLMultipleJoin # This is a many-to-many join, with an intermediary table class SORelatedJoin(SOMultipleJoin): def __init__(self, otherColumn=None, intermediateTable=None, createRelatedTable=True, **kw): self.intermediateTable = intermediateTable self.otherColumn = otherColumn self.createRelatedTable = createRelatedTable SOMultipleJoin.__init__(self, **kw) classregistry.registry( self.soClass.sqlmeta.registry).addClassCallback( self.otherClassName, self._setOtherRelatedClass) def _setOtherRelatedClass(self, otherClass): if not self.intermediateTable: names = [self.soClass.sqlmeta.table, otherClass.sqlmeta.table] names.sort() self.intermediateTable = '%s_%s' % (names[0], names[1]) if not self.otherColumn: self.otherColumn = self.soClass.sqlmeta.style.tableReference( otherClass.sqlmeta.table) def hasIntermediateTable(self): return True def performJoin(self, inst): ids = inst._connection._SO_intermediateJoin( self.intermediateTable, self.otherColumn, self.joinColumn, inst.id) if inst.sqlmeta._perConnection: conn = inst._connection else: conn = None return self._applyOrderBy([self.otherClass.get(id, conn) for (id,) in ids if id is not None], self.otherClass) def remove(self, inst, other): inst._connection._SO_intermediateDelete( self.intermediateTable, self.joinColumn, getID(inst), self.otherColumn, getID(other)) def add(self, inst, other): inst._connection._SO_intermediateInsert( self.intermediateTable, self.joinColumn, getID(inst), self.otherColumn, getID(other)) class RelatedJoin(MultipleJoin): baseClass = SORelatedJoin # helper classes to SQLRelatedJoin class OtherTableToJoin(sqlbuilder.SQLExpression): def __init__(self, otherTable, otherIdName, interTable, joinColumn): self.otherTable = otherTable self.otherIdName = otherIdName self.interTable = interTable self.joinColumn = joinColumn def __sqlrepr__(self, db): return '%s.%s = %s.%s' % (self.otherTable, self.otherIdName, self.interTable, self.joinColumn) class JoinToTable(sqlbuilder.SQLExpression): def __init__(self, table, idName, interTable, joinColumn): self.table = table self.idName = idName self.interTable = interTable self.joinColumn = joinColumn def __sqlrepr__(self, db): return '%s.%s = %s.%s' % (self.interTable, self.joinColumn, self.table, self.idName) class TableToId(sqlbuilder.SQLExpression): def __init__(self, table, idName, idValue): self.table = table self.idName = idName self.idValue = idValue def __sqlrepr__(self, db): return '%s.%s = %s' % (self.table, self.idName, self.idValue) class SOSQLRelatedJoin(SORelatedJoin): def performJoin(self, inst): results = self.otherClass.select(sqlbuilder.AND( OtherTableToJoin( self.otherClass.sqlmeta.table, self.otherClass.sqlmeta.idName, self.intermediateTable, self.otherColumn ), JoinToTable( self.soClass.sqlmeta.table, self.soClass.sqlmeta.idName, self.intermediateTable, self.joinColumn ), TableToId(self.soClass.sqlmeta.table, self.soClass.sqlmeta.idName, inst.id), ), clauseTables=(self.soClass.sqlmeta.table, self.otherClass.sqlmeta.table, self.intermediateTable)) if self.orderBy is NoDefault: self.orderBy = self.otherClass.sqlmeta.defaultOrder return results.orderBy(self.orderBy) class SQLRelatedJoin(RelatedJoin): baseClass = SOSQLRelatedJoin def capitalize(name): return name[0].capitalize() + name[1:] class SOSingleJoin(SOMultipleJoin): def __init__(self, **kw): self.makeDefault = popKey(kw, 'makeDefault', False) SOMultipleJoin.__init__(self, **kw) def performJoin(self, inst): if inst.sqlmeta._perConnection: conn = inst._connection else: conn = None pythonColumn = self.soClass.sqlmeta.style.dbColumnToPythonAttr(self.joinColumn) results = self.otherClass.select( getattr(self.otherClass.q, pythonColumn) == inst.id, connection=conn ) if results.count() == 0: if not self.makeDefault: return None else: kw = {pythonColumn[:-2]: inst} # skipping the ID (from foreignkeyID) return self.otherClass(**kw) # instanciating the otherClass with all # values to their defaults, except the foreign key # TODO I don't think this is the best way to know the column as foreignKey # reather than foreignKeyID, but I don't found a sqlmeta.style function # to do the work, if there isn't such function, I must create it. else: return results[0] class SingleJoin(Join): baseClass = SOSingleJoin PKa95TX[nnsqlobject/declarative.py""" Declarative objects. Declarative objects have a simple protocol: you can use classes in lieu of instances and they are equivalent, and any keyword arguments you give to the constructor will override those instance variables. (So if a class is received, we'll simply instantiate an instance with no arguments). You can provide a variable __unpackargs__ (a list of strings), and if the constructor is called with non-keyword arguments they will be interpreted as the given keyword arguments. If __unpackargs__ is ('*', name), then all the arguments will be put in a variable by that name. You can define a __classinit__(cls, new_attrs) method, which will be called when the class is created (including subclasses). Note: you can't use super() in __classinit__ because the class isn't bound to a name. As an analog to __classinit__, Declarative adds __instanceinit__ which is called with the same argument (new_attrs). This is like __init__, but after __unpackargs__ and other factors have been taken into account. If __mutableattributes__ is defined as a sequence of strings, these attributes will not be shared between superclasses and their subclasses. E.g., if you have a class variable that contains a list and you append to that list, changes to subclasses will effect superclasses unless you add the attribute here. Also defines classinstancemethod, which acts as either a class method or an instance method depending on where it is called. """ from __future__ import generators import threading __all__ = ('classinstancemethod', 'DeclarativeMeta', 'Declarative') import copy try: import itertools counter = itertools.count() except ImportError: def _counter(): i = 0 while 1: i += 1 yield i counter = _counter() class classinstancemethod(object): """ Acts like a class method when called from a class, like an instance method when called by an instance. The method should take two arguments, 'self' and 'cls'; one of these will be None depending on how the method was called. """ def __init__(self, func): self.func = func def __get__(self, obj, type=None): return _methodwrapper(self.func, obj=obj, type=type) class _methodwrapper(object): def __init__(self, func, obj, type): self.func = func self.obj = obj self.type = type def __call__(self, *args, **kw): assert not kw.has_key('self') and not kw.has_key('cls'), ( "You cannot use 'self' or 'cls' arguments to a " "classinstancemethod") return self.func(*((self.obj, self.type) + args), **kw) def __repr__(self): if self.obj is None: return ('' % (self.type.__name__, self.func.func_name)) else: return ('' % (self.type.__name__, self.func.func_name, self.obj)) def threadSafeMethod(lock): def decorator(fn): def _wrapper(self, *args, **kwargs): lock.acquire() try: return fn(self, *args, **kwargs) finally: lock.release() try: _wrapper.func_name = fn.func_name except TypeError: pass return _wrapper return decorator class DeclarativeMeta(type): def __new__(meta, class_name, bases, new_attrs): cls = type.__new__(meta, class_name, bases, new_attrs) if new_attrs.has_key('__classinit__'): cls.__classinit__ = staticmethod(cls.__classinit__.im_func) cls.__classinit__(cls, new_attrs) if new_attrs.has_key('__init__'): lock = threading.RLock() cls.__init__ = threadSafeMethod(lock)(cls.__init__) return cls class Declarative(object): __unpackargs__ = () __mutableattributes__ = () __metaclass__ = DeclarativeMeta def __classinit__(cls, new_attrs): cls.declarative_count = counter.next() for name in cls.__mutableattributes__: if not new_attrs.has_key(name): setattr(cls, copy.copy(getattr(cls, name))) def __instanceinit__(self, new_attrs): for name, value in new_attrs.items(): setattr(self, name, value) if not new_attrs.has_key('declarative_count'): self.declarative_count = counter.next() def __init__(self, *args, **kw): if self.__unpackargs__ and self.__unpackargs__[0] == '*': assert len(self.__unpackargs__) == 2, \ "When using __unpackargs__ = ('*', varname), you must only provide a single variable name (you gave %r)" % self.__unpackargs__ name = self.__unpackargs__[1] if kw.has_key(name): raise TypeError( "keyword parameter '%s' was given by position and name" % name) kw[name] = args else: if len(args) > len(self.__unpackargs__): raise TypeError( '%s() takes at most %i arguments (%i given)' % (self.__class__.__name__, len(self.__unpackargs__), len(args))) for name, arg in zip(self.__unpackargs__, args): if kw.has_key(name): raise TypeError( "keyword parameter '%s' was given by position and name" % name) kw[name] = arg if kw.has_key('__alsocopy'): for name, value in kw['__alsocopy'].items(): if not kw.has_key(name): if name in self.__mutableattributes__: value = copy.copy(value) kw[name] = value del kw['__alsocopy'] self.__instanceinit__(kw) def __call__(self, *args, **kw): kw['__alsocopy'] = self.__dict__ return self.__class__(*args, **kw) def singleton(self, cls): if self: return self name = '_%s__singleton' % cls.__name__ if not hasattr(cls, name): setattr(cls, name, cls(declarative_count=cls.declarative_count)) return getattr(cls, name) singleton = classinstancemethod(singleton) def __repr__(self, cls): if self: name = '%s object' % self.__class__.__name__ v = self.__dict__.copy() else: name = '%s class' % cls.__name__ v = cls.__dict__.copy() if v.has_key('declarative_count'): name = '%s %i' % (name, v['declarative_count']) del v['declarative_count'] # @@: simplifying repr: #v = {} names = v.keys() args = [] for n in self._repr_vars(names): args.append('%s=%r' % (n, v[n])) if not args: return '<%s>' % name else: return '<%s %s>' % (name, ' '.join(args)) def _repr_vars(dictNames): names = [n for n in dictNames if not n.startswith('_') and n != 'declarative_count'] names.sort() return names _repr_vars = staticmethod(_repr_vars) __repr__ = classinstancemethod(__repr__) PKa953CI9sqlobject/main.py""" SQLObject --------- :author: Ian Bicking SQLObject is a object-relational mapper. See SQLObject.html or SQLObject.txt for more. Modified by Daniel Savard, Xsoli Inc 7 Feb 2004 - Added support for simple table inheritance. Oleg Broytmann, SIA "ANK" 3 Feb 2005 - Split inheritance support into a number of separate modules and classes - InheritableSQLObject at al. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. """ import threading import sqlbuilder import dbconnection import col import styles import types import warnings import joins import index import classregistry import declarative from sresults import SelectResults from formencode import schema, compound import sys if sys.version_info[:3] < (2, 2, 0): raise ImportError, "SQLObject requires Python 2.2.0 or later" NoDefault = sqlbuilder.NoDefault class SQLObjectNotFound(LookupError): pass class SQLObjectIntegrityError(Exception): pass True, False = 1==1, 0==1 def makeProperties(obj): """ This function takes a dictionary of methods and finds methods named like: * _get_attr * _set_attr * _del_attr * _doc_attr Except for _doc_attr, these should be methods. It then creates properties from these methods, like property(_get_attr, _set_attr, _del_attr, _doc_attr). Missing methods are okay. """ if isinstance(obj, dict): def setFunc(var, value): obj[var] = value d = obj else: def setFunc(var, value): setattr(obj, var, value) d = obj.__dict__ props = {} for var, value in d.items(): if var.startswith('_set_'): props.setdefault(var[5:], {})['set'] = value elif var.startswith('_get_'): props.setdefault(var[5:], {})['get'] = value elif var.startswith('_del_'): props.setdefault(var[5:], {})['del'] = value elif var.startswith('_doc_'): props.setdefault(var[5:], {})['doc'] = value for var, setters in props.items(): if len(setters) == 1 and setters.has_key('doc'): continue if d.has_key(var): if isinstance(d[var], types.MethodType) \ or isinstance(d[var], types.FunctionType): warnings.warn( "I tried to set the property %r, but it was " "already set, as a method (%r). Methods have " "significantly different semantics than properties, " "and this may be a sign of a bug in your code." % (var, d[var])) continue setFunc(var, property(setters.get('get'), setters.get('set'), setters.get('del'), setters.get('doc'))) def unmakeProperties(obj): if isinstance(obj, dict): def delFunc(obj, var): del obj[var] d = obj else: delFunc = delattr d = obj.__dict__ for var, value in d.items(): if isinstance(value, property): for prop in [value.fget, value.fset, value.fdel]: if prop and not d.has_key(prop.__name__): delFunc(obj, var) break def findDependencies(name, registry=None): depends = [] for klass in classregistry.registry(registry).allClasses(): if findDependantColumns(name, klass): depends.append(klass) return depends def findDependantColumns(name, klass): depends = [] for col in klass.sqlmeta.columnList: if col.foreignKey == name and col.cascade is not None: depends.append(col) return depends def _collectAttributes(cls, new_attrs, look_for_class, delete=True, set_name=False, sort=False): """ Finds all attributes in `new_attrs` that are instances of `look_for_class`. Returns them as a list. If `delete` is true they are also removed from the `cls`. If `set_name` is true, then the ``.name`` attribute is set for any matching objects. If `sort` is true, then they will be sorted by ``obj.creationOrder``. """ result = [] for attr, value in new_attrs.items(): if isinstance(value, look_for_class): result.append(value) if set_name: value.name = attr if delete: delattr(cls, attr) if sort: result.sort( lambda a, b: cmp(a.creationOrder, b.creationOrder)) return result class CreateNewSQLObject: """ Dummy singleton to use in place of an ID, to signal we want a new object. """ pass class sqlmeta(object): """ This object is the object we use to keep track of all sorts of information. Subclasses are made for each SQLObject subclass (dynamically if necessary), and instances are created to go alongside every SQLObject instance. """ table = None idName = None idSequence = None # This function is used to coerce IDs into the proper format, # so you should replace it with str, or another function, if you # aren't using integer IDs idType = int style = None lazyUpdate = False defaultOrder = None cacheValues = True registry = None fromDatabase = False # Default is false, but we set it to true for the *instance* # when necessary: (bad clever? maybe) expired = False # This is a mapping from column names to SOCol (or subclass) # instances: columns = {} columnList = [] # This is a mapping from column names to Col (or subclass) # instances; these objects don't have the logic that the SOCol # objects do, and are not attached to this class closely. columnDefinitions = {} # These are lists of the join and index objects: joins = [] indexes = [] indexDefinitions = [] joinDefinitions = [] __metaclass__ = declarative.DeclarativeMeta # These attributes shouldn't be shared with superclasses: _unshared_attributes = ['table', 'idName', 'columns'] # These are internal bookkeeping attributes; the class-level # definition is a default for the instances, instances will # reset these values. # When an object is being created, it has an instance # variable _creating, which is true. This way all the # setters can be captured until the object is complete, # and then the row is inserted into the database. Once # that happens, _creating is deleted from the instance, # and only the class variable (which is always false) is # left. _creating = False _obsolete = False # Sometimes an intance is attached to a connection, not # globally available. In that case, self.sqlmeta._perConnection # will be true. It's false by default: _perConnection = False def __classinit__(cls, new_attrs): for attr in cls._unshared_attributes: if not new_attrs.has_key(attr): setattr(cls, attr, None) def __init__(self, instance): self.instance = instance def setClass(cls, soClass): cls.soClass = soClass if not cls.style: cls.style = styles.defaultStyle try: if cls.soClass._connection and cls.soClass._connection.style: cls.style = cls.soClass._connection.style except AttributeError: pass if cls.table is None: cls.table = cls.style.pythonClassToDBTable(cls.soClass.__name__) if cls.idName is None: cls.idName = cls.style.idForTable(cls.table) # plainSetters are columns that haven't been overridden by the # user, so we can contact the database directly to set them. # Note that these can't set these in the SQLObject class # itself, because they specific to this subclass of SQLObject, # and cannot be shared among classes. cls._plainSetters = {} cls._plainGetters = {} cls._plainForeignSetters = {} cls._plainForeignGetters = {} cls._plainJoinGetters = {} cls._plainJoinAdders = {} cls._plainJoinRemovers = {} # This is a dictionary of columnName: columnObject # None of these objects can be shared with superclasses cls.columns = {} cls.columnList = [] # These, however, can be shared: cls.columnDefinitions = cls.columnDefinitions.copy() cls.indexes = [] cls.indexDefinitions = cls.indexDefinitions[:] cls.joins = [] cls.joinDefinitions = cls.joinDefinitions[:] setClass = classmethod(setClass) ############################################################ ## Adding special values, like columns and indexes ############################################################ ######################################## ## Column handling ######################################## def addColumn(cls, columnDef, changeSchema=False, connection=None): sqlmeta = cls soClass = cls.soClass del cls column = columnDef.withClass(soClass) name = column.name assert name != 'id', ( "The 'id' column is implicit, and should not be defined as " "a column") assert name not in sqlmeta.columns, ( "The class %s.%s already has a column %r (%r), you cannot " "add the column %r" % (soClass.__module__, soClass.__name__, name, sqlmeta.columnDefinitions[name], columnDef)) sqlmeta.columnDefinitions[name] = columnDef sqlmeta.columns[name] = column # A stable-ordered version of the list... sqlmeta.columnList.append(column) ################################################### # Create the getter function(s). We'll start by # creating functions like _SO_get_columnName, # then if there's no function named _get_columnName # we'll alias that to _SO_get_columnName. This # allows a sort of super call, even though there's # no superclass that defines the database access. if sqlmeta.cacheValues: # We create a method here, which is just a function # that takes "self" as the first argument. getter = eval('lambda self: self._SO_loadValue(%s)' % repr(instanceName(name))) else: # If we aren't caching values, we just call the # function _SO_getValue, which fetches from the # database. getter = eval('lambda self: self._SO_getValue(%s)' % repr(name)) setattr(soClass, rawGetterName(name), getter) # Here if the _get_columnName method isn't in the # definition, we add it with the default # _SO_get_columnName definition. if not hasattr(soClass, getterName(name)) or (name == 'childName'): setattr(soClass, getterName(name), getter) sqlmeta._plainGetters[name] = 1 ################################################# # Create the setter function(s) # Much like creating the getters, we will create # _SO_set_columnName methods, and then alias them # to _set_columnName if the user hasn't defined # those methods themself. # @@: This is lame; immutable right now makes it unsettable, # making the table read-only if not column.immutable: # We start by just using the _SO_setValue method setter = eval('lambda self, val: self._SO_setValue(%s, val, self.%s, self.%s)' % (repr(name), '_SO_from_python_%s' % name, '_SO_to_python_%s' % name)) setattr(soClass, '_SO_from_python_%s' % name, column.from_python) setattr(soClass, '_SO_to_python_%s' % name, column.to_python) setattr(soClass, rawSetterName(name), setter) # Then do the aliasing if not hasattr(soClass, setterName(name)) or (name == 'childName'): setattr(soClass, setterName(name), setter) # We keep track of setters that haven't been # overridden, because we can combine these # set columns into one SQL UPDATE query. sqlmeta._plainSetters[name] = 1 ################################################## # Here we check if the column is a foreign key, in # which case we need to make another method that # fetches the key and constructs the sister # SQLObject instance. if column.foreignKey: # We go through the standard _SO_get_columnName # deal, except chopping off the "ID" ending since # we're giving the object, not the ID of the # object this time: if sqlmeta.cacheValues: # self._SO_class_className is a reference # to the class in question. getter = eval('lambda self: self._SO_foreignKey(self._SO_loadValue(%r), self._SO_class_%s)' % (instanceName(name), column.foreignKey)) else: # Same non-caching version as above. getter = eval('lambda self: self._SO_foreignKey(self._SO_getValue(%s), self._SO_class_%s)' % (repr(name), column.foreignKey)) if column.origName.upper().endswith('ID'): origName = column.origName[:-2] else: origName = column.origName setattr(soClass, rawGetterName(origName), getter) # And we set the _get_columnName version # (sans ID ending) if not hasattr(soClass, getterName(name)[:-2]): setattr(soClass, getterName(name)[:-2], getter) sqlmeta._plainForeignGetters[name[:-2]] = 1 if not column.immutable: # The setter just gets the ID of the object, # and then sets the real column. setter = eval('lambda self, val: setattr(self, %s, self._SO_getID(val))' % (repr(name))) setattr(soClass, rawSetterName(name)[:-2], setter) if not hasattr(soClass, setterName(name)[:-2]): setattr(soClass, setterName(name)[:-2], setter) sqlmeta._plainForeignSetters[name[:-2]] = 1 # We'll need to put in a real reference at # some point. See needSet at the top of the # file for more on this. classregistry.registry(sqlmeta.registry).addClassCallback( column.foreignKey, lambda foreign, me, attr: setattr(me, attr, foreign), soClass, '_SO_class_%s' % column.foreignKey) if column.alternateMethodName: func = eval('lambda cls, val, connection=None: cls._SO_fetchAlternateID(%s, %s, val, connection=connection)' % (repr(column.name), repr(column.dbName))) setattr(soClass, column.alternateMethodName, classmethod(func)) if changeSchema: conn = connection or soClass._connection conn.addColumn(sqlmeta.table, column) if soClass._SO_finishedClassCreation: makeProperties(soClass) addColumn = classmethod(addColumn) def addColumnsFromDatabase(sqlmeta, connection=None): soClass = sqlmeta.soClass conn = connection or soClass._connection for columnDef in conn.columnsFromSchema(sqlmeta.table, soClass): if columnDef.name not in sqlmeta.columnDefinitions: if isinstance(columnDef.name, unicode): columnDef.name = columnDef.name.encode('ascii') sqlmeta.addColumn(columnDef) addColumnsFromDatabase = classmethod(addColumnsFromDatabase) def delColumn(sqlmeta, column, changeSchema=False, connection=None): soClass = sqlmeta.soClass if isinstance(column, str): column = sqlmeta.columns[column] if isinstance(column, col.Col): for c in sqlmeta.columns.values(): if column is c.columnDef: column = c break else: raise IndexError( "Column with definition %r not found" % column) name = column.name del sqlmeta.columns[name] del sqlmeta.columnDefinitions[name] sqlmeta.columnList.remove(column) delattr(soClass, rawGetterName(name)) if sqlmeta._plainGetters.has_key(name): delattr(soClass, getterName(name)) delattr(soClass, rawSetterName(name)) if sqlmeta._plainSetters.has_key(name): delattr(soClass, setterName(name)) if column.foreignKey: delattr(soClass, rawGetterName(name)[:-2]) if sqlmeta._plainForeignGetters.has_key(name[:-2]): delattr(soClass, getterName(name)[:-2]) delattr(soClass, rawSetterName(name)[:-2]) if sqlmeta._plainForeignSetters.has_key(name[:-2]): delattr(soClass, setterName(name)[:-2]) if column.alternateMethodName: delattr(soClass, column.alternateMethodName) if changeSchema: conn = connection or soClass._connection conn.delColumn(sqlmeta.table, column) if soClass._SO_finishedClassCreation: unmakeProperties(soClass) delColumn = classmethod(delColumn) ######################################## ## Join handling ######################################## def addJoin(cls, joinDef): sqlmeta = cls soClass = cls.soClass # The name of the method we'll create. If it's # automatically generated, it's generated by the # join class. join = joinDef.withClass(soClass) meth = join.joinMethodName sqlmeta.joins.append(join) index = len(sqlmeta.joins)-1 if joinDef not in sqlmeta.joinDefinitions: sqlmeta.joinDefinitions.append(joinDef) # The function fetches the join by index, and # then lets the join object do the rest of the # work: func = eval('lambda self: self.sqlmeta.joins[%i].performJoin(self)' % index) # And we do the standard _SO_get_... _get_... deal setattr(soClass, rawGetterName(meth), func) if not hasattr(soClass, getterName(meth)): setattr(soClass, getterName(meth), func) sqlmeta._plainJoinGetters[meth] = 1 # Some joins allow you to remove objects from the # join. if hasattr(join, 'remove'): # Again, we let it do the remove, and we do the # standard naming trick. func = eval('lambda self, obj: self.sqlmeta.joins[%i].remove(self, obj)' % index) setattr(soClass, '_SO_remove' + join.addRemoveName, func) if not hasattr(soClass, 'remove' + join.addRemoveName): setattr(soClass, 'remove' + join.addRemoveName, func) sqlmeta._plainJoinRemovers[meth] = 1 # Some joins allow you to add objects. if hasattr(join, 'add'): # And again... func = eval('lambda self, obj: self.sqlmeta.joins[%i].add(self, obj)' % index) setattr(soClass, '_SO_add' + join.addRemoveName, func) if not hasattr(soClass, 'add' + join.addRemoveName): setattr(soClass, 'add' + join.addRemoveName, func) sqlmeta._plainJoinAdders[meth] = 1 if soClass._SO_finishedClassCreation: makeProperties(soClass) addJoin = classmethod(addJoin) def delJoin(sqlmeta, joinDef): soClass = sqlmeta.soClass for join in sqlmeta.joins: # previously deleted joins will be None, so it must # be skipped or it'll error out on the next line. if join is None: continue if joinDef is join.joinDef: break else: raise IndexError( "Join %r not found in class %r (from %r)" % (joinDef, soClass, sqlmeta.joins)) meth = join.joinMethodName sqlmeta.joinDefinitions.remove(joinDef) for i in range(len(sqlmeta.joins)): if sqlmeta.joins[i] is join: # Have to leave None, because we refer to joins # by index. sqlmeta.joins[i] = None delattr(soClass, rawGetterName(meth)) if sqlmeta._plainJoinGetters.has_key(meth): delattr(soClass, getterName(meth)) if hasattr(join, 'remove'): delattr(soClass, '_SO_remove' + join.addRemovePrefix) if sqlmeta._plainJoinRemovers.has_key(meth): delattr(soClass, 'remove' + join.addRemovePrefix) if hasattr(join, 'add'): delattr(soClass, '_SO_add' + join.addRemovePrefix) if sqlmeta._plainJoinAdders.has_key(meth): delattr(soClass, 'add' + join.addRemovePrefix) if soClass._SO_finishedClassCreation: unmakeProperties(soClass) delJoin = classmethod(delJoin) ######################################## ## Indexes ######################################## def addIndex(cls, indexDef): cls.indexDefinitions.append(indexDef) index = indexDef.withClass(cls.soClass) cls.indexes.append(index) addIndex = classmethod(addIndex) sqlhub = dbconnection.ConnectionHub() class _sqlmeta_attr(object): def __init__(self, name, deprecation_level): self.name = name self.deprecation_level = deprecation_level def __get__(self, obj, type=None): if self.deprecation_level is not None: deprecated( 'Use of this attribute should be replaced with ' '.sqlmeta.%s' % self.name, level=self.deprecation_level) return getattr((type or obj).sqlmeta, self.name) # @@: This should become a public interface or documented or # something. Turning it on gives earlier warning about things # that will be deprecated (having this off we won't flood people # with warnings right away). warnings_level = 1 exception_level = None # Current levels: # 1) Actively deprecated in version after 0.6.1 (0.7?); removed after # 2) Deprecated after 1 (0.8?) # 3) Deprecated after 2 (0.9?) def deprecated(message, level=1, stacklevel=2): if exception_level is not None and exception_level <= level: raise NotImplementedError(message) if warnings_level is not None and warnings_level <= level: warnings.warn(message, DeprecationWarning, stacklevel=stacklevel) def setDeprecationLevel(warning=1, exception=None): """ Set the deprecation level for SQLObject. Low levels are more actively being deprecated. Any warning at a level at or below ``warning`` will give a warning. Any warning at a level at or below ``exception`` will give an exception. You can use a higher ``exception`` level for tests to help upgrade your code. ``None`` for either value means never warn or raise exceptions. The levels currently mean: 1) Deprecated in current version (0.7). Will be removed in next version (0.8) 2) Planned to deprecate in next version, remove later. 3) Planned to deprecate sometime, remove sometime much later ;) As the SQLObject versions progress, the deprecation level of specific features will go down, indicating the advancing nature of the feature's doom. We'll try to keep features at 1 for a major revision. As time continues there may be a level 0, which will give a useful error message (better than ``AttributeError``) but where the feature has been fully removed. """ global warnings_level, exception_level warnings_level = warning exception_level = exception # SQLObject is the superclass for all SQLObject classes, of # course. All the deeper magic is done in MetaSQLObject, and # only lesser magic is done here. All the actual work is done # here, though -- just automatic method generation (like # methods and properties for each column) is done in # MetaSQLObject. class SQLObject(object): __metaclass__ = declarative.DeclarativeMeta _connection = sqlhub sqlmeta = sqlmeta #DSM: The _inheritable attribute controls wheter the class can by #DSM: inherited 'logically' with a foreignKey and a back reference. _inheritable = False # Is this class inheritable? _parentClass = None # A reference to the parent class _parent = None # A reference to the parent instance _childClasses = {} # References to child classes childName = None # Children name (to be able to get a subclass) # The law of Demeter: the class should not call another classes by name SelectResultsClass = SelectResults def __classinit__(cls, new_attrs): # This is true if we're initializing the SQLObject class, # instead of a subclass: is_base = cls.__bases__ == (object,) cls._SO_setupSqlmeta(new_attrs, is_base) implicitColumns = _collectAttributes( cls, new_attrs, col.Col, set_name=True, sort=True) implicitJoins = _collectAttributes( cls, new_attrs, joins.Join, set_name=True) implicitIndexes = _collectAttributes( cls, new_attrs, index.DatabaseIndex, set_name=True) if not is_base: cls._SO_cleanDeprecatedAttrs(new_attrs) if new_attrs.has_key('_connection'): connection = new_attrs['_connection'] del cls._connection assert not new_attrs.has_key('connection') elif new_attrs.has_key('connection'): connection = new_attrs['connection'] del cls.connection else: connection = None cls._SO_finishedClassCreation = False if '_columns' in new_attrs and not is_base: deprecated( 'The _columns attribute you gave (%r) is deprecated; ' 'columns should be added as class attributes' % new_attrs['_columns'], level=1) for column in new_attrs['_columns']: if isinstance(column, str): column = col.Col(column) implicitColumns.append(column) if '_joins' in new_attrs and not is_base: deprecated( 'The _joins attribute you gave (%r) is deprecated; ' 'joins should be added as class attributes' % new_attrs['_joins'], level=1) for j in new_attrs['_joins']: implicitJoins.append(j) #DSM: Need to know very soon if the class is a child of an #DSM: inheritable class. If so, we keep a link to our parent class. cls._childClasses = {} for superclass in cls.__bases__: if hasattr(superclass, '_inheritable') and superclass._inheritable and \ superclass.__name__ <> "InheritableSQLObject": cls._parentClass = superclass cls._parent = None superclass._childClasses[cls.__name__] = cls #DSM: If this class is a child of a parent class, we need to do some #DSM: attribute check and add a foreign key to the parent. if cls._parentClass: #DSM: First, look for invalid column name: #DSM: reserved ones or same as a parent parentCols = cls.sqlmeta.columns.keys() for column in implicitColumns: cname = column.name if cname == 'childName': raise AttributeError, \ "The column name 'childName' is reserved" if cname in parentCols: raise AttributeError, "The column '%s' is already " \ "defined in an inheritable parent" % cname #DSM: Remove columns if inherited from an inheritable class #DSM: as we don't want them. All we want is a foreign key #DSM: that points to our parent cls.sqlmeta.columns = {} cls.sqlmeta.columnList = [] cls.sqlmeta.columnDefinitions = {} #DSM: If this is inheritable, add some default columns #DSM: to be able to link to children if hasattr(cls, '_inheritable') and cls._inheritable and \ cls.__name__ <> "InheritableSQLObject": cls.sqlmeta.columnDefinitions['childName'] = col.StringCol( name='childName', length=255, default=None) ###################################################### # Set some attributes to their defaults, if necessary. # First we get the connection: if not connection and not getattr(cls, '_connection', None): mod = sys.modules[cls.__module__] # See if there's a __connection__ global in # the module, use it if there is. if hasattr(mod, '__connection__'): connection = mod.__connection__ if connection and not hasattr(cls, '_connection'): cls.setConnection(connection) # We have to check if there are columns in the inherited # _columns where the attribute has been set to None in this # class. If so, then we need to remove that column from # _columns. for key in cls.sqlmeta.columnDefinitions.keys(): if (key in new_attrs and new_attrs[key] is None): del cls.sqlmeta.columnDefinitions[key] for column in cls.sqlmeta.columnDefinitions.values(): cls.sqlmeta.addColumn(column) for column in implicitColumns: cls.sqlmeta.addColumn(column) if cls.sqlmeta.fromDatabase: cls.sqlmeta.addColumnsFromDatabase() for j in implicitJoins: cls.sqlmeta.addJoin(j) for i in implicitIndexes: cls.sqlmeta.addIndex(i) # We don't setup the properties until we're finished with the # batch adding of all the columns... cls._notifyFinishClassCreation() cls._SO_finishedClassCreation = True makeProperties(cls) # We use the magic "q" attribute for accessing lazy # SQL where-clause generation. See the sql module for # more. if not is_base: cls.q = sqlbuilder.SQLObjectTable(cls) #DSM: If we are a child, get the q magic from the parent currentClass = cls while currentClass._parentClass: currentClass = currentClass._parentClass for column in currentClass.sqlmeta.columnDefinitions.values(): if type(column) == col.ForeignKey: continue setattr(cls.q, column.name, getattr(currentClass.q, column.name)) classregistry.registry(cls.sqlmeta.registry).addClass(cls) _style = _sqlmeta_attr('style', 2) _table = _sqlmeta_attr('table', 2) _idName = _sqlmeta_attr('idName', 2) _lazyUpdate = _sqlmeta_attr('lazyUpdate', 2) _defaultOrder = _sqlmeta_attr('defaultOrder', 2) _cacheValues = _sqlmeta_attr('cacheValues', 2) _registry = _sqlmeta_attr('registry', 2) _idType = _sqlmeta_attr('idType', 2) _fromDatabase = _sqlmeta_attr('fromDatabase', 2) _expired = _sqlmeta_attr('expired', 2) _columns = _sqlmeta_attr('columnList', 1) _columnDict = _sqlmeta_attr('columns', 1) addColumn = _sqlmeta_attr('addColumn', 2) delColumn = _sqlmeta_attr('delColumn', 2) addJoin = _sqlmeta_attr('addJoin', 2) delJoin = _sqlmeta_attr('delJoin', 2) addIndex = _sqlmeta_attr('addIndex', 2) # @classmethod def _SO_setupSqlmeta(cls, new_attrs, is_base): """ This fixes up the sqlmeta attribute. It handles both the case where no sqlmeta was given (in which we need to create another subclass), or the sqlmeta given doesn't have the proper inheritance. Lastly it calls sqlmeta.setClass, which handles much of the setup. """ if (not new_attrs.has_key('sqlmeta') and not is_base): # We have to create our own subclass, usually. # type(className, bases_tuple, attr_dict) creates a new # subclass: cls.sqlmeta = type('sqlmeta', (cls.sqlmeta,), {}) if not issubclass(cls.sqlmeta, sqlmeta): # We allow no superclass and an object superclass, instead # of inheriting from sqlmeta; but in that case we replace # the class and just move over its attributes: assert cls.sqlmeta.__bases__ in ((), (object,)), ( "If you do not inherit your sqlmeta class from " "sqlobject.sqlmeta, it must not inherit from any other " "class (your sqlmeta inherits from: %s)" % cls.sqlmeta.__bases__) for base in cls.__bases__: superclass = getattr(base, 'sqlmeta', None) if superclass: break else: assert 0, ( "No sqlmeta class could be found in any superclass " "(while fixing up sqlmeta %r inheritance)" % cls.sqlmeta) values = dict(cls.sqlmeta.__dict__) for key in values.keys(): if key.startswith('__') and key.endswith('__'): # Magic values shouldn't be passed through: del values[key] cls.sqlmeta = type('sqlmeta', (superclass,), values) cls.sqlmeta.setClass(cls) _SO_setupSqlmeta = classmethod(_SO_setupSqlmeta) # @classmethod def _SO_cleanDeprecatedAttrs(cls, new_attrs): """ This removes attributes on SQLObject subclasses that have been deprecated; they are moved to the sqlmeta class, and a deprecation warning is given. """ for attr in ['_table', '_lazyUpdate', '_style', '_idName', '_defaultOrder', '_cacheValues', '_registry', '_idType', '_fromDatabase', '_idSequence']: if new_attrs.has_key(attr): new_name = attr[1:] deprecated("%r is deprecated; please set the %r " "attribute in sqlmeta instead" % (attr, new_name), level=2, stacklevel=5) setattr(cls.sqlmeta, new_name, new_attrs[attr]) delattr(cls, attr) for attr in ['_expired']: if new_attrs.has_key(attr): deprecated("%r is deprecated and read-only; please do " "not use it in your classes until it is fully " "deprecated" % attr, level=3, stacklevel=5) _SO_cleanDeprecatedAttrs = classmethod(_SO_cleanDeprecatedAttrs) def get(cls, id, connection=None, selectResults=None): assert id is not None, 'None is not a possible id for %s' % cls.__name__ id = cls.sqlmeta.idType(id) if connection is None: cache = cls._connection.cache else: cache = connection.cache # This whole sequence comes from Cache.CacheFactory's # behavior, where a None returned means a cache miss. val = cache.get(id, cls) if val is None: try: val = cls(_SO_fetch_no_create=1) val._SO_validatorState = SQLObjectState(val) val._init(id, connection, selectResults) cache.put(id, cls, val) finally: cache.finishPut(cls) elif selectResults and not val.dirty: val._SO_writeLock.acquire() try: val._SO_selectInit(selectResults) val.sqlmeta.expired = False finally: val._SO_writeLock.release() return val get = classmethod(get) def _notifyFinishClassCreation(cls): pass _notifyFinishClassCreation = classmethod(_notifyFinishClassCreation) def _init(self, id, connection=None, selectResults=None): assert id is not None # This function gets called only when the object is # created, unlike __init__ which would be called # anytime the object was returned from cache. self.id = id # We shadow the sqlmeta class with an instance of sqlmeta # that points to us (our sqlmeta buddy object; where the # sqlmeta class is our class's buddy class) self.sqlmeta = self.__class__.sqlmeta(self) self._SO_writeLock = threading.Lock() # If no connection was given, we'll inherit the class # instance variable which should have a _connection # attribute. if connection is not None: self._connection = connection # Sometimes we need to know if this instance is # global or tied to a particular connection. # This flag tells us that: self.sqlmeta._perConnection = True if not selectResults: dbNames = [col.dbName for col in self.sqlmeta.columnList] selectResults = self._connection._SO_selectOne(self, dbNames) if not selectResults: raise SQLObjectNotFound, "The object %s by the ID %s does not exist" % (self.__class__.__name__, self.id) self._SO_selectInit(selectResults) self._SO_createValues = {} self.dirty = False def _SO_loadValue(self, attrName): try: return getattr(self, attrName) except AttributeError: try: self._SO_writeLock.acquire() try: # Maybe, just in the moment since we got the lock, # some other thread did a _SO_loadValue and we # have the attribute! Let's try and find out! We # can keep trying this all day and still beat the # performance on the database call (okay, we can # keep trying this for a few msecs at least)... result = getattr(self, attrName) except AttributeError: pass else: return result self.sqlmeta.expired = False dbNames = [col.dbName for col in self.sqlmeta.columnList] selectResults = self._connection._SO_selectOne(self, dbNames) if not selectResults: raise SQLObjectNotFound, "The object %s by the ID %s has been deleted" % (self.__class__.__name__, self.id) self._SO_selectInit(selectResults) result = getattr(self, attrName) return result finally: self._SO_writeLock.release() def sync(self): if self.sqlmeta.lazyUpdate and self._SO_createValues: self.syncUpdate() self._SO_writeLock.acquire() try: dbNames = [col.dbName for col in self.sqlmeta.columnList] selectResults = self._connection._SO_selectOne(self, dbNames) if not selectResults: raise SQLObjectNotFound, "The object %s by the ID %s has been deleted" % (self.__class__.__name__, self.id) self._SO_selectInit(selectResults) self.sqlmeta.expired = False finally: self._SO_writeLock.release() def syncUpdate(self): if not self._SO_createValues: return self._SO_writeLock.acquire() try: if self.sqlmeta.columns: values = [(self.sqlmeta.columns[v[0]].dbName, v[1]) for v in self._SO_createValues.items()] self._connection._SO_update(self, values) self.dirty = False self._SO_createValues = {} finally: self._SO_writeLock.release() def expire(self): if self.sqlmeta.expired: return self._SO_writeLock.acquire() try: if self.sqlmeta.expired: return for column in self.sqlmeta.columnList: delattr(self, instanceName(column.name)) self.sqlmeta.expired = True self._connection.cache.expire(self.id, self.__class__) self._SO_createValues = {} finally: self._SO_writeLock.release() def _SO_setValue(self, name, value, from_python, to_python): # This is the place where we actually update the # database. # If we are _creating, the object doesn't yet exist # in the database, and we can't insert it until all # the parts are set. So we just keep them in a # dictionary until later: if from_python: dbValue = from_python(value, self._SO_validatorState) else: dbValue = value if to_python: value = to_python(dbValue, self._SO_validatorState) if self.sqlmeta._creating or self.sqlmeta.lazyUpdate: self.dirty = True self._SO_createValues[name] = dbValue setattr(self, instanceName(name), value) return self._connection._SO_update( self, [(self.sqlmeta.columns[name].dbName, dbValue)]) if self.sqlmeta.cacheValues: setattr(self, instanceName(name), value) def set(self, **kw): # set() is used to update multiple values at once, # potentially with one SQL statement if possible. # Filter out items that don't map to column names. # Those will be set directly on the object using # setattr(obj, name, value). is_column = self.sqlmeta._plainSetters.has_key f_is_column = lambda item: is_column(item[0]) f_not_column = lambda item: not is_column(item[0]) items = kw.items() extra = dict(filter(f_not_column, items)) kw = dict(filter(f_is_column, items)) # _creating is special, see _SO_setValue if self.sqlmeta._creating or self.sqlmeta.lazyUpdate: for name, value in kw.items(): from_python = getattr(self, '_SO_from_python_%s' % name, None) if from_python: kw[name] = dbValue = from_python(value, self._SO_validatorState) else: dbValue = value to_python = getattr(self, '_SO_to_python_%s' % name, None) if to_python: value = to_python(dbValue, self._SO_validatorState) setattr(self, instanceName(name), value) self._SO_createValues.update(kw) for name, value in extra.items(): try: getattr(self.__class__, name) except AttributeError: if name not in self.sqlmeta.columns: raise TypeError, "%s.set() got an unexpected keyword argument %s" % (self.__class__.__name__, name) try: setattr(self, name, value) except AttributeError, e: raise AttributeError, '%s (with attribute %r)' % (e, name) self.dirty = True return self._SO_writeLock.acquire() try: # We have to go through and see if the setters are # "plain", that is, if the user has changed their # definition in any way (put in something that # normalizes the value or checks for consistency, # for instance). If so then we have to use plain # old setattr() to change the value, since we can't # read the user's mind. We'll combine everything # else into a single UPDATE, if necessary. toUpdate = {} for name, value in kw.items(): from_python = getattr(self, '_SO_from_python_%s' % name, None) if from_python: dbValue = from_python(value, self._SO_validatorState) else: dbValue = value to_python = getattr(self, '_SO_to_python_%s' % name, None) if to_python: value = to_python(dbValue, self._SO_validatorState) if self.sqlmeta.cacheValues: setattr(self, instanceName(name), value) toUpdate[name] = dbValue for name, value in extra.items(): try: getattr(self.__class__, name) except AttributeError: if name not in self.sqlmeta.columns: raise TypeError, "%s.set() got an unexpected keyword argument %s" % (self.__class__.__name__, name) try: setattr(self, name, value) except AttributeError, e: raise AttributeError, '%s (with attribute %r)' % (e, name) if toUpdate: args = [(self.sqlmeta.columns[name].dbName, value) for name, value in toUpdate.items()] self._connection._SO_update(self, args) finally: self._SO_writeLock.release() def _SO_selectInit(self, row): for col, colValue in zip(self.sqlmeta.columnList, row): if col.to_python: colValue = col.to_python(colValue, self._SO_validatorState) setattr(self, instanceName(col.name), colValue) def _SO_getValue(self, name): # Retrieves a single value from the database. Simple. assert not self.sqlmeta._obsolete, ( "%s with id %s has become obsolete" \ % (self.__class__.__name__, self.id)) # @@: do we really need this lock? #self._SO_writeLock.acquire() column = self.sqlmeta.columns[name] results = self._connection._SO_selectOne(self, [column.dbName]) #self._SO_writeLock.release() assert results != None, "%s with id %s is not in the database" \ % (self.__class__.__name__, self.id) value = results[0] if column.to_python: value = column.to_python(value, self._SO_validatorState) return value def _SO_foreignKey(self, id, joinClass): if id is None: return None elif self.sqlmeta._perConnection: return joinClass.get(id, connection=self._connection) else: return joinClass.get(id) def __init__(self, **kw): # The get() classmethod/constructor uses a magic keyword # argument when it wants an empty object, fetched from the # database. So we have nothing more to do in that case: if kw.has_key('_SO_fetch_no_create'): return # Pass the connection object along if we were given one. if kw.has_key('connection'): self._connection = kw['connection'] self.sqlmeta._perConnection = True del kw['connection'] self._SO_writeLock = threading.Lock() if kw.has_key('id'): id = self.sqlmeta.idType(kw['id']) del kw['id'] else: id = None self._create(id, **kw) def _create(self, id, **kw): self.sqlmeta._creating = True self._SO_createValues = {} self._SO_validatorState = SQLObjectState(self) # First we do a little fix-up on the keywords we were # passed: for column in self.sqlmeta.columnList: # Then we check if the column wasn't passed in, and # if not we try to get the default. if not kw.has_key(column.name) and not kw.has_key(column.foreignName): default = column.default # If we don't get it, it's an error: if default is NoDefault: raise TypeError, "%s() did not get expected keyword argument %s" % (self.__class__.__name__, column.name) # Otherwise we put it in as though they did pass # that keyword: kw[column.name] = default self.set(**kw) # Then we finalize the process: self._SO_finishCreate(id) def _SO_finishCreate(self, id=None): # Here's where an INSERT is finalized. # These are all the column values that were supposed # to be set, but were delayed until now: setters = self._SO_createValues.items() # Here's their database names: names = [self.sqlmeta.columns[v[0]].dbName for v in setters] values = [v[1] for v in setters] # Get rid of _SO_create*, we aren't creating anymore. # Doesn't have to be threadsafe because we're still in # new(), which doesn't need to be threadsafe. self.dirty = False if not self.sqlmeta.lazyUpdate: del self._SO_createValues else: self._SO_createValues = {} del self.sqlmeta._creating # Do the insert -- most of the SQL in this case is left # up to DBConnection, since getting a new ID is # non-standard. id = self._connection.queryInsertID(self, id, names, values) cache = self._connection.cache cache.created(id, self.__class__, self) self._init(id) def _SO_getID(self, obj): return getID(obj) def _findAlternateID(cls, name, dbName, value, connection=None): if isinstance(value, unicode): column = cls.sqlmeta.columns[name] if isinstance(column, col.SOUnicodeCol): value = value.encode(column.dbEncoding) return (connection or cls._connection)._SO_selectOneAlt( cls, [cls.sqlmeta.idName] + [column.dbName for column in cls.sqlmeta.columnList], dbName, value), None _findAlternateID = classmethod(_findAlternateID) def _SO_fetchAlternateID(cls, name, dbName, value, connection=None): result, obj = cls._findAlternateID(name, dbName, value, connection) if not result: raise SQLObjectNotFound, "The %s by alternateID %s=%s does not exist" % (cls.__name__, name, repr(value)) if obj: return obj if connection: obj = cls.get(result[0], connection=connection, selectResults=result[1:]) else: obj = cls.get(result[0], selectResults=result[1:]) return obj _SO_fetchAlternateID = classmethod(_SO_fetchAlternateID) def _SO_depends(cls): return findDependencies(cls.__name__, cls.sqlmeta.registry) _SO_depends = classmethod(_SO_depends) def select(cls, clause=None, clauseTables=None, orderBy=NoDefault, limit=None, lazyColumns=False, reversed=False, distinct=False, connection=None, join=None): return cls.SelectResultsClass(cls, clause, clauseTables=clauseTables, orderBy=orderBy, limit=limit, lazyColumns=lazyColumns, reversed=reversed, distinct=distinct, connection=connection, join=join) select = classmethod(select) def selectBy(cls, connection=None, **kw): for key, column in cls.sqlmeta.columns.items(): if (key in kw) and isinstance(column, col.SOUnicodeCol): value = kw[key] if isinstance(value, unicode): kw[key] = value.encode(column.dbEncoding) conn = connection or cls._connection return cls.SelectResultsClass(cls, conn._SO_columnClause(cls, kw), connection=conn) selectBy = classmethod(selectBy) def dropTable(cls, ifExists=False, dropJoinTables=True, cascade=False, connection=None): conn = connection or cls._connection if ifExists and not conn.tableExists(cls.sqlmeta.table): return conn.dropTable(cls.sqlmeta.table, cascade) if dropJoinTables: cls.dropJoinTables(ifExists=ifExists, connection=conn) dropTable = classmethod(dropTable) def createTable(cls, ifNotExists=False, createJoinTables=True, createIndexes=True, connection=None): conn = connection or cls._connection if ifNotExists and conn.tableExists(cls.sqlmeta.table): return conn.createTable(cls) if createJoinTables: cls.createJoinTables(ifNotExists=ifNotExists, connection=conn) if createIndexes: cls.createIndexes(ifNotExists=ifNotExists, connection=conn) createTable = classmethod(createTable) def createTableSQL(cls, createJoinTables=True, connection=None, createIndexes=True): conn = connection or cls._connection sql = conn.createTableSQL(cls) if createJoinTables: sql += ';\n' + cls.createJoinTablesSQL(connection=conn) if createIndexes: sql += ';\n' + cls.createIndexesSQL(connection=conn) return sql createTableSQL = classmethod(createTableSQL) def createJoinTables(cls, ifNotExists=False, connection=None): conn = connection or cls._connection for join in cls._getJoinsToCreate(): if not getattr(join, 'createRelatedTable', True): # This join has requested not to be created continue if (ifNotExists and conn.tableExists(join.intermediateTable)): continue conn._SO_createJoinTable(join) createJoinTables = classmethod(createJoinTables) def createJoinTablesSQL(cls, connection=None): conn = connection or cls._connection sql = [] for join in cls._getJoinsToCreate(): if not getattr(join, 'createRelatedTable', True): # This join has requested not to be created continue sql.append(conn._SO_createJoinTableSQL(join)) return ';\n'.join(sql) createJoinTablesSQL = classmethod(createJoinTablesSQL) def createIndexes(cls, ifNotExists=False, connection=None): conn = connection or cls._connection for index in cls.sqlmeta.indexes: if not index: continue conn._SO_createIndex(cls, index) createIndexes = classmethod(createIndexes) def createIndexesSQL(cls, connection=None): conn = connection or cls._connection sql = [] for index in cls.sqlmeta.indexes: if not index: continue sql.append(conn.createIndexSQL(cls, index)) return ';\n'.join(sql) createIndexesSQL = classmethod(createIndexesSQL) def _getJoinsToCreate(cls): joins = [] for join in cls.sqlmeta.joins: if not join: continue if not join.hasIntermediateTable(): continue if join.soClass.__name__ > join.otherClass.__name__: continue joins.append(join) return joins _getJoinsToCreate = classmethod(_getJoinsToCreate) def dropJoinTables(cls, ifExists=False, connection=None): conn = connection or cls._connection for join in cls.sqlmeta.joins: if not join: continue if not join.hasIntermediateTable(): continue if join.soClass.__name__ > join.otherClass.__name__: continue if ifExists and \ not conn.tableExists(join.intermediateTable): continue conn._SO_dropJoinTable(join) dropJoinTables = classmethod(dropJoinTables) def clearTable(cls, connection=None, clearJoinTables=True): # 3-03 @@: Maybe this should check the cache... but it's # kind of crude anyway, so... conn = connection or cls._connection conn.clearTable(cls.sqlmeta.table) if clearJoinTables: for join in cls._getJoinsToCreate(): conn.clearTable(join.intermediateTable) clearTable = classmethod(clearTable) def destroySelf(self): # Kills this object. Kills it dead! depends = [] klass = self.__class__ depends = self._SO_depends() for k in depends: cols = findDependantColumns(klass.__name__, k) query = [] delete = setnull = restrict = False for col in cols: if col.cascade == False: # Found a restriction restrict = True query.append(getattr(k.q, col.name) == self.id) if col.cascade == 'null': setnull = col.name elif col.cascade: delete = True assert delete or setnull or restrict, ( "Class %s depends on %s accoriding to " "findDependantColumns, but this seems inaccurate" % (k, klass)) query = sqlbuilder.OR(*query) results = k.select(query, connection=self._connection) if restrict: if results.count(): # Restrictions only apply if there are # matching records on the related table raise SQLObjectIntegrityError, ( "Tried to delete %s::%s but " "table %s has a restriction against it" % (klass.__name__, self.id, k.__name__)) else: for row in results: if delete: row.destroySelf() else: row.set(**{setnull: None}) self.sqlmeta._obsolete = True self._connection._SO_delete(self) self._connection.cache.expire(self.id, self.__class__) def delete(cls, id, connection=None): obj = cls.get(id, connection=connection) obj.destroySelf() delete = classmethod(delete) def __repr__(self): return '<%s %r %s>' \ % (self.__class__.__name__, self.id, ' '.join(['%s=%s' % (name, repr(value)) for name, value in self._reprItems()])) def sqlrepr(cls, value, connection=None): return (connection or cls._connection).sqlrepr(value) sqlrepr = classmethod(sqlrepr) def coerceID(cls, value): if isinstance(value, cls): return value.id else: return cls.sqlmeta.idType(value) coerceID = classmethod(coerceID) def _reprItems(self): items = [] for col in self.sqlmeta.columnList: value = getattr(self, col.name) r = repr(value) if len(r) > 20: value = r[:17] + "..." + r[-1] items.append((col.name, value)) return items def setConnection(cls, value): if isinstance(value, (str, unicode)): value = dbconnection.connectionForURI(value) cls._connection = value setConnection = classmethod(setConnection) def capitalize(name): return name[0].capitalize() + name[1:] def setterName(name): return '_set_%s' % name def rawSetterName(name): return '_SO_set_%s' % name def getterName(name): return '_get_%s' % name def rawGetterName(name): return '_SO_get_%s' % name def instanceName(name): return '_SO_val_%s' % name class SQLObjectState(object): def __init__(self, soObject): self.soObject = soObject self.protocol = 'sql' ######################################## ## Utility functions (for external consumption) ######################################## def getID(obj): if isinstance(obj, SQLObject): return obj.id elif type(obj) is type(1): return obj elif type(obj) is type(1L): return int(obj) elif type(obj) is type(""): try: return int(obj) except ValueError: return obj elif obj is None: return None def getObject(obj, klass): if type(obj) is type(1): return klass(obj) elif type(obj) is type(1L): return klass(int(obj)) elif type(obj) is type(""): return klass(int(obj)) elif obj is None: return None else: return obj __all__ = ['NoDefault', 'SQLObject', 'sqlmeta', 'getID', 'getObject', 'SQLObjectNotFound', 'sqlhub', 'setDeprecationLevel'] PKa95i9"9"sqlobject/sresults.pyimport sqlbuilder import dbconnection StringType = type('') class SelectResults(object): IterationClass = dbconnection.Iteration def __init__(self, sourceClass, clause, clauseTables=None, **ops): self.sourceClass = sourceClass if clause is None or isinstance(clause, str) and clause == 'all': clause = sqlbuilder.SQLTrueClause self.clause = clause tablesDict = sqlbuilder.tablesUsedDict(self.clause) tablesDict[sourceClass.sqlmeta.table] = 1 if clauseTables: for table in clauseTables: tablesDict[table] = 1 self.clauseTables = clauseTables self.tables = tablesDict.keys() self.ops = ops if self.ops.get('orderBy', sqlbuilder.NoDefault) is sqlbuilder.NoDefault: self.ops['orderBy'] = sourceClass.sqlmeta.defaultOrder orderBy = self.ops['orderBy'] if isinstance(orderBy, list) or isinstance(orderBy, tuple): orderBy = map(self._mungeOrderBy, orderBy) else: orderBy = self._mungeOrderBy(orderBy) self.ops['dbOrderBy'] = orderBy if ops.has_key('connection') and ops['connection'] is None: del ops['connection'] def __repr__(self): return "<%s at %x>" % (self.__class__.__name__, id(self)) def _getConnection(self): return self.ops.get('connection') or self.sourceClass._connection def __str__(self): conn = self._getConnection() return conn.queryForSelect(self) def _mungeOrderBy(self, orderBy): if isinstance(orderBy, str) and orderBy.startswith('-'): orderBy = orderBy[1:] desc = True else: desc = False if isinstance(orderBy, (str, unicode)): if orderBy in self.sourceClass.sqlmeta.columns: val = self.sourceClass.sqlmeta.columns[orderBy].dbName if desc: return '-' + val else: return val else: if desc: return '-' + orderBy else: return orderBy else: return orderBy def clone(self, **newOps): ops = self.ops.copy() ops.update(newOps) return self.__class__(self.sourceClass, self.clause, self.clauseTables, **ops) def orderBy(self, orderBy): return self.clone(orderBy=orderBy) def connection(self, conn): return self.clone(connection=conn) def limit(self, limit): return self[:limit] def lazyColumns(self, value): return self.clone(lazyColumns=value) def reversed(self): return self.clone(reversed=not self.ops.get('reversed', False)) def distinct(self): return self.clone(distinct=True) def newClause(self, new_clause): return self.__class__(self.sourceClass, new_clause, self.clauseTables, **self.ops) def filter(self, filter_clause): if filter_clause is None: # None doesn't filter anything, it's just a no-op: return self clause = self.clause if isinstance(clause, (str, unicode)): clause = sqlbuilder.SQLConstant('(%s)' % self.clause) return self.newClause(sqlbuilder.AND(clause, filter_clause)) def __getitem__(self, value): if type(value) is type(slice(1)): assert not value.step, "Slices do not support steps" if not value.start and not value.stop: # No need to copy, I'm immutable return self # Negative indexes aren't handled (and everything we # don't handle ourselves we just create a list to # handle) if (value.start and value.start < 0) \ or (value.stop and value.stop < 0): if value.start: if value.stop: return list(self)[value.start:value.stop] return list(self)[value.start:] return list(self)[:value.stop] if value.start: assert value.start >= 0 start = self.ops.get('start', 0) + value.start if value.stop is not None: assert value.stop >= 0 if value.stop < value.start: # an empty result: end = start else: end = value.stop + self.ops.get('start', 0) if self.ops.get('end', None) is not None \ and value['end'] < end: # truncated by previous slice: end = self.ops['end'] else: end = self.ops.get('end', None) else: start = self.ops.get('start', 0) end = value.stop + start if self.ops.get('end', None) is not None \ and self.ops['end'] < end: end = self.ops['end'] return self.clone(start=start, end=end) else: if value < 0: return list(iter(self))[value] else: start = self.ops.get('start', 0) + value return list(self.clone(start=start, end=start+1))[0] def __iter__(self): # @@: This could be optimized, using a simpler algorithm # since we don't have to worry about garbage collection, # etc., like we do with .lazyIter() return iter(list(self.lazyIter())) def lazyIter(self): """ Returns an iterator that will lazily pull rows out of the database and return SQLObject instances """ conn = self._getConnection() return conn.iterSelect(self) def accumulate(self, *expressions): """ Use accumulate expression(s) to select result using another SQL select through current connection. Return the accumulate result """ conn = self._getConnection() return conn.accumulateSelect(self, *expressions) def count(self): """ Counting elements of current select results """ assert not (self.ops.get('distinct') and (self.ops.get('start') or self.ops.get('end'))), \ "distinct-counting of sliced objects is not supported" if self.ops.get('distinct'): # Column must be specified, so we are using unique ID column. # COUNT(DISTINCT column) is supported by MySQL and PostgreSQL, # but not by SQLite. Perhaps more portable would be subquery: # SELECT COUNT(*) FROM (SELECT DISTINCT id FROM table) count = self.accumulate('COUNT(DISTINCT %s.%s)' % ( self.sourceClass.sqlmeta.table, self.sourceClass.sqlmeta.idName)) else: count = self.accumulate('COUNT(*)') if self.ops.get('start'): count -= self.ops['start'] if self.ops.get('end'): count = min(self.ops['end'] - self.ops.get('start', 0), count) return count def accumulateMany(self, *attributes): """ Making the expressions for count/sum/min/max/avg of a given select result attributes. `attributes` must be a list/tuple of pairs (func_name, attribute); `attribute` can be a column name (like 'a_column') or a dot-q attribute (like Table.q.aColumn) """ expressions = [] for func_name, attribute in attributes: if type(attribute) == StringType: expression = '%s(%s)' % (func_name, attribute) else: expression = getattr(sqlbuilder.func, func_name)(attribute) expressions.append(expression) return self.accumulate(*expressions) def accumulateOne(self, func_name, attribute): """ Making the sum/min/max/avg of a given select result attribute. `attribute` can be a column name (like 'a_column') or a dot-q attribute (like Table.q.aColumn) """ return self.accumulateMany((func_name, attribute)) def sum(self, attribute): return self.accumulateOne("SUM", attribute) def min(self, attribute): return self.accumulateOne("MIN", attribute) def avg(self, attribute): return self.accumulateOne("AVG", attribute) def max(self, attribute): return self.accumulateOne("MAX", attribute) __all__ = ['SelectResults'] PKa95ȿ5:sqlobject/conftest.py""" This module is used by py.test to configure testing for this application. """ # Override some options (doesn't override command line): verbose = 0 exitfirst = True import py import os import sqlobject connectionShortcuts = { 'mysql': 'mysql://test@localhost/test', 'dbm': 'dbm:///data', 'postgres': 'postgres:///test', 'postgresql': 'postgres:///test', 'pygresql': 'pygresql://localhost/test', 'sqlite': 'sqlite:///%s/data/sqlite.data' % os.getcwd(), 'sybase': 'sybase://test:test123@sybase/test?autoCommit=0', 'firebird': 'firebird://sysdba:masterkey@localhost/var/lib/firebird/data/test.gdb', 'mssql': 'mssql://sa:@127.0.0.1/test' } Option = py.test.Config.Option option = py.test.Config.addoptions( "SQLObject options", Option('-D', '--Database', action="store", dest="Database", default='sqlite', help="The database to run the tests under (default sqlite). " "Can also use an alias from: %s" % (', '.join(connectionShortcuts.keys()))), Option('-S', '--SQL', action="store_true", dest="show_sql", default=False, help="Show SQL from statements (when capturing stdout the " "SQL is only displayed when a test fails)"), Option('-O', '--SQL-output', action="store_true", dest="show_sql_output", default=False, help="Show output from SQL statements (when capturing " "stdout the output is only displayed when a test fails)")) class SQLObjectClass(py.test.collect.Class): def run(self): if (isinstance(self.obj, type) and issubclass(self.obj, sqlobject.SQLObject)): return [] return super(SQLObjectClass, self).run() Class = SQLObjectClass PKb95Hllsqlobject/boundattributes.pyc; Ec@sfdZddddgZdkZdeifdYZdefdYZdZd ZdS( s, Bound attributes are attributes that are bound to a specific class and a specific name. In SQLObject a typical example is a column object, which knows its name and class. A bound attribute should define a method ``__addtoclass__(added_class, name)`` (attributes without this method will simply be treated as normal). The return value is ignored; if the attribute wishes to change the value in the class, it must call ``setattr(added_class, name, new_value)``. BoundAttribute is a class that facilitates lazy attribute creation. ``bind_attributes(cls, new_attrs)`` is a function that looks for attributes with this special method. ``new_attrs`` is a dictionary, as typically passed into ``__classinit__`` with declarative (calling ``bind_attributes`` in ``__classinit__`` would be typical). Note if you do this that attributes defined in a superclass will not be rebound in subclasses. If you want to rebind attributes in subclasses, use ``bind_attributes_local``, which adds a ``__bound_attributes__`` variable to your class to track these active attributes. sBoundAttributes BoundFactorysbind_attributessbind_attributes_localNcBstZdZdddddddfZfZdZd Zd ZeeZd Z e i e Z d Z e e Z d Ze eZRS(s" This is a declarative class that passes all the values given to it to another object. So you can pass it arguments (via __init__/__call__) or give it the equivalent of keyword arguments through subclassing. Then a bound object will be added in its place. To hook this other object in, override ``make_object(added_class, name, **attrs)`` and maybe ``set_object(added_class, name, **attrs)`` (the default implementation of ``set_object`` just resets the attribute to whatever ``make_object`` returned). s_private_variabless_all_attributess __classinit__s__addtoclass__s _add_attrss set_objects make_objectcCs,tii|||i|||_dS(N(s declaratives Declaratives __classinit__sclss new_attrss _add_attrss _all_attrs(sclss new_attrs((s7build/bdist.linux-i686/egg/sqlobject/boundattributes.pys __classinit__:scCs,tii|||i|||_dS(N(s declaratives Declaratives__instanceinit__sselfs new_attrss _add_attrss _all_attrs(sselfs new_attrs((s7build/bdist.linux-i686/egg/sqlobject/boundattributes.pys__instanceinit__>scCs|i}t|i}xV|iD]H}|i dp ||joq%n||jo|i |q%q%Wt |SdS(Ns_( s this_objects_private_variablessprivateslists _all_attrss all_attrss new_attrsskeysskeys startswithsappendstuple(s this_objects new_attrssprivateskeys all_attrs((s7build/bdist.linux-i686/egg/sqlobject/boundattributes.pys _add_attrsBs   cCst|p|}h}x$|iD]}t|||||iD]0\}}t|do|i||q q WdS(Ns__addtoclass__(s new_attrssitemssnamesvalueshasattrs__addtoclass__scls(sclss new_attrssvaluesname((s7build/bdist.linux-i686/egg/sqlobject/boundattributes.pysbind_attributesjs cCsh}xWt|dhiD]=\}}|i|oqn|i||||||dfjo|odSq:dSn|odSndSdS(Nspostgress't's'f's1s0(sdbsvalue(svaluesdb((s2build/bdist.linux-i686/egg/sqlobject/converters.pys BoolConverterscCst|SdS(N(sreprsvalue(svaluesdb((s2build/bdist.linux-i686/egg/sqlobject/converters.pysFloatConvertersf1.0cCsdt|SdS(Ns'%s'(sisoStrsvalue(svaluesdb((s2build/bdist.linux-i686/egg/sqlobject/converters.pysDateTimeConverterscCsd|idSdS(Ns'%s's%T(svaluesstrftime(svaluesdb((s2build/bdist.linux-i686/egg/sqlobject/converters.pys TimeConverterscCsdSdS(NsNULL((svaluesdb((s2build/bdist.linux-i686/egg/sqlobject/converters.pys NoneConverterscCs?ddigi}|D]}|t||q~SdS(Ns(%s)s, (sjoinsappends_[1]svaluesvssqlreprsdb(svaluesdbs_[1]sv((s2build/bdist.linux-i686/egg/sqlobject/converters.pysSequenceConverterss struct_timecCstid|SdS(Ns'%Y-%m-%d %H:%M:%S'(stimesstrftimesvalue(svaluesdb((s2build/bdist.linux-i686/egg/sqlobject/converters.pysStructTimeConverterscCs0d|i|i|i|i|i|ifSdS(Ns'%4d-%02d-%02d %02d:%02d:%02d'(svaluesyearsmonthsdayshoursminutessecond(svaluesdb((s2build/bdist.linux-i686/egg/sqlobject/converters.pysDateTimeConverterscCsd|i|i|ifSdS(Ns'%4d-%02d-%02d'(svaluesyearsmonthsday(svaluesdb((s2build/bdist.linux-i686/egg/sqlobject/converters.pys DateConverterscCsd|i|i|ifSdS(Ns'%02d:%02d:%02d'(svalueshoursminutessecond(svaluesdb((s2build/bdist.linux-i686/egg/sqlobject/converters.pys TimeConverterscCs|iSdS(N(svalues to_eng_string(svaluesdb((s2build/bdist.linux-i686/egg/sqlobject/converters.pysDecimalConverterscCszy |i}Wn\tj oPt|}|tjo#tdt|t |fn|||Sn X||SdS(Ns#Unknown SQL builtin type: %s for %s( sobjs __sqlrepr__sreprFuncsAttributeErrorslookupConverters convertersNones ValueErrorstypesreprsdb(sobjsdbs convertersreprFunc((s2build/bdist.linux-i686/egg/sqlobject/converters.pyssqlreprs   #(5sarraysmx.DateTime.ISOsmxsDateTimesISOsstrGMTs origISOStrs mx.DateTimes DateTimeTypesDateTimeDeltaTypes ImportErrors DateTime.ISOsNonestimesdatetimesSybases NumericTypestypesobjectsBOOLsTRUEsFALSEstypess InstanceTypes ClassTypesTypeTypesdecimalsDecimalssqlStringReplacesisoStrsConverterRegistrys converterssregisterConverterslookupConverters array_typesbuffers buffer_typesStringLikeConverters IntConverters LongConverters BoolConvertersFloatConvertersDateTimeConverters TimeConverters NoneConvertersSequenceConvertershasattrsStructTimeConverters struct_times DateConvertersdatesDecimalConverterssqlrepr(&s TimeConvertersStringLikeConverters DateConvertersSequenceConvertersDateTimesSybasesarraysTRUEssqlreprs LongConverters NumericTypesTypeTypesDateTimeConverters origISOStrsisoStrs InstanceTypesDateTimeDeltaTypessqlStringReplacesDecimalsConverterRegistrys NoneConvertersDecimalConverters array_types BoolConvertersdatetimes IntConvertersFALSEs buffer_typesregisterConverters ClassTypeslookupConverters converterss DateTimeTypesBOOLstimesFloatConvertersmxsStructTimeConverter((s2build/bdist.linux-i686/egg/sqlobject/converters.pys?s              E                     PKb95K,sqlobject/classregistry.pyc; Ec@sTdZdefdYZdefdYZeZeiZedZdS(s classresolver.py 2 February 2004, Ian Bicking Resolves strings to classes, and runs callbacks when referenced classes are created. Classes are referred to only by name, not by module. So that identically-named classes can coexist, classes are put into individual registries, which are keyed on strings (names). These registries are created on demand. Use like:: >>> import classregistry >>> registry = classregistry.registry('MyModules') >>> def afterMyClassExists(cls): ... print 'Class finally exists:', cls >>> registry.addClassCallback('MyClass', afterMyClassExists) >>> class MyClass: ... pass >>> registry.addClass(MyClass) Class finally exists: MyClass s ClassRegistrycBsDtZdZdZdZdZdZdZdZRS(s We'll be dealing with classes that reference each other, so class C1 may reference C2 (in a join), while C2 references C1 right back. Since classes are created in an order, there will be a point when C1 exists but C2 doesn't. So we deal with classes by name, and after each class is created we try to fix up any references by replacing the names with actual classes. Here we keep a dictionaries of class names to classes -- note that the classes might be spread among different modules, so since we pile them together names need to be globally unique, to just module unique. Like needSet below, the container dictionary is keyed by the class registry. cCs(||_h|_h|_g|_dS(N(snamesselfsclassess callbackssgenericCallbacks(sselfsname((s5build/bdist.linux-i686/egg/sqlobject/classregistry.pys__init__-s   cOsW|ii|o||i|||n&|ii|gi |||fdS(s Whenever a name is substituted for the class, you can register a callback that will be called when the needed class is created. If it's already been created, the callback will be called immediately. N( sselfsclassesshas_keys classNamescallbacksargsskws callbackss setdefaultsappend(sselfs classNamescallbacksargsskw((s5build/bdist.linux-i686/egg/sqlobject/classregistry.pysaddClassCallback3scOsG|ii|||fx'|iiD]}||||q)WdS(sr This callback is called for all classes, not just specific ones (like addClassCallback). N( sselfsgenericCallbackssappendscallbacksargsskwsclassessvaluesscls(sselfscallbacksargsskwscls((s5build/bdist.linux-i686/egg/sqlobject/classregistry.pys addCallback?s c Cs0|i|ijodk}|i|i}td|i||it|i i |idd||it|i i |iddfn||i|i<|i i |ioEx1|i |iD]\}}}||||qW|i |i=nx*|iD]\}}}||||q WdS(s Everytime a class is created, we add it to the registry, so that other classes can find it by name. We also call any callbacks that are waiting for the class. Nsclass %s is already in the registry (other class is %r, from the module %s in %s; attempted new class is %r, from the module %s in %s)s__file__s (unknown)(sclss__name__sselfsclassesssyssothers ValueErrors __module__sgetattrsmodulessgets callbacksshas_keyscallbacksargsskwsgenericCallbacks(sselfsclssargsssysscallbacksotherskw((s5build/bdist.linux-i686/egg/sqlobject/classregistry.pysaddClassHs  *' cCsny|i|SWnXtj oL|ii}|itd||ipddi|fnXdS(Ns>No class %s found in the registry %s (these classes exist: %s)s [default]s, ( sselfsclassess classNamesKeyErrorskeyssallssortsnamesjoin(sselfs classNamesall((s5build/bdist.linux-i686/egg/sqlobject/classregistry.pysgetClassds  cCs|iiSdS(N(sselfsclassessvalues(sself((s5build/bdist.linux-i686/egg/sqlobject/classregistry.pys allClassesos( s__name__s __module__s__doc__s__init__saddClassCallbacks addCallbacksaddClasssgetClasss allClasses(((s5build/bdist.linux-i686/egg/sqlobject/classregistry.pys ClassRegistrys    s_MasterRegistrycBs tZdZdZdZRS(s3 This singleton holds all the class registries. There can be multiple registries to hold different unrelated sets of classes that reside in the same process. These registries are named with strings, and are created on demand. The MasterRegistry module global holds the singleton. cCs h|_dS(N(sselfs registries(sself((s5build/bdist.linux-i686/egg/sqlobject/classregistry.pys__init__{scCs:|ii| ot||i|W|id|i|_Wd|ii XdS(s Runs through the cache and expires objects. E.g., if ``cullFraction`` is 3, then every third object is moved to the 'expired' (aka weakref) cache. iN(sselfslocksacquirescacheskeyssxranges cullOffsetslens cullFractionsisidsrefs expiredCachesrelease(sselfskeyssisid((s-build/bdist.linux-i686/egg/sqlobject/cache.pysculls  cCs,|io|iin|iidS(ss Removes everything from the cache. Warning! This can cause duplicate objects in memory. N(sselfsdoCachescachesclears expiredCache(sself((s-build/bdist.linux-i686/egg/sqlobject/cache.pysclears cCs{|i odSn|iizF|ii|o|i|=n|ii|o|i|=nWd|iiXdS(s Expires a single object. Typically called after a delete. Doesn't even keep a weakref. (@@: bad name?) N( sselfsdoCacheslocksacquirescacheshas_keysids expiredCachesrelease(sselfsid((s-build/bdist.linux-i686/egg/sqlobject/cache.pysexpires  cCsu|i odSn|iiz@x0|iiD]\}}t||i | Returns the IDs of all objects in the cache. N( sselfsdoCachescacheskeyssalls expiredCachesitemssidsvaluesappend(sselfsallsvaluesid((s-build/bdist.linux-i686/egg/sqlobject/cache.pysallIDss   (s__name__s __module__s__doc__sTrues__init__stryGetsgetsputs finishPutscreatedscullsclearsexpires expireAllsallIDs(((s-build/bdist.linux-i686/egg/sqlobject/cache.pys CacheFactorys  M    sCacheSetcBs}tZdZdZdZdZdZdZdZe dZ dZ d Z d Z d Zd ZRS( s- A CacheSet is used to collect and maintain a series of caches. In SQLObject, there is one CacheSet per connection, and one Cache in the CacheSet for each class, since IDs are not unique across classes. It contains methods similar to Cache, but that take a ``cls`` argument. cOsh|_||_||_dS(N(sselfscachessargsskw(sselfsargsskw((s-build/bdist.linux-i686/egg/sqlobject/cache.pys__init__s  cCsky|i|ii|SWnItj o=t|i|i |i|i<|i|ii|SnXdS(N( sselfscachessclss__name__sgetsidsKeyErrors CacheFactorysargsskw(sselfsidscls((s-build/bdist.linux-i686/egg/sqlobject/cache.pysgets cCs|i|ii||dS(N(sselfscachessclss__name__sputsidsobj(sselfsidsclssobj((s-build/bdist.linux-i686/egg/sqlobject/cache.pysput scCs|i|iidS(N(sselfscachessclss__name__s finishPut(sselfscls((s-build/bdist.linux-i686/egg/sqlobject/cache.pys finishPutscCsqy|i|ii||WnLtj o@t|i |i |i|i<|i|ii||nXdS(N( sselfscachessclss__name__screatedsidsobjsKeyErrors CacheFactorysargsskw(sselfsidsclssobj((s-build/bdist.linux-i686/egg/sqlobject/cache.pyscreateds cCs5y|i|ii|Wntj onXdS(N(sselfscachessclss__name__sexpiresidsKeyError(sselfsidscls((s-build/bdist.linux-i686/egg/sqlobject/cache.pysexpirescCsg|tjo(xS|iiD]}|iqWn/|ii|io|i|iindS(N( sclssNonesselfscachessvaluesscachesclearshas_keys__name__(sselfsclsscache((s-build/bdist.linux-i686/egg/sqlobject/cache.pysclear s  cCs|i||iSdS(N(sselfs tryGetByNamesidsclss__name__(sselfsidscls((s-build/bdist.linux-i686/egg/sqlobject/cache.pystryGet'scCs6y|i|i|SWntj o tSnXdS(N(sselfscachessclsnamestryGetsidsKeyErrorsNone(sselfsidsclsname((s-build/bdist.linux-i686/egg/sqlobject/cache.pys tryGetByName*scCs6y|i|iiWntj o gSnXdS(N(sselfscachessclss__name__sallIDssKeyError(sselfscls((s-build/bdist.linux-i686/egg/sqlobject/cache.pysallIDs0scCs|iiSdS(N(sselfscachessvalues(sself((s-build/bdist.linux-i686/egg/sqlobject/cache.pys allSubCaches6scCs |iSdS(N(sselfscaches(sself((s-build/bdist.linux-i686/egg/sqlobject/cache.pysallSubCachesByClassNames9s(s__name__s __module__s__doc__s__init__sgetsputs finishPutscreatedsexpiresNonesclearstryGets tryGetByNamesallIDss allSubCachessallSubCachesByClassNames(((s-build/bdist.linux-i686/egg/sqlobject/cache.pysCacheSets            ( s__doc__s threadingsweakrefsrefstimesnowsTruesFalsesobjects CacheFactorysCacheSet(sFalsesrefs threadingsCacheSets CacheFactorysnowsTrue((s-build/bdist.linux-i686/egg/sqlobject/cache.pys?s    PKb95xsqlobject/dbconnection.pyc; Ec@sdklZddjddjf\ZZdkZdklZdkZdk Z dk Z dk Z dk Z dk Z dkZdkZdkZdkZdklZdkZeiZdkZdklZdklZdkZe idd hZd Zd fd YZd e fdYZ!de fdYZ"defdYZ#de fdYZ$de fdYZ%de fdYZ&de fdYZ'e'Z(e(i)Z)e(i*Z*e(i+Z+dS((s generatorsiiN(slocal(sCacheSet(ssorter(ssqlreprsignores&DB-API extension cursor.lastrowid usedcCs(|}|tj o|indS(N(srefsconnsNonesclose(srefsconn((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pys_closeConnections  s DBConnectionc BsztZeeeeeeeedZdZdZeeZdZ ee Z dZ e e Z dZ RS(Nc Cs||_||_||_||_td||_||_||_h|_ d|_ ||_ |pt |_ ti |i i|it|titti|dS(Nscachei(snamesselfsdebugs debugOutputsdebugThreadingsCacheSetscachesdoCachesstyles_connectionNumberss_connectionCounts autoCommitsregistrysNones classregistrys addCallbacks soClassAddedsregisterConnectionInstancesatexitsregisters_closeConnectionsweakrefsref( sselfsnamesdebugs debugOutputscachesstyles autoCommitsdebugThreadingsregistry((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pys__init__$s          cCst|dtpd}|o-|io|d|i}n|d}nt|dt p tdd|i|f}|io||i7}n|d7}|i }|i dot d }n||SdS( Nsuserss:s@spasswords/URIs cannot express passwords without usernamess%s://%ss/i( sgetattrsselfsNonesauthspasswordsAssertionErrorsdbNamesurishostsdbs startswithspath(sselfsdbsurisauth((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pysuri7s    cCs tdS(N(sNotImplemented(scls((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pys isSupportedIscCs tdS(N(sNotImplemented(sclssuri((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pysconnectionFromURIMscCs |idd\} }|idptd||ido|id ot}|d}nm|idot}|d}nI|d}|idd jo|}d }n|idd\}}|o|id d jof||i d  }||i d d}|idd jo|idd\}} qdt} n t}} |o|idd jo|id\}} yt| } Wn tj otd | nXd| jo d jn otd| n|}nt} d|}tidjoDt|djo|ddjod|d|df}qgnh}|idd jom|idd\}}|id}xC|D]7} | idd\} }ti|}||| (sselfs_methods _connection(sself((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pys__repr__s(s__name__s __module__s__init__s __getattr__s__call__s__repr__(((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pysConnMethodWrappers   sDBAPIcBstZdZeZdZdZdZedZ ddZ dZ dZ d Z d Zd Zd Zd ZdZdZdZdZdZdZdZdZdZdZdddZdZdZdZdZ dZ!dZ"d Z#d!Z$d"Z%ed#Z&d$Z'd%Z(d&Z)d'Z*d(Z+d)Z,d*Z-d+Z.d,Z/d-Z0d.Z1d/Z2d0Z3d1Z4d2Z5RS(3s Subclass must define a `makeConnection()` method, which returns a newly-created connection object. ``queryInsertID`` must also be defined. cKsGg|_ti|_ti||t|i i d|_ dS(Ns( sselfs_pools threadingsLocks _poolLocks DBConnections__init__skwstypesmodulesBinarys _binaryType(sselfskw((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pys__init__s cGs8|i}z|||}Wd|i|X|SdS(N(sselfs getConnectionsconnsmethsargssvalsreleaseConnection(sselfsmethsargssconnsval((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pys_runWithConnections  c Cs|iiz|i o5|i}|i|it|<|id7_n|ii }|i od}|it j oR|ddi gi}|iD]#}|t|it|q~7}n|i||dn|SWd|iiXdS(NisACQUIREs pool=[%s]s, sPool(sselfs _poolLocksacquires_poolsmakeConnectionsconns_connectionCounts_connectionNumberssidspopsdebugsssNonesjoinsappends_[1]svsstrs printDebugsrelease(sselfs_[1]sssvsconn((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pys getConnections    Rc Cs|io|o d}nd|i}|itjo|d7}nO|ddigi}|iD]#}|t |i t |qc~7}|i||dn|io| o|idjo8|io|i|dd n|itd q|ioG|io|i|d d nt|d t o|iqq|io|i|d d n|in|itj o+||ijo|iid|qn |idS(NsRELEASE (explicit)s!RELEASE (implicit, autocommit=%s)s no poolings pool=[%s]s, sPools exceptionsauto/exceptionsROLLBACKsMObject used outside of a transaction; implicit COMMIT or ROLLBACK not allowedsautosCOMMITs autocommiti(sselfsdebugsexplicitsss autoCommits_poolsNonesjoinsappends_[1]svsstrs_connectionNumberssids printDebugsconnssupportTransactionssrollbacks ExceptionsgetattrsFalsescommitsinsertsclose(sselfsconnsexplicits_[1]sssv((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pysreleaseConnections4   N      squeryc Cs|djo |idjodSn|djo d}nd}t|}|it|}ddt |}|i o2tii}d|ddt |}nd}d tGHdS( NsPoolsquerys: s->s is:ss4%(n)2i%(threadName)s/%(name)s%(spaces)s%(sep)s %(s)s(snamesselfsdebugstypessepsreprsss_connectionNumberssidsconnsnslensspacessdebugThreadings threadings currentThreadsgetNames threadNameslocals( sselfsconnsssnamestypesseps threadNamesnsspaces((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pys printDebugs     cCs2|io|i||dn|i|SdS(NsQueryR(sselfsdebugs printDebugsconnsqueryscursorsexecute(sselfsconnscursorsquery((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pys _executeRetry(s cCs>|io|i||dn|i||i|dS(NsQuery(sselfsdebugs printDebugsconnsss _executeRetryscursor(sselfsconnss((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pys_query-s cCs|i|i|SdS(N(sselfs_runWithConnections_queryss(sselfss((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pysquery2scCsx|io|i||dn|i}|i||||i}|i o|i||ddn|SdS(NsQueryAllsresult( sselfsdebugs printDebugsconnssscursorscs _executeRetrysfetchallsvalues debugOutput(sselfsconnssscsvalue((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pys _queryAll5s    cCs|i|i|SdS(N(sselfs_runWithConnections _queryAllss(sselfss((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pysqueryAll?scCs|io|i||dn|i}|i||||i}|i o|i||ddn|i |fSdS(s Like queryAll, but returns (description, rows), where the description is cursor.description (which gives row types) s QueryAllDescsQueryAllsresultN( sselfsdebugs printDebugsconnssscursorscs _executeRetrysfetchallsvalues debugOutputs description(sselfsconnssscsvalue((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pys_queryAllDescriptionBs    cCs|i|i|SdS(N(sselfs_runWithConnections_queryAllDescriptionss(sselfss((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pysqueryAllDescriptionPscCsx|io|i||dn|i}|i||||i}|i o|i||ddn|SdS(NsQueryOnesresult( sselfsdebugs printDebugsconnssscursorscs _executeRetrysfetchonesvalues debugOutput(sselfsconnssscsvalue((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pys _queryOneSs    cCs|i|i|SdS(N(sselfs_runWithConnections _queryOness(sselfss((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pysqueryOne]sc CsQd|di|digi}|D]}||i|q&~fSdS(NsINSERT INTO %s (%s) VALUES (%s)s, ( stablesjoinsnamessappends_[1]svaluessvsselfssqlrepr(sselfstablesnamessvaluess_[1]sv((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pys _insertSQL`scCst|SdS(N(s Transactionsself(sself((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pys transactionescCs |i|i||||SdS(N(sselfs_runWithConnections_queryInsertIDs soInstancesidsnamessvalues(sselfs soInstancesidsnamessvalues((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pys queryInsertIDhscCs#|i||i|dtSdS(NskeepConnection(sselectsIterationClasssselfs getConnectionsFalse(sselfsselect((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pys iterSelectksc Gs |i}|id}|o|i|}n |i}ddigi}|D]} |t | qR~}|ddi|7}|o||i ||7}n|d7}|i||dddd}|i|}t|d jo|d}n|Sd S( so Apply an accumulate function(s) (SUM, COUNT, MIN, AVG, MAX, etc...) to the select object. sjoins SELECT %ss, s FROM %ss WHEREslimitisorderiN(sselectsopssgetsjoinsselfs_fixTablesForJoinsstablessappends_[1]s expressionss expressionsstrsqs _addJoinss_addWhereClausesqueryOnesvalslen( sselfsselects expressionsstablessjoinsvalsopssqs_[1]s expression((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pysaccumulateSelectos   : c Cs|i}|id}|i} |o|i|}n |i}|idt o d}nd}|iddo0|d| i i | i i di|f7}ndigi}| i iD]#}|d | i i |ifq~}|o3|d | i i | i i |di|f7}n-|d| i i | i i di|f7}|o||i||7}n|d 7}|i||SdS( NsjoinsdistinctsSELECT DISTINCT sSELECT s lazyColumnsis %s.%s FROM %ss, s%s.%ss%s.%s, %s FROM %ss WHERE(sselectsopssgetsjoins sourceClasssclssselfs_fixTablesForJoinsstablessFalsesqssqlmetastablesidNamesappends_[1]s columnListscolsdbNamescolumnss _addJoinss_addWhereClause( sselfsselectstablessjoinsopssqs_[1]scolumnsscolscls((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pysqueryForSelects&    0I3, cCs|i}|id}|i}t|tjo|Sn|}t|ti oL|i |jo|i |i n|i |jo|i |i qnZxV|D]N}|i |jo|i |i n|i |jo|i |i qqW|SdS(Nsjoin(sselectsopssgetsjoinstablesstypesstrs isinstances sqlbuildersSQLJoinstable1sremovestable2sj(sselfsselectstablessjoinsopssj((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pys_fixTablesForJoinss$  cCs|i}|id}t|tjod|}nt|ti o8|o|i o d}nd}||i |7}nPd}xF|D]>}|o|i o d}nd}|||i |7}qW|SdS(Nsjoins s, s(sselectsopssgetsjoinstypesstrsjoin_strs isinstances sqlbuildersSQLJoinstablesstable1sselfssqlreprsjssep(sselfsselectstablessjoin_strsjoinsopssjssep((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pys _addJoinss"   ic si}t|tdtdgjoi|}ni}td} d|o |i do-d|| |d|i dtf}n|i dd }|i d t }|d |}|o |p|oi|||}n|SdS( Nsucst|tgtffjo |g}ngi}|D]}||q@~}|o4gi}|D]}|ti|qt~}ndi gi}|D]}|i |q~SdS(Ns, ( stypeslstsappends_[1]sis clauseQuotesdescs sqlbuildersDESCsjoinsselfssqlrepr(slstsdescsis_[1](sselfs clauseQuote(s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pys clauseLists % -4cst|tdjo|idot}|d}nt}ti|ptd||i i i joi i i |i }n|otiti|Sqti|Sn|SdS(Nss-isDStrings in clauses are expected to be column identifiers. I got: %r(stypesss startswithsTruesdescsFalses sqlbuilders sqlIdentifiersAssertionErrorsselects sourceClassssqlmetascolumnssdbNamesDESCs SQLConstant(sssdesc(sselect(s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pys clauseQuotess dbOrderBys%s ORDER BY %ssreversedsstartisends (sselectsclausesqstypesselfssqlreprsopssFalses clauseLists clauseQuotesordersgetsstartsNonesends startSelectslimits_queryAddLimitOffset( sselfsselects startSelectslimitsordersendsopssqsstarts clauseQuotes clauseList((sselfsselects clauseQuotes4build/bdist.linux-i686/egg/sqlobject/dbconnection.pys_addWhereClauses %  -cCs|i|i|dS(N(sselfsquerys_SO_createJoinTableSQLsjoin(sselfsjoin((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pys_SO_createJoinTablescCs6d|i|i|i||i|i|fSdS(Ns CREATE TABLE %s ( %s %s, %s %s )(sjoinsintermediateTables joinColumnsselfs joinSQLTypes otherColumn(sselfsjoin((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pys_SO_createJoinTableSQLscCs|id|idS(Ns DROP TABLE %s(sselfsquerysjoinsintermediateTable(sselfsjoin((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pys_SO_dropJoinTablescCs|i|i||dS(N(sselfsqueryscreateIndexSQLssoClasssindex(sselfssoClasssindex((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pys_SO_createIndex scCsdp tddS(NisImplement in subclasses(sAssertionError(sselfssoClasssindex((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pyscreateIndexSQL scCs|i|i|dS(N(sselfsqueryscreateTableSQLssoClass(sselfssoClass((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pys createTablescCs!d|ii|i|fSdS(NsCREATE TABLE %s ( %s )(ssoClassssqlmetastablesselfs createColumns(sselfssoClass((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pyscreateTableSQLscCs|i|ggi}|iiD]}||i||q#~}di gi}|D]}|d|q]~SdS(Ns, s %s( sselfscreateIDColumnssoClasssappends_[1]ssqlmetas columnListscols createColumns columnDefssjoinsc(sselfssoClassscs_[1]s columnDefsscol((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pys createColumnssIcCsdp tddS(NisImplement in subclasses(sAssertionError(sselfssoClassscol((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pys createColumnscCs|id|dS(Ns DROP TABLE %s(sselfsquerys tableName(sselfs tableNamescascade((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pys dropTablescCs|id|dS(NsDELETE FROM %s(sselfsquerys tableName(sselfs tableName((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pys clearTable"scCs|ii|SdS(sH Create a binary object wrapper for the given database. N(sselfsmodulesBinarysvalue(sselfsvalue((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pys createBinary)sc Cs||id|iidigi}|D])\}}|d||i |fq&~|ii |i |i fdS(Ns UPDATE %s SET %s WHERE %s = (%s)s, s %s = (%s)(sselfsqueryssossqlmetastablesjoinsappends_[1]svaluessdbNamesvaluessqlreprsidNamesid(sselfssosvaluessvalues_[1]sdbName((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pys _SO_update6scCsdi|}|o9|id||ii|ii|i |i fSn3|id|ii|ii|i |i fSdS(Ns, s!SELECT %s FROM %s WHERE %s = (%s)s#SELECT NULL FROM %s WHERE %s = (%s)( sjoins columnNamesscolumnssselfsqueryOnessossqlmetastablesidNamessqlreprsid(sselfssos columnNamesscolumns((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pys _SO_selectOne>s9cCs9|iddi||ii||i|fSdS(NsSELECT %s FROM %s WHERE %s = %ss, ( sselfsqueryOnesjoins columnNamessclsssqlmetastablescolumnssqlreprsvalue(sselfsclss columnNamesscolumnsvalue((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pys_SO_selectOneAltNscCs6|id|ii|ii|i|ifdS(NsDELETE FROM %s WHERE %s = (%s)(sselfsqueryssossqlmetastablesidNamessqlreprsid(sselfsso((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pys _SO_deleteUscCs6|id|ii|ii||i|fSdS(Ns!SELECT %s FROM %s WHERE %s = (%s)( sselfsqueryAllssoClassssqlmetasidNamestablescolumnssqlreprsvalue(sselfssoClassscolumnsvalue((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pys_SO_selectJoin[scCs*|id||||i|fSdS(Ns!SELECT %s FROM %s WHERE %s = (%s)(sselfsqueryAlls getColumnstables joinColumnssqlreprsvalue(sselfstables getColumns joinColumnsvalue((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pys_SO_intermediateJoinbscCs6|id|||i|||i|fdS(Ns,DELETE FROM %s WHERE %s = (%s) AND %s = (%s)(sselfsquerystables firstColumnssqlreprs firstValues secondColumns secondValue(sselfstables firstColumns firstValues secondColumns secondValue((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pys_SO_intermediateDeleteiscCs6|id||||i||i|fdS(Ns'INSERT INTO %s (%s, %s) VALUES (%s, %s)(sselfsquerystables firstColumns secondColumnssqlreprs firstValues secondValue(sselfstables firstColumns firstValues secondColumns secondValue((s4build/bdist.linux-i686/egg/sqlobject/dbconnection.pys_SO_intermediateInsertrsc Csqhtd<}h} d|jot|d| |iiZ4d?efd@YZ5e e5edAefdBYZ6e e6edCe5fdDYZ7e e7edEefdFYZ8dGZ9dHZ:dIZ;dJZ<dKZ=dLZ>dMZ?dNZ@dOZAdPZBdQZCdRfdSYZDdTefdUYZEe eEedVZFdWZGdXZHdYZIdZZJd[ZKd\ZLd]ZMd^ZNd_ZOd`ZPdaZQdbZRdcZSddZTdeZUdfZVdgeEfdhYZWe eWeeXeXdiZYeXeXdjZZeXeXdkZ[eXeXdlZ\eXeXdmZ]eXeXdnZ^eXeXdoZ_dpeWfdqYZ`e e`edreWfdsYZae eaedtZbduZcdvZddwZedxZfdyZgdzZhd{Zid|Zjd}Zkd~ZldZmdZndZode(fdYZpde+fdYZqdfdYZrdefdYZsdesfdYZtdefdYZudeufdYZvdefdYZwdZxdZydZzdZ{dZ|e-Z}e.Z~e~ZedjoWdZxNeidD]9Zei oqneidoedZqqWndS(sd sqlobject.sqlbuilder -------------------- :author: Ian Bicking Builds SQL expressions from normal Python expressions. Disclaimer ---------- This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Instructions ------------ To begin a SQL expression, you must use some sort of SQL object -- a field, table, or SQL statement (``SELECT``, ``INSERT``, etc.) You can then use normal operators, with the exception of: `and`, `or`, `not`, and `in`. You can use the `AND`, `OR`, `NOT`, and `IN` functions instead, or you can also use `&`, `|`, and `~` for `and`, `or`, and `not` respectively (however -- the precidence for these operators doesn't work as you would want, so you must use many parenthesis). To create a sql field, table, or constant/function, use the namespaces `table`, `const`, and `func`. For instance, ``table.address`` refers to the ``address`` table, and ``table.address.state`` refers to the ``state`` field in the address table. ``const.NULL`` is the ``NULL`` SQL constant, and ``func.NOW()`` is the ``NOW()`` function call (`const` and `func` are actually identicle, but the two names are provided for clarity). Once you create this object, expressions formed with it will produce SQL statements. The ``sqlrepr(obj)`` function gets the SQL representation of these objects, as well as the proper SQL representation of basic Python types (None==NULL). There are a number of DB-specific SQL features that this does not implement. There are a bunch of normal ANSI features also not present -- particularly left joins, among others. You may wish to only use this to generate ``WHERE`` clauses. See the bottom of this module for some examples, and run it (i.e. ``python sql.py``) to see the results of those examples. s VersionErrorcBstZRS(N(s__name__s __module__(((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys VersionErrorAss NoDefaultcBstZRS(N(s__name__s __module__(((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys NoDefaultCsiiN(ssqlreprsregisterConvertersTRUEsFALSEs^[a-zA-Z_][a-zA-Z0-9_\.]*$cCs2t|tdjoti|i SdS(Ns(stypesobjs safeSQLREssearchsstrip(sobj((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys sqlIdentifierNscCs)t|do|i|Sn|SdS(Nsexecute(shasattrsexprsexecutesexecutor(sexprsexecutor((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysexecuteRss SQLExpressioncBs^tZdZdZdZdZdZdZdZdZ d Z d Z d Z d Z d ZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZ d Z!d!Z"d"Z#d#Z$d$Z%d%Z&d&Z'RS('NcCstd||SdS(Ns+(sSQLOpsselfsother(sselfsother((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__add__]scCstd||SdS(Ns+(sSQLOpsothersself(sselfsother((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__radd___scCstd||SdS(Ns-(sSQLOpsselfsother(sselfsother((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__sub__ascCstd||SdS(Ns-(sSQLOpsothersself(sselfsother((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__rsub__cscCstd||SdS(Ns*(sSQLOpsselfsother(sselfsother((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__mul__escCstd||SdS(Ns*(sSQLOpsothersself(sselfsother((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__rmul__gscCstd||SdS(Ns/(sSQLOpsselfsother(sselfsother((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__div__iscCstd||SdS(Ns/(sSQLOpsothersself(sselfsother((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__rdiv__kscCstd|SdS(Ns+(s SQLPrefixsself(sself((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__pos__mscCstd|SdS(Ns-(s SQLPrefixsself(sself((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__neg__oscCstd||SdS(NsPOW(s SQLConstantsselfsother(sselfsother((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__pow__qscCstd||SdS(NsPOW(s SQLConstantsothersself(sselfsother((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__rpow__sscCstd|SdS(NsABS(s SQLConstantsself(sself((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__abs__uscCstd||SdS(NsMOD(s SQLConstantsselfsother(sselfsother((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__mod__wscCstd||SdS(NsMOD(s SQLConstantsothersself(sselfsother((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__rmod__yscCstd||SdS(Ns<(sSQLOpsselfsother(sselfsother((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__lt__|scCstd||SdS(Ns<=(sSQLOpsselfsother(sselfsother((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__le__~scCstd||SdS(Ns>(sSQLOpsselfsother(sselfsother((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__gt__scCstd||SdS(Ns>=(sSQLOpsselfsother(sselfsother((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__ge__scCs/|tjot|Sntd||SdS(Ns=(sothersNonesISNULLsselfsSQLOp(sselfsother((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__eq__s cCs/|tjot|Sntd||SdS(Ns<>(sothersNones ISNOTNULLsselfsSQLOp(sselfsother((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__ne__s cCstd||SdS(NsAND(sSQLOpsselfsother(sselfsother((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__and__scCstd||SdS(NsAND(sSQLOpsothersself(sselfsother((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__rand__scCstd||SdS(NsOR(sSQLOpsselfsother(sselfsother((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__or__scCstd||SdS(NsOR(sSQLOpsothersself(sselfsother((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__ror__scCstd|SdS(NsNOT(s SQLPrefixsself(sself((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys __invert__scGst||SdS(N(sSQLCallsselfsargs(sselfsargs((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__call__scCsOy|itSWn7tj o+d|iitt|dfSnXdS(Ns<%s %s>i(sselfs __sqlrepr__sNonesAssertionErrors __class__s__name__shexsid(sself((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__repr__scCst|SdS(N(sreprsself(sself((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__str__scCs tddS(NsPython 2.1+ required(s VersionError(sselfsother((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__cmp__scCs tddS(NsPython 2.1+ required(s VersionError(sselfsother((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__rcmp__scCst||SdS(N(s STARTSWITHsselfss(sselfss((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys startswithscCst||SdS(N(sENDSWITHsselfss(sselfss((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysendswithscCst||SdS(N(sCONTAINSSTRINGsselfss(sselfss((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pyscontainsscCsgSdS(N((sself((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys componentsscCs|iiSdS(N(sselfstablesUsedDictskeys(sself((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys tablesUsedscCsYh}x|iD]}d||=s>sINsISsSQLOpcBs,tZdZdZdZdZRS(NcCs%|i|_||_||_dS(N(sopsuppersselfsexpr1sexpr2(sselfsopsexpr1sexpr2((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__init__s cCst|i|}t|i|}|ddjo |djod|d}n|ddjo |djod|d}nd||i|fSdS(Nis(sNULLs)s (%s %s %s)(ssqlreprsselfsexpr1sdbss1sexpr2ss2sop(sselfsdbss2ss1((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys __sqlrepr__scCs|i|igSdS(N(sselfsexpr1sexpr2(sself((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys componentsscCs|idjo't|i|ot|i|Snj|idjo't|i|pt|i|Sn3t|iit|i|t|i|SdS(NsANDsOR(sselfsopsexecutesexpr1sexecutorsexpr2s operatorMapsupper(sselfsexecutor((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysexecutes ''(s__name__s __module__s__init__s __sqlrepr__s componentssexecute(((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysSQLOps   sSQLCallcBs,tZdZdZdZdZRS(NcCs||_||_dS(N(sexprsselfsargs(sselfsexprsargs((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__init__s cCs*dt|i|t|i|fSdS(Ns%s%s(ssqlreprsselfsexprsdbsargs(sselfsdb((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys __sqlrepr__scCs|igt|iSdS(N(sselfsexprslistsargs(sself((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys componentsscCs tddS(Ns1I don't yet know how to locally execute functions(s ValueError(sselfsexecutor((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysexecutes(s__name__s __module__s__init__s __sqlrepr__s componentssexecute(((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysSQLCalls   s SQLPrefixcBs,tZdZdZdZdZRS(NcCs||_||_dS(N(sprefixsselfsexpr(sselfsprefixsexpr((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__init__ s cCs!d|it|i|fSdS(Ns%s %s(sselfsprefixssqlreprsexprsdb(sselfsdb((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys __sqlrepr__ scCs|igSdS(N(sselfsexpr(sself((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys componentsscCs]t|i|}tdjo|Sn3tdjo | Sntidjo | SndS(Ns+s-sNOT(sexecutesselfsexprsexecutorsprefixsupper(sselfsexecutorsexpr((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysexecutes   (s__name__s __module__s__init__s __sqlrepr__s componentssexecute(((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys SQLPrefix s   s SQLConstantcBs#tZdZdZdZRS(NcCs ||_dS(N(sconstsself(sselfsconst((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__init__scCs |iSdS(N(sselfsconst(sselfsdb((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys __sqlrepr__scCs tddS(Ns-I don't yet know how to execute SQL constants(s ValueError(sselfsexecutor((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysexecute!s(s__name__s __module__s__init__s __sqlrepr__sexecute(((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys SQLConstants  sSQLTrueClauseClasscBstZdZdZRS(NcCsdSdS(Ns1 = 1((sselfsdb((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys __sqlrepr__'scCsdSdS(Ni((sselfsexecutor((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysexecute)s(s__name__s __module__s __sqlrepr__sexecute(((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysSQLTrueClauseClass&s sFieldcBs,tZdZdZdZdZRS(NcCs||_||_dS(N(s tableNamesselfs fieldName(sselfs tableNames fieldName((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__init__5s cCs|id|iSdS(Ns.(sselfs tableNames fieldName(sselfsdb((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys __sqlrepr__8scCs|igSdS(N(sselfs tableName(sself((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pystablesUsedImmediate:scCs|i|i|iSdS(N(sexecutorsfieldsselfs tableNames fieldName(sselfsexecutor((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysexecute<s(s__name__s __module__s__init__s __sqlrepr__stablesUsedImmediatesexecute(((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysField4s   sSQLObjectFieldcBstZdZRS(NcCs ||_ti|||dS(N(soriginalsselfsFields__init__s tableNames fieldName(sselfs tableNames fieldNamesoriginal((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__init__@s (s__name__s __module__s__init__(((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysSQLObjectField?ss UnicodeFieldcBs#tZdZdZdZRS(NcCs#ti||||||_dS(N(sSQLObjectFields__init__sselfs tableNames fieldNamesoriginalscolumn(sselfs tableNames fieldNamesoriginalscolumn((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__init__HscCs=t|to|i|ii}ntd||SdS(Ns=(s isinstancesothersunicodesencodesselfscolumns dbEncodingsSQLOp(sselfsother((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__eq__KscCs=t|to|i|ii}ntd||SdS(Ns<>(s isinstancesothersunicodesencodesselfscolumns dbEncodingsSQLOp(sselfsother((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__ne__Os(s__name__s __module__s__init__s__eq__s__ne__(((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys UnicodeFieldGs  sTablecBs2tZeZdZdZdZdZRS(NcCs ||_dS(N(s tableNamesself(sselfs tableName((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__init__ZscCs1|ido tn|i|i|SdS(Ns__(sattrs startswithsAttributeErrorsselfs FieldClasss tableName(sselfsattr((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys __getattr__\s cCst|iSdS(N(sstrsselfs tableName(sselfsdb((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys __sqlrepr__`scCs tddS(NsTables don't have values(s ValueError(sselfsexecutor((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysexecutebs(s__name__s __module__sFields FieldClasss__init__s __getattr__s __sqlrepr__sexecute(((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysTableWs    sSQLObjectTablecBs&tZeZeZdZdZRS(NcCsJ||_|iiptd||iifti||iidS(NsBad table name in class %r: %r(ssoClasssselfssqlmetastablesAssertionErrorsTables__init__(sselfssoClass((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__init__is 'cCs|ido tn|djo#|i|i|iii|Sn||iii jo td|ii |fn]|iii |}t |do |i |i|i||Sn|i|i|i|SdS(Ns__sids!%s instance has no attribute '%s's dbEncoding(sattrs startswithsAttributeErrorsselfs FieldClasss tableNamessoClassssqlmetasidNamescolumnss__name__scolumnshasattrsUnicodeFieldClasssdbName(sselfsattrscolumn((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys __getattr__ps  # (s__name__s __module__sSQLObjectFields FieldClasss UnicodeFieldsUnicodeFieldClasss__init__s __getattr__(((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysSQLObjectTablees s TableSpacecBstZeZdZRS(NcCs+|ido tn|i|SdS(Ns__(sattrs startswithsAttributeErrorsselfs TableClass(sselfsattr((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys __getattr__s (s__name__s __module__sTables TableClasss __getattr__(((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys TableSpacess ConstantSpacecBstZdZRS(NcCs(|ido tnt|SdS(Ns__(sattrs startswithsAttributeErrors SQLConstant(sselfsattr((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys __getattr__s (s__name__s __module__s __getattr__(((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys ConstantSpacess AliasFieldcBs)tZdZdZdZdZRS(NscCs ti|||||_dS(N(sFields__init__sselfs tableNames fieldNamesalias(sselfs tableNames fieldNamesalias((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__init__scCs|id|iSdS(Ns.(sselfsaliass fieldName(sselfsdb((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys __sqlrepr__scCs!d|i|i|ifgSdS(Ns%s %s %s(sselfs tableNames as_stringsalias(sself((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pystablesUsedImmediates(s__name__s __module__s as_strings__init__s __sqlrepr__stablesUsedImmediate(((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys AliasFields  s AliasTablecBs5tZeZeiZdZedZ dZ RS(NicCst|do|ii}n |}t}ti||||_|tjoH|i i z&t i d7_ d|t i f}Wd|i i Xn||_dS(Nssqlmetais %s_alias%d(shasattrstablessqlmetas tableNamesNonesTables__init__sselfsaliass _alias_locksacquires AliasTables_alias_countersrelease(sselfstablesaliass tableName((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__init__s   cCs]|ido tn|iot|ii|i}n|i|i ||i SdS(Ns__( sattrs startswithsAttributeErrorsselfstablesgetattrsqs fieldNames FieldClasss tableNamesalias(sselfsattr((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys __getattr__s   ( s__name__s __module__s AliasFields FieldClasss threadingsLocks _alias_locks_alias_countersNones__init__s __getattr__(((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys AliasTables   sAliascBstZedZRS(NcCst|||_dS(N(s AliasTablestablesaliassselfsq(sselfstablesalias((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__init__s(s__name__s __module__sNones__init__(((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysAliasssSelectcBs)tZeeeeedZdZRS(NcCsyt|tgj ot|tfj o |g}n||_||_||_||_||_||_dS(N( stypesitemssselfswheres whereClausesgroupByshavingsorderByslimit(sselfsitemsswheresgroupByshavingsorderByslimit((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__init__s2      cCsddigi}|iD]}|t||q~}h}t |i}|i t j o|i|i nx5|D]-}t|to|it|qqW|i}|o|ddi|7}n|i t j o|dt|i |7}n|it j o|dt|i|7}n|it j o|dt|i|7}n|it j o|dt|i|7}n|it j o|dt|i|7}n|SdS( Ns SELECT %ss, s FROM %ss WHERE %ss GROUP BY %ss HAVING %ss ORDER BY %ss LIMIT %s(sjoinsappends_[1]sselfsitemssvssqlreprsdbsselectstablessliststhingss whereClauses NoDefaultsthings isinstances SQLExpressionsupdatestablesUsedDictskeyssgroupByshavingsorderByslimit(sselfsdbstablessthingss_[1]svsthingsselect((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys __sqlrepr__s.@ (s__name__s __module__s NoDefaults__init__s __sqlrepr__(((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysSelects sInsertcBs#tZeeedZdZRS(NcCsJ||_||_|o!|o tdn||_n |g|_dS(Ns'You may only give valueList *or* values(stemplatesselfstables valueListsvaluess TypeError(sselfstables valueListsvaluesstemplate((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__init__s    c Cs|i odSnd|i}t}|i}|tjot|idthjo|idi }t }n|tj o|ddi |7}n|d7}g}|i } x|iD]}t|thjo7|tjotdt|nt||}n | otdt|n| ddi gi }|D]}|t||qS~qWd |di |f}|SdS( NssINSERT INTO %sis (%s)s, s VALUES sbYou can't mix non-dictionaries with dictionaries in an INSERT if you don't provide a template (%s)s(%s)s%s%s(sselfs valueListstablesinsertsTrues allowNonDictstemplates NoDefaultstypeskeyssFalsesjoins listToJoinsappendslistToJoin_appsvalues TypeErrorsreprs dictToLists_[1]svssqlreprsdb( sselfsdbsinsertsvs allowNonDicts listToJoinsvalues_[1]stemplateslistToJoin_app((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys __sqlrepr__s0   -      E(s__name__s __module__sNones NoDefaults__init__s __sqlrepr__(((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysInserts cCsrg}x|D]}|i||q Wt|it|jo#tdt|t|fn|SdS(NsTExtra entries in dictionary that aren't asked for in template (template=%s, dict=%s)( sliststemplateskeysappendsdictslenskeyss TypeErrorsrepr(stemplatesdictslistskey((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys dictToLists#sUpdatecBs)tZeedZdZdZRS(NcCs(||_||_||_||_dS(N(stablesselfsvaluesstemplateswheres whereClause(sselfstablesvaluesstemplateswhere((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__init__s   cCs1d|i|if}|d7}t}|itj ojxtt |iD]L}|o t }n |d7}|d|i|t |i ||f7}qOWnYxU|i iD]D\}}|o t }n |d7}|d|t ||f7}qW|itj o|dt |i|7}n|SdS(Ns%s %ss SETs,s %s=%ss WHERE %s(sselfssqlNamestablesupdatesTruesfirststemplates NoDefaultsrangeslensisFalsessqlreprsvaluessdbsitemsskeysvalues whereClause(sselfsdbsisupdatesvalueskeysfirst((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys __sqlrepr__!s&   3   !cCsdSdS(NsUPDATE((sself((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pyssqlName6s(s__name__s __module__s NoDefaults__init__s __sqlrepr__ssqlName(((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysUpdates sDeletecBs#tZdZedZdZRS(sxTo be safe, this will signal an error if there is no where clause, unless you pass in where=None to the constructor.cCs0||_|tjo tdn||_dS(NsHYou must give a where clause or pass in None to indicate no where clause(stablesselfswheres NoDefaults TypeErrors whereClause(sselfstableswhere((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__init__>s   cCs@|itjod|iSnd|it|i|fSdS(NsDELETE FROM %ssDELETE FROM %s WHERE %s(sselfs whereClausesNonestablessqlreprsdb(sselfsdb((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys __sqlrepr__Cs(s__name__s __module__s__doc__s NoDefaults__init__s __sqlrepr__(((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysDelete;s  sReplacecBstZdZRS(NcCsdSdS(NsREPLACE((sself((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pyssqlNameLs(s__name__s __module__ssqlName(((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysReplaceKssDESCcBstZdZdZRS(NcCs ||_dS(N(sexprsself(sselfsexpr((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__init__WscCsBt|itot|ii|Sndt|i|SdS(Ns%s DESC(s isinstancesselfsexprsDESCssqlreprsdb(sselfsdb((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys __sqlrepr__Zs(s__name__s __module__s__init__s __sqlrepr__(((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysDESCUs cGs=|d}|d}|otd|t|Sn|SdS(NiisAND(sopssop1sSQLOpsAND(sopssop1((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysAND_s   cGs=|d}|d}|otd|t|Sn|SdS(NiisOR(sopssop1sSQLOpsOR(sopssop1((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysORgs   cCstd|SdS(NsNOT(s SQLPrefixsop(sop((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysNOToscCstd||SdS(NsIN(sSQLOpsitemslist(sitemslist((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys_INrscCs2t|tot||Snt||SdS(N(s isinstanceslistsSelects INSubquerysitems_IN(sitemslist((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysINuscCs8t|tot||Sntt||SdS(N(s isinstanceslistsSelects NOTINSubquerysitemsNOTs_IN(sitemslist((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysNOTIN{scCstd|t|dSdS(NsLIKEs%(sSQLOpsexprs _LikeQuotedsstring(sexprsstring((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys STARTSWITHscCstd|dt|SdS(NsLIKEs%(sSQLOpsexprs _LikeQuotedsstring(sexprsstring((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysENDSWITHscCs"td|dt|dSdS(NsLIKEs%(sSQLOpsexprs _LikeQuotedsstring(sexprsstring((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysCONTAINSSTRINGscCstd|tSdS(NsIS(sSQLOpsexprsNone(sexpr((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysISNULLscCstd|tSdS(NsIS NOT(sSQLOpsexprsNone(sexpr((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys ISNOTNULLss _LikeQuotedcBs,tZdZdZdZdZRS(NcCs||_d|_d|_dS(Ns(sexprsselfsprefixspostfix(sselfsexpr((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__init__s  cCs||i|_|SdS(N(sssselfsprefix(sselfss((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__radd__scCs|i|7_|SdS(N(sselfspostfixss(sselfss((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__add__scCsot|i|dd!}|ddfjo|idd}n|idd}d|i||ifSdS( Niispostgressmysqls%s\%s%%s'%s%s%s'(ssqlreprsselfsexprsdbsssreplacesprefixspostfix(sselfsdbss((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys __sqlrepr__s (s__name__s __module__s__init__s__radd__s__add__s __sqlrepr__(((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys _LikeQuoteds   sSQLJoincBstZddZdZRS(Ns,cCs|ot|tjo@t|to d|ii|iif}qZ|ii }nt|tjo@t|to d|ii|iif}q|ii }n||_||_ ||_ dS(Ns%s AS %s( stable1stypesstrs isinstancesAliassqs tableNamesaliasssqlmetastablestable2sselfsop(sselfstable1stable2sop((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__init__s    cCs@|iod|i|i|ifSnd|i|ifSdS(Ns%s%s %ss%s %s(sselfstable1sopstable2(sselfsdb((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys __sqlrepr__s (s__name__s __module__s__init__s __sqlrepr__(((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysSQLJoins cCst||dSdS(Ns JOIN(sSQLJoinstable1stable2(stable1stable2((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysJOINscCst||dSdS(Ns INNER JOIN(sSQLJoinstable1stable2(stable1stable2((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys INNERJOINscCst||dSdS(Ns CROSS JOIN(sSQLJoinstable1stable2(stable1stable2((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys CROSSJOINscCst||dSdS(Ns STRAIGHT JOIN(sSQLJoinstable1stable2(stable1stable2((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys STRAIGHTJOINscCst||dSdS(Ns LEFT JOIN(sSQLJoinstable1stable2(stable1stable2((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysLEFTJOINscCst||dSdS(Ns LEFT OUTER JOIN(sSQLJoinstable1stable2(stable1stable2((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys LEFTOUTERJOINscCst||dSdS(Ns NATURAL JOIN(sSQLJoinstable1stable2(stable1stable2((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys NATURALJOINscCst||dSdS(Ns NATURAL LEFT JOIN(sSQLJoinstable1stable2(stable1stable2((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysNATURALLEFTJOINscCst||dSdS(Ns NATURAL LEFT OUTER JOIN(sSQLJoinstable1stable2(stable1stable2((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysNATURALLEFTOUTERJOINscCst||dSdS(Ns RIGHT JOIN(sSQLJoinstable1stable2(stable1stable2((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys RIGHTJOINscCst||dSdS(Ns RIGHT OUTER JOIN(sSQLJoinstable1stable2(stable1stable2((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysRIGHTOUTERJOINscCst||dSdS(Ns NATURAL RIGHT JOIN(sSQLJoinstable1stable2(stable1stable2((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysNATURALRIGHTJOINscCst||dSdS(Ns NATURAL RIGHT OUTER JOIN(sSQLJoinstable1stable2(stable1stable2((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysNATURALRIGHTOUTERJOINscCst||dSdS(Ns FULL JOIN(sSQLJoinstable1stable2(stable1stable2((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysFULLJOINscCst||dSdS(Ns FULL OUTER JOIN(sSQLJoinstable1stable2(stable1stable2((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys FULLOUTERJOINscCst||dSdS(Ns NATURAL FULL JOIN(sSQLJoinstable1stable2(stable1stable2((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysNATURALFULLJOINscCst||dSdS(Ns NATURAL FULL OUTER JOIN(sSQLJoinstable1stable2(stable1stable2((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysNATURALFULLOUTERJOINssSQLJoinConditionalcBs&tZdZeedZdZRS(sConditional JOINcCsd| o| o tdn|o|o tdnti||||||_||_dS(s:For condition you must give on_condition or using_columns but not both on_condition can be a string or SQLExpression, for example Table1.q.col1 == Table2.q.col2 using_columns can be a string or a list of columns, e.g. (Table1.q.col1, Table2.q.col2) s+You must give ON condition or USING columnss8You must give ON condition or USING columns but not bothN( s on_conditions using_columnss TypeErrorsSQLJoins__init__sselfstable1stable2sop(sselfstable1stable2sops on_conditions using_columns((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__init__s   cCs+|ion|i}t|dot||}nd|i|i|f}|iod|i|f}n|Sn|i og}xA|i D]6}t|dot||}n|i |qWdi|}d|i|i|f}|iod|i|f}n|Sn t dfdS(Ns __sqlrepr__s %s %s ON %ss%s %ss, s%s %s USING (%s)sImpossible error( sselfs on_conditionshasattrssqlreprsdbsopstable2sjoinstable1s using_columnsscolsappends RuntimeError(sselfsdbsjoins on_conditions using_columnsscol((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys __sqlrepr__ s*      (s__name__s __module__s__doc__sNones__init__s __sqlrepr__(((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysSQLJoinConditionals cCst||d||SdS(Ns INNER JOIN(sSQLJoinConditionalstable1stable2s on_conditions using_columns(stable1stable2s on_conditions using_columns((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysINNERJOINConditional#scCst||d||SdS(Ns LEFT JOIN(sSQLJoinConditionalstable1stable2s on_conditions using_columns(stable1stable2s on_conditions using_columns((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysLEFTJOINConditional&scCst||d||SdS(NsLEFT OUTER JOIN(sSQLJoinConditionalstable1stable2s on_conditions using_columns(stable1stable2s on_conditions using_columns((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysLEFTOUTERJOINConditional)scCst||d||SdS(Ns RIGHT JOIN(sSQLJoinConditionalstable1stable2s on_conditions using_columns(stable1stable2s on_conditions using_columns((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysRIGHTJOINConditional,scCst||d||SdS(NsRIGHT OUTER JOIN(sSQLJoinConditionalstable1stable2s on_conditions using_columns(stable1stable2s on_conditions using_columns((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysRIGHTOUTERJOINConditional/scCst||d||SdS(Ns FULL JOIN(sSQLJoinConditionalstable1stable2s on_conditions using_columns(stable1stable2s on_conditions using_columns((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysFULLJOINConditional2scCst||d||SdS(NsFULL OUTER JOIN(sSQLJoinConditionalstable1stable2s on_conditions using_columns(stable1stable2s on_conditions using_columns((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysFULLOUTERJOINConditional5ss SQLJoinOncBstZdZdZRS(sConditional JOIN ONcCsti|||||dS(N(sSQLJoinConditionals__init__sselfstable1stable2sops on_condition(sselfstable1stable2sops on_condition((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__init__:s(s__name__s __module__s__doc__s__init__(((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys SQLJoinOn8s s SQLJoinUsingcBstZdZdZRS(sConditional JOIN USINGcCs ti||||t|dS(N(sSQLJoinConditionals__init__sselfstable1stable2sopsNones using_columns(sselfstable1stable2sops using_columns((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__init__As(s__name__s __module__s__doc__s__init__(((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys SQLJoinUsing?s cCst||d|SdS(Ns INNER JOIN(s SQLJoinOnstable1stable2s on_condition(stable1stable2s on_condition((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys INNERJOINOnFscCst||d|SdS(Ns LEFT JOIN(s SQLJoinOnstable1stable2s on_condition(stable1stable2s on_condition((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys LEFTJOINOnIscCst||d|SdS(NsLEFT OUTER JOIN(s SQLJoinOnstable1stable2s on_condition(stable1stable2s on_condition((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysLEFTOUTERJOINOnLscCst||d|SdS(Ns RIGHT JOIN(s SQLJoinOnstable1stable2s on_condition(stable1stable2s on_condition((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys RIGHTJOINOnOscCst||d|SdS(NsRIGHT OUTER JOIN(s SQLJoinOnstable1stable2s on_condition(stable1stable2s on_condition((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysRIGHTOUTERJOINOnRscCst||d|SdS(Ns FULL JOIN(s SQLJoinOnstable1stable2s on_condition(stable1stable2s on_condition((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys FULLJOINOnUscCst||d|SdS(NsFULL OUTER JOIN(s SQLJoinOnstable1stable2s on_condition(stable1stable2s on_condition((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysFULLOUTERJOINOnXscCst||d|SdS(Ns INNER JOIN(s SQLJoinUsingstable1stable2s using_columns(stable1stable2s using_columns((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysINNERJOINUsing[scCst||d|SdS(Ns LEFT JOIN(s SQLJoinUsingstable1stable2s using_columns(stable1stable2s using_columns((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys LEFTJOINUsing^scCst||d|SdS(NsLEFT OUTER JOIN(s SQLJoinUsingstable1stable2s using_columns(stable1stable2s using_columns((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysLEFTOUTERJOINUsingascCst||d|SdS(Ns RIGHT JOIN(s SQLJoinUsingstable1stable2s using_columns(stable1stable2s using_columns((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysRIGHTJOINUsingdscCst||d|SdS(NsRIGHT OUTER JOIN(s SQLJoinUsingstable1stable2s using_columns(stable1stable2s using_columns((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysRIGHTOUTERJOINUsinggscCst||d|SdS(Ns FULL JOIN(s SQLJoinUsingstable1stable2s using_columns(stable1stable2s using_columns((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys FULLJOINUsingjscCst||d|SdS(NsFULL OUTER JOIN(s SQLJoinUsingstable1stable2s using_columns(stable1stable2s using_columns((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysFULLOUTERJOINUsingmss OuterFieldcBstZdZRS(NcCsgSdS(N((sself((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pystablesUsedImmediatevs(s__name__s __module__stablesUsedImmediate(((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys OuterFielduss OuterTablecBstZeZdZRS(NcCsIt|do|ii}n |}t}ti||||_dS(Nssqlmeta(shasattrstablessqlmetas tableNamesNonesTables__init__sself(sselfstables tableName((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__init__|s (s__name__s __module__s OuterFields FieldClasss__init__(((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys OuterTableyssOutercBstZdZRS(NcCst||_dS(N(s OuterTablestablesselfsq(sselfstable((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__init__s(s__name__s __module__s__init__(((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysOuterssLIKEcBs2tZdZdZdZdZdZRS(NsLIKEcCs||_||_dS(N(sexprsselfsstring(sselfsexprsstring((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__init__s cCs0dt|i||it|i|fSdS(Ns (%s %s (%s))(ssqlreprsselfsexprsdbsopsstring(sselfsdb((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys __sqlrepr__scCs|i|igSdS(N(sselfsexprsstring(sself((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys componentsscCst|d o|i}|idd}|idd}|idd}|idd}|idd}titi|ti |_ n|i i t |i |SdS(Ns_regexs%%ss*ss%s[*](shasattrsselfsstringsdestsreplacesrescompilesfnmatchs translatesIs_regexssearchsexecutesexprsexecutor(sselfsexecutorsdest((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysexecutes %(s__name__s __module__sops__init__s __sqlrepr__s componentssexecute(((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysLIKEs    sRLIKEcBs)tZdZdZdZdZRS(NsRLIKEcCsP|dddfjodSn/|djodSn|djodSnd SdS( NsmysqlsmaxdbsfirebirdsRLIKEssqlitesREGEXPspostgress~sLIKE(sdb(sselfsdb((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys_get_ops  cCs6dt|i||i|t|i|fSdS(Ns (%s %s (%s))(ssqlreprsselfsexprsdbs_get_opsstring(sselfsdb((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys __sqlrepr__scCs)|i|i|_ti||SdS(N(sselfs_get_opsdbsopsLIKEsexecutesexecutor(sselfsexecutor((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysexecutes(s__name__s __module__sops_get_ops __sqlrepr__sexecute(((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysRLIKEs s INSubquerycBs)tZdZdZdZdZRS(NsINcCs||_||_dS(N(sitemsselfssubquery(sselfsitemssubquery((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__init__s cCs|igSdS(N(sselfsitem(sself((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys componentsscCs0dt|i||it|i|fSdS(Ns %s %s (%s)(ssqlreprsselfsitemsdbsopssubquery(sselfsdb((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys __sqlrepr__s(s__name__s __module__sops__init__s componentss __sqlrepr__(((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys INSubquerys  s NOTINSubquerycBstZdZRS(NsNOT IN(s__name__s __module__sop(((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys NOTINSubqueryssSubquerycBstZdZdZRS(NcCs||_||_dS(N(sopsselfssubquery(sselfsopssubquery((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys__init__s cCs!d|it|i|fSdS(Ns%s (%s)(sselfsopssqlreprssubquerysdb(sselfsdb((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys __sqlrepr__s(s__name__s __module__s__init__s __sqlrepr__(((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysSubquerys cCstd|SdS(NsEXISTS(sSubqueryssubquery(ssubquery((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysEXISTSscCstd|SdS(Ns NOT EXISTS(sSubqueryssubquery(ssubquery((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys NOTEXISTSscCstd|SdS(NsSOME(sSubqueryssubquery(ssubquery((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysSOMEscCstd|SdS(NsANY(sSubqueryssubquery(ssubquery((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysANYscCstd|SdS(NsALL(sSubqueryssubquery(ssubquery((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pysALLss__main__s9 >>> AND(table.address.name == "Ian Bicking", table.address.zip > 30000) >>> table.address.name >>> AND(LIKE(table.address.name, "this"), IN(table.address.zip, [100, 200, 300])) >>> Select([table.address.name, table.address.state], where=LIKE(table.address.name, "%ian%")) >>> Select([table.user.name], where=AND(table.user.state == table.states.abbrev)) >>> Insert(table.address, [{"name": "BOB", "address": "3049 N. 18th St."}, {"name": "TIM", "address": "409 S. 10th St."}]) >>> Insert(table.address, [("BOB", "3049 N. 18th St."), ("TIM", "409 S. 10th St.")], template=('name', 'address')) >>> Delete(table.address, where="BOB"==table.address.name) >>> Update(table.address, {"lastModified": const.NOW()}) >>> Replace(table.address, [("BOB", "3049 N. 18th St."), ("TIM", "409 S. 10th St.")], template=('name', 'address')) s s>>> i(s__doc__s Exceptions VersionErrors NoDefaultsTruesFalsesresfnmatchsoperators threadings convertersssqlreprsregisterConvertersTRUEsFALSEscompiles safeSQLREs sqlIdentifiersexecutes SQLExpressionsSQLExprConverterstablesUsedDictsaddsdivssubsmulsltsleseqsnesgesgtscontainss operatorMapsSQLOpsSQLCalls SQLPrefixs SQLConstantsSQLTrueClauseClasss SQLTrueClausesFieldsSQLObjectFields UnicodeFieldsTablesSQLObjectTables TableSpaces ConstantSpaces AliasFields AliasTablesAliassSelectsInserts dictToListsUpdatesDeletesReplacesDESCsANDsORsNOTs_INsINsNOTINs STARTSWITHsENDSWITHsCONTAINSSTRINGsISNULLs ISNOTNULLs _LikeQuotedsSQLJoinsJOINs INNERJOINs CROSSJOINs STRAIGHTJOINsLEFTJOINs LEFTOUTERJOINs NATURALJOINsNATURALLEFTJOINsNATURALLEFTOUTERJOINs RIGHTJOINsRIGHTOUTERJOINsNATURALRIGHTJOINsNATURALRIGHTOUTERJOINsFULLJOINs FULLOUTERJOINsNATURALFULLJOINsNATURALFULLOUTERJOINsSQLJoinConditionalsNonesINNERJOINConditionalsLEFTJOINConditionalsLEFTOUTERJOINConditionalsRIGHTJOINConditionalsRIGHTOUTERJOINConditionalsFULLJOINConditionalsFULLOUTERJOINConditionals SQLJoinOns SQLJoinUsings INNERJOINOns LEFTJOINOnsLEFTOUTERJOINOns RIGHTJOINOnsRIGHTOUTERJOINOns FULLJOINOnsFULLOUTERJOINOnsINNERJOINUsings LEFTJOINUsingsLEFTOUTERJOINUsingsRIGHTJOINUsingsRIGHTOUTERJOINUsings FULLJOINUsingsFULLOUTERJOINUsings OuterFields OuterTablesOutersLIKEsRLIKEs INSubquerys NOTINSubquerysSubquerysEXISTSs NOTEXISTSsSOMEsANYsALLstablesconstsfuncs__name__stestsssplitsexprsstrips startswith(rs LEFTJOINUsings INSubquerys RIGHTJOINOns LEFTOUTERJOINsOuters NOTEXISTSsTRUEsLEFTOUTERJOINConditionals CROSSJOINsSQLCallsconstsUpdates RIGHTJOINs STRAIGHTJOINsLEFTJOINConditionalsRIGHTJOINConditionalsRIGHTOUTERJOINsNATURALRIGHTOUTERJOINs ConstantSpacesRIGHTOUTERJOINConditionalsFALSEs AliasFieldsLIKEsexecutesSQLJoinsFalses threadings SQLConstantsORsSelects NoDefaultsSQLOps FULLOUTERJOINs FULLJOINUsings OuterFieldstables NOTINSubquerysrestestssSQLExprConvertersTrues SQLPrefixsSubquerys TableSpacesDeletesANDsCONTAINSSTRINGsISNULLsReplacesFULLOUTERJOINOns ISNOTNULLs VersionErrors SQLTrueClauses SQLExpressionsNOTsRLIKEsFULLJOINs OuterTables STARTSWITHsINNERJOINConditionalsRIGHTOUTERJOINUsingsNATURALLEFTOUTERJOINsoperatorsSQLObjectFieldssqlreprs sqlIdentifiersNATURALRIGHTJOINsRIGHTJOINUsingsSOMEs NATURALJOINs SQLJoinOnsfuncs _LikeQuotedsLEFTJOINsALLsNATURALLEFTJOINsJOINsNATURALFULLOUTERJOINs FULLJOINOnsexprsRIGHTOUTERJOINOns_INsFULLOUTERJOINConditionalsfnmatchs operatorMaps LEFTJOINOnsSQLTrueClauseClasss SQLJoinUsingsINNERJOINUsingsFULLJOINConditionalsNATURALFULLJOINsFieldsENDSWITHs safeSQLREsLEFTOUTERJOINUsings dictToListsNOTINsSQLJoinConditionalsSQLObjectTablesLEFTOUTERJOINOns INNERJOINOns INNERJOINsInsertsEXISTSsAliassINsDESCs UnicodeFieldsregisterConverters AliasTablestablesUsedDictsANYsTablesFULLOUTERJOINUsing((s2build/bdist.linux-i686/egg/sqlobject/sqlbuilder.pys?;s    j               & #                                  )                            PKb95;sqlobject/index.pyc; Ec@sVdkTdkZdklZdefdYZdefdYZdgZdS((s*N(ssqlreprsSODatabaseIndexcBsNtZedZdZdZdZeZZZ Z Z dZ RS(NcCs1||_||_|i||_||_dS(N(ssoClasssselfsnamesconvertColumnsscolumnss descriptionssunique(sselfssoClasssnamescolumnssunique((s-build/bdist.linux-i686/egg/sqlobject/index.pys__init__s  cCsxg}xg|D]_}t|t ohd|<}n|idop|id ptd||i|i f|id ptd||i|i f|i |q n|d}t|t  o |i}n|i i i}|i| oLxS|iD]!}|i|jo |}Pq q Wtd||i fn ||}||d<|i |q W|SdS(so Converts all the columns to dictionary descriptors; dereferences string column names. scolumns expressionsMYou cannot provide both an expression and a column (for %s in index %s in %s)slengths?length does not apply to expressions (for %s in index %s in %s)s7The column by the name %r was not found in the class %rN(snewscolumnssdescs isinstancesdictshas_keysAssertionErrorsselfsnamessoClasssappends columnNamesstrssqlmetascolDictsvaluesspossiblesorigNamescolumns ValueError(sselfscolumnsscolumnspossibles columnNamesnewscolDictsdesc((s-build/bdist.linux-i686/egg/sqlobject/index.pysconvertColumnss4..       cCs5t|dto |dSnt|d|SdS(Ns expression(s isinstancesdescsstrssqlreprsdb(sselfsdescsdb((s-build/bdist.linux-i686/egg/sqlobject/index.pys getExpression7s cCs|io d}nd}g}xR|iD]G}|ido|i|i|dq*|i|di q*Wd||i i i |i |i i i di|f}|SdS(Ns UNIQUE INDEXsINDEXs expressionssqlitescolumnsCREATE %s %s_%s ON %s (%s)s, (sselfsuniques uniqueOrIndexsspecs descriptionssdescshas_keysappends getExpressionsdbNamessoClassssqlmetastablesnamesjoinsret(sselfssoClasssrets uniqueOrIndexsspecsdesc((s-build/bdist.linux-i686/egg/sqlobject/index.pyssqliteCreateIndexSQL=s   7cCs|io d}nd}g}x|iD]}}|ido|i|i|dq*|ido&|id|di |dfq*|i|di q*Wd|i i ||i d i|fSdS( NsUNIQUEsINDEXs expressionsmysqlslengths%s(%d)scolumnsALTER TABLE %s ADD %s %s (%s)s, (sselfsuniques uniqueOrIndexsspecs descriptionssdescshas_keysappends getExpressionsdbNamessoClassssqlmetastablesnamesjoin(sselfssoClasss uniqueOrIndexsspecsdesc((s-build/bdist.linux-i686/egg/sqlobject/index.pysmysqlCreateIndexSQLQs   &( s__name__s __module__sFalses__init__sconvertColumnss getExpressionssqliteCreateIndexSQLspostgresCreateIndexSQLsmaxdbCreateIndexSQLsmssqlCreateIndexSQLssybaseCreateIndexSQLsfirebirdCreateIndexSQLsmysqlCreateIndexSQL(((s-build/bdist.linux-i686/egg/sqlobject/index.pysSODatabaseIndexs  &  s DatabaseIndexcBsYtZdZeZdZdZdZdZe eeZ dZ dZ RS(sV This takes a variable number of parameters, each of which is a column for indexing. Each column may be a column object or the string name of the column (*not* the database name). You may also use dictionaries, to further customize the indexing of the column. The dictionary may have certain keys: 'column': The column object or string identifier. 'length': MySQL will only index the first N characters if this is given. For other databases this is ignored. 'expression': You can create an index based on an expression, e.g., 'lower(column)'. This can either be a string or a sqlbuilder expression. Further keys may be added to the column specs in the future. The class also take the keyword argument `unique`; if true then a UNIQUE index is created. cOs||d<||_dS(Nscolumns(scolumnsskwsself(sselfscolumnsskw((s-build/bdist.linux-i686/egg/sqlobject/index.pys__init__s cCsE|iidtjptd|id|f||idi(sselfs __class__s__name__shexsabssidskw(sself((s-build/bdist.linux-i686/egg/sqlobject/index.pys__repr__s( s__name__s __module__s__doc__sSODatabaseIndexs baseClasss__init__ssetNames _get_names _set_namespropertysnames withClasss__repr__(((s-build/bdist.linux-i686/egg/sqlobject/index.pys DatabaseIndexes      (stypesscols convertersssqlreprsobjectsSODatabaseIndexs DatabaseIndexs__all__(ssqlreprs__all__sSODatabaseIndexs DatabaseIndexscol((s-build/bdist.linux-i686/egg/sqlobject/index.pys?s   `3PKb95 sqlobject/constraints.pyc; Ec@sdZddjddjf\ZZdefdYZdZdZdZdZd Z d fd YZ d fd YZ dS(s Constraints iisBadValuecBstZdZRS(NcGs`||_||_t||_t||_d||i||f}ti |||dS(Ns%s.%s %s (you gave: %s)( sdescsselfscolsreprsobjsvaluesnamesfullDescs ValueErrors__init__sargs(sselfsdescsobjscolsvaluesargssfullDesc((s3build/bdist.linux-i686/egg/sqlobject/constraints.pys__init__ s   (s__name__s __module__s__init__(((s3build/bdist.linux-i686/egg/sqlobject/constraints.pysBadValuescCs6t|tdj otd|||ndS(Nssonly allows strings(stypesvaluesBadValuesobjscol(sobjscolsvalue((s3build/bdist.linux-i686/egg/sqlobject/constraints.pysisStringscCs*|tjotd|||ndS(Nsis defined NOT NULL(svaluesNonesBadValuesobjscol(sobjscolsvalue((s3build/bdist.linux-i686/egg/sqlobject/constraints.pysnotNulls cCsBt|tdtdfjotd|||ndS(Nilsonly allows integers(stypesvaluesBadValuesobjscol(sobjscolsvalue((s3build/bdist.linux-i686/egg/sqlobject/constraints.pysisInts%cCsKt|tdtdtdfjotd|||ndS(Nilf1.1000000000000001s"only allows floating point numbers(stypesvaluesBadValuesobjscol(sobjscolsvalue((s3build/bdist.linux-i686/egg/sqlobject/constraints.pysisFloat!s.cCs9t|ttfjotd|||ndS(Nsonly allows booleans(stypesvaluesTruesBadValuesobjscol(sobjscolsvalue((s3build/bdist.linux-i686/egg/sqlobject/constraints.pysisBool%ssInListcBstZdZdZRS(NcCs ||_dS(N(slsselfslist(sselfsl((s3build/bdist.linux-i686/egg/sqlobject/constraints.pys__init__+scCs:||ijo&tdt|i|||ndS(Nsaccepts only values in %s(svaluesselfslistsBadValuesreprsobjscol(sselfsobjscolsvalue((s3build/bdist.linux-i686/egg/sqlobject/constraints.pys__call__.s(s__name__s __module__s__init__s__call__(((s3build/bdist.linux-i686/egg/sqlobject/constraints.pysInList)s s MaxLengthcBstZdZdZRS(NcCs ||_dS(N(slengthsself(sselfslength((s3build/bdist.linux-i686/egg/sqlobject/constraints.pys__init__5scCsoyt|}Wn(tj otd|||nX||ijo td|i|||ndS(Nsobject does not have a lengths!must be shorter in length than %s(slensvalueslengths TypeErrorsBadValuesobjscolsself(sselfsobjscolsvalueslength((s3build/bdist.linux-i686/egg/sqlobject/constraints.pys__call__8s (s__name__s __module__s__init__s__call__(((s3build/bdist.linux-i686/egg/sqlobject/constraints.pys MaxLength3s N( s__doc__sTruesFalses ValueErrorsBadValuesisStringsnotNullsisIntsisFloatsisBoolsInLists MaxLength( sisFloatsisStringsFalsesisInts MaxLengthsisBoolsnotNullsBadValuesInListsTrue((s3build/bdist.linux-i686/egg/sqlobject/constraints.pys?s      PKb95 @  sqlobject/col.pyc; Ec@sdZdkZdkZy dkZWnej odkZnXdkZdkZdk l Z dk l Z dk l Z dklZlZdklZeiZddjddjf\ZZy dkZWnej o eZnXeZyd klZWnBej o6y dkZWnej o eZqOXeZnXeZd Zd ZeoZeeiZe ed oeei!Z"qeeii!eiZ"neo eZ#neo eZ#ne$Z#d ddgZ%eoe%i&dneoe%i&dneZ'de i(fdYZ)de*fdYZ+de*fdYZ,de+fdYZ-de i.fdYZ/de-fdYZ0de,fdYZ1d e i.fd!YZ2d"e-fd#YZ3d$e,fd%YZ4d&e i.fd'YZ5d(e+fd)YZ6d*e,fd+YZ7d,e i.fd-YZ8d.e+fd/YZ9d0e,fd1YZ:d2e i.fd3YZ;d4e+fd5YZ<d6e,fd7YZ=d8e+fd9YZ>d:e,fd;YZ?d<e>fd=YZ@d>e?fd?YZAd@e+fdAYZBdBe i.fdCYZCdDe,fdEYZDeodFe iEfdGYZFneodHe iEfdIYZGndJe+fdKYZHdLe,fdMYZIeodNeFfdOYZEndPe+fdQYZJdRe,fdSYZKeodTeFfdUYZLndVe+fdWYZMdXe,fdYYZNdZe+fd[YZOd\e,fd]YZPd^eOfd_YZQd`ePfdaYZRdbe i.fdcYZSdde0fdeYZTdfe1fdgYZUdheSfdiYZVdjeTfdkYZWdleUfdmYZXe$dnZYdoZZgZ[x^e\i]D]M\Z^Z_e`e_eoeae_e,p eae_e+oe[i&e^qqWe%ibe[[[dS(ps! Col -- SQLObject columns Note that each column object is named BlahBlahCol, and these are used in class definitions. But there's also a corresponding SOBlahBlahCol object, which is used in SQLObject *classes*. An explanation: when a SQLObject subclass is created, the metaclass looks through your class definition for any subclasses of Col. It collects them together, and indexes them to do all the database stuff you like, like the magic attributes and whatnot. It then asks the Col object to create an SOCol object (usually a subclass, actually). The SOCol object contains all the interesting logic, as well as a record of the attribute name you used and the class it is bound to (set by the metaclass). So, in summary: Col objects are what you define, but SOCol objects are what gets used. N(scompound(s validators(s findClass(s array_types buffer_type(scountii(sDateTimesdatetimes mxDateTimesTimesdatetime_availablesmxdatetime_availablesdefault_datetime_implementationsDATETIME_IMPLEMENTATIONsMXDATETIME_IMPLEMENTATIONs SQLValidatorcBstZdZRS(NcCs||tijot|i}|in$|tijo |i}ntx |D]}||||}qXW|SdS(N( svalidates validatorss to_pythonslistsselfsvlistsreverses from_pythons RuntimeErrors validatorsvaluesstate(sselfsvaluesstatesvalidates validatorsvlist((s+build/bdist.linux-i686/egg/sqlobject/col.pysattemptConvertWs (s__name__s __module__sattemptConvert(((s+build/bdist.linux-i686/egg/sqlobject/col.pys SQLValidatorVssSOColcBsytZeeeeeeeeeeeeeeeeeegeedZdZdZeeeZ dZ dZ dZ ee eeZ dZeeeeZdZd Zd Zd Zd Zd ZdZdZdZdZdZdZdZdZdZdZdZ dZ!edZ"dZ#dZ$RS(NcCstt|i| o(ti|ptdt |n|djp td|p td||_ ||_ ||_ t |to|djptd|n||_t| tgtffjo | g} n|i| |_t|_| tj o=| |_| tjp | | jptd| | fn| tj o | |_n|iotig|i|_n||_||_||_| |_||_|ioN|iiid o |i|_ |id|_q"|id |_ n t!|_ |t!jo|i#i$i%|i|_"n ||_"||_&|i&o |t!jo)d |id i(|id |_'n ||_'| tjo ||_)n | |_)|i*}|o9|o|i-|nt.i/|d |d |_,n ||_,||_0||_1|p||_2||_3||_4|o1x.|i6D]\}}t8|||qiWndS( NsSName must be SQL-safe (letters, numbers, underscores): %s (or use forceDBName=True)sidsOThe column name "id" is reserved for SQLObject use (and is implicitly created).s'You must provide a name for all columnssnullsBThe only string value allowed for cascade is 'null' (you gave: %r)sfThe notNull and notNone arguments are aliases, and must not conflict. You gave notNull=%r, notNone=%rsIDisbyii(9ssupersSOColsselfs__init__s forceDBNames sqlbuilders sqlIdentifiersnamesAssertionErrorsreprs columnDefs creationOrders immutables isinstancescascadesstrstypes constraintssautoConstraintssFalsesnotNonesnotNulls NoDefaultsconstsssoClasssdefaults_defaultssqlTypes customSQLTypes foreignKeysuppersendswiths foreignNamesNonesdbNamessqlmetasstylespythonAttrToDBColumns alternateIDsalternateMethodNames capitalizesuniquescreateValidatorss _validatorss validatorsappends SQLValidatorsjoinsnoCacheslazysorigNamestitlestagss extra_varssitemssvaluessetattr(sselfsnamessoClasss creationOrdersdbNamesdefaults foreignKeys alternateIDsalternateMethodNames constraintssnotNullsnotNonesuniquessqlTypes columnDefs validators immutablescascadeslazysnoCaches forceDBNamestitlestagssorigNames extra_varss _validatorssvalue((s+build/bdist.linux-i686/egg/sqlobject/col.pys__init__lst(    %    4              )     !      cCsK||_|io"|ii|_|ii|_nt|_t|_dS(N(svaluesselfs _validators to_pythons from_pythonsNone(sselfsvalue((s+build/bdist.linux-i686/egg/sqlobject/col.pys_set_validators    cCs |iSdS(N(sselfs _validator(sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys_get_validatorscCsgSdS(s+Create a list of validators for the column.N((sself((s+build/bdist.linux-i686/egg/sqlobject/col.pyscreateValidatorsscCsgSdS(N((sself((s+build/bdist.linux-i686/egg/sqlobject/col.pysautoConstraintsscCs_|itjotSnDt|ido |iSn&t|io|iSn|iSdS(Ns __sqlrepr__(sselfs_defaults NoDefaultshasattrscallable(sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _get_defaults cCs*|iddjpt|id SdS(NisID(sselfsnamesAssertionError(sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _get_joinName scCsd|ii|if}|itj o|dt|i7}n|io|d|i7}n|i o|d7}n|i o|d7}n|dSdS(Ns<%s %ss default=%ss connected to %ss alternate IDs not nulls>( sselfs __class__s__name__snamesrsdefaults NoDefaultsreprs foreignKeys alternateIDsnotNone(sselfsr((s+build/bdist.linux-i686/egg/sqlobject/col.pys__repr__s   cCs$di|i|igSdS(Ns (sjoinsselfs_sqlTypes _extraSQL(sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys createSQLscCsXg}|ip|io|idn|ip|io|idn|SdS(NsNOT NULLsUNIQUE(sresultsselfsnotNones alternateIDsappendsunique(sselfsresult((s+build/bdist.linux-i686/egg/sqlobject/col.pys _extraSQLs cCs8|itjotd|i|ifn|iSdS(NsGCol %s (%s) cannot be used for automatic schema creation (too abstract)(sselfs customSQLTypesNones ValueErrorsnames __class__(sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys_sqlType&scCs|iSdS(N(sselfs_sqlType(sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _mysqlType.scCs|iSdS(N(sselfs_sqlType(sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _postgresType1scCs,y|iSWntj o dSnXdS(Ns(sselfs_sqlTypes ValueError(sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _sqliteType4scCs|iSdS(N(sselfs_sqlType(sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _sybaseType<scCs|iSdS(N(sselfs_sqlType(sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _mssqlType?scCs|iSdS(N(sselfs_sqlType(sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _firebirdTypeBscCs|iSdS(N(sselfs_sqlType(sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _maxdbTypeEscCs*di|i|ig|iSdS(Ns (sjoinsselfsdbNames _mysqlTypes _extraSQL(sself((s+build/bdist.linux-i686/egg/sqlobject/col.pysmysqlCreateSQLHscCs*di|i|ig|iSdS(Ns (sjoinsselfsdbNames _postgresTypes _extraSQL(sself((s+build/bdist.linux-i686/egg/sqlobject/col.pyspostgresCreateSQLKscCs*di|i|ig|iSdS(Ns (sjoinsselfsdbNames _sqliteTypes _extraSQL(sself((s+build/bdist.linux-i686/egg/sqlobject/col.pyssqliteCreateSQLNscCs*di|i|ig|iSdS(Ns (sjoinsselfsdbNames _sybaseTypes _extraSQL(sself((s+build/bdist.linux-i686/egg/sqlobject/col.pyssybaseCreateSQLQscCs*di|i|ig|iSdS(Ns (sjoinsselfsdbNames _mssqlTypes _extraSQL(sself((s+build/bdist.linux-i686/egg/sqlobject/col.pysmssqlCreateSQLTscCs~t|t o*di|i|ig|iSn@di|ig|idg|i|idgSdS(Ns ii(s isinstancesselfs SOEnumColsjoinsdbNames _firebirdTypes _extraSQL(sself((s+build/bdist.linux-i686/egg/sqlobject/col.pysfirebirdCreateSQLWs*cCs*di|i|ig|iSdS(Ns (sjoinsselfsdbNames _maxdbTypes _extraSQL(sself((s+build/bdist.linux-i686/egg/sqlobject/col.pysmaxdbCreateSQL`scCs|tjo|Sn|iio dn|iio`|ii}|tjo|iiny |t SWqt j o|ii |SqXn|ii |SdS(Ns)@@: figure out the exception for a delete( sobjsNonesselfssqlmetasobsoletes cacheColumnss _columnCachescolumnss loadValuessnamesKeyErrors loadColumn(sselfsobjstypescolumns((s+build/bdist.linux-i686/egg/sqlobject/col.pys__get__cs       cCsD|io#td|ii|ifn|ii||dS(NsThe column %s.%s is immutable( sselfs immutablesAttributeErrorsobjs __class__s__name__snamessqlmetas setColumnsvalue(sselfsobjsvalue((s+build/bdist.linux-i686/egg/sqlobject/col.pys__set__ts #cCstd|dS(NsI can't be deleted from %r(sAttributeErrorsobj(sselfsobj((s+build/bdist.linux-i686/egg/sqlobject/col.pys __delete__{s(%s__name__s __module__sNones NoDefaultsFalses__init__s_set_validators_get_validatorspropertys validatorscreateValidatorssautoConstraintss _get_defaultsdefaults _get_joinNamesjoinNames__repr__s createSQLs _extraSQLs_sqlTypes _mysqlTypes _postgresTypes _sqliteTypes _sybaseTypes _mssqlTypes _firebirdTypes _maxdbTypesmysqlCreateSQLspostgresCreateSQLssqliteCreateSQLssybaseCreateSQLsmssqlCreateSQLsfirebirdCreateSQLsmaxdbCreateSQLs__get__s__set__s __delete__(((s+build/bdist.linux-i686/egg/sqlobject/col.pysSOColjs>H|                       sColcBsVtZeZedZdZdZeeeZ dZ dZ dZ RS(NcKsQtt|i||id<||idis (unnamed)(sselfs __class__s__name__shexsabssids_name(sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys__repr__s( s__name__s __module__sSOCols baseClasssNones__init__s _set_names _get_namespropertysnames withClasss __setattr__s__repr__(((s+build/bdist.linux-i686/egg/sqlobject/col.pysCols     sSOStringLikeColcBsqtZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z RS( s2A common ancestor for SOStringCol and SOUnicodeColcKst|d|_t|dd|_t|dt|_|i o2|idjp|i p tdt|_n|idjo t |_nt t |i |dS(Nslengthsvarcharsautos char_binarys9Without a length strings are treated as TEXT, not varchar( spopKeyskwsselfslengthsvarcharsNones char_binarysAssertionErrorsFalsesTruessupersSOStringLikeCols__init__(sselfskw((s+build/bdist.linux-i686/egg/sqlobject/col.pys__init__s %  cCsAtig}|itj o|ti|ig7}n|SdS(N(sconstssisStrings constraintssselfslengthsNones MaxLength(sselfs constraints((s+build/bdist.linux-i686/egg/sqlobject/col.pysautoConstraintss cCsV|itj o |iSn|i odSn%|iod|iSn d|iSdS(NsTEXTs VARCHAR(%i)sCHAR(%i)(sselfs customSQLTypesNoneslengthsvarchar(sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys_sqlTypes   cCs|iotd|ndS(Ns,%s does not support binary character columns(sselfs char_binarys ValueErrorsdb(sselfsdb((s+build/bdist.linux-i686/egg/sqlobject/col.pys_check_case_sensitives cCs,|i}|io|d7}n|SdS(Ns BINARY(sselfs_sqlTypestypes char_binary(sselfstype((s+build/bdist.linux-i686/egg/sqlobject/col.pys _mysqlTypes  cCs$|idtt|iSdS(Ns PostgreSQL(sselfs_check_case_sensitivessupersSOStringLikeCols _postgresType(sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _postgresTypes cCs$|idtt|iSdS(NsSQLite(sselfs_check_case_sensitivessupersSOStringLikeCols _sqliteType(sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _sqliteTypes cCsE|id|i}|i o|i o|d7}n|SdS(NsSYBASEs NULL(sselfs_check_case_sensitives_sqlTypestypesnotNones alternateID(sselfstype((s+build/bdist.linux-i686/egg/sqlobject/col.pys _sybaseTypes   cCsi|i o d}n)|iod|i}nd|i}|i o|i o|d7}n|SdS(Ns varchar(4000)s VARCHAR(%i)sCHAR(%i)s NULL(sselfslengthstypesvarcharsnotNones alternateID(sselfstype((s+build/bdist.linux-i686/egg/sqlobject/col.pys _mssqlTypes    cCs.|id|i odSn |iSdS(NsFireBirdsBLOB SUB_TYPE TEXT(sselfs_check_case_sensitiveslengths_sqlType(sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _firebirdTypes  cCs.|id|i odSn |iSdS(Ns SAP DB/MaxDBs LONG ASCII(sselfs_check_case_sensitiveslengths_sqlType(sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _maxdbTypes  (s__name__s __module__s__doc__s__init__sautoConstraintss_sqlTypes_check_case_sensitives _mysqlTypes _postgresTypes _sqliteTypes _sybaseTypes _mssqlTypes _firebirdTypes _maxdbType(((s+build/bdist.linux-i686/egg/sqlobject/col.pysSOStringLikeCols        sStringValidatorcBstZdZdZRS(NcCs>|tjotSnt|to|idSn|SdS(Nsascii(svaluesNones isinstancesunicodesencode(sselfsvaluesstate((s+build/bdist.linux-i686/egg/sqlobject/col.pys to_pythons  cCsV|tjotSnt|to|Snt|to|idSn|SdS(Nsascii(svaluesNones isinstancesstrsunicodesencode(sselfsvaluesstate((s+build/bdist.linux-i686/egg/sqlobject/col.pys from_pythons (s__name__s __module__s to_pythons from_python(((s+build/bdist.linux-i686/egg/sqlobject/col.pysStringValidators s SOStringColcBstZdZRS(NcCs!tgtt|iSdS(N(sStringValidatorssupers SOStringColsselfscreateValidators(sself((s+build/bdist.linux-i686/egg/sqlobject/col.pyscreateValidatorss(s__name__s __module__screateValidators(((s+build/bdist.linux-i686/egg/sqlobject/col.pys SOStringCol ss StringColcBstZeZRS(N(s__name__s __module__s SOStringCols baseClass(((s+build/bdist.linux-i686/egg/sqlobject/col.pys StringColssUnicodeStringValidatorcBstZdZdZRS(NcCsk|tjotSnt|to|Snt|tot|i|iSnt||iSdS(N(svaluesNones isinstancesunicodes array_typestostringsselfs db_encoding(sselfsvaluesstate((s+build/bdist.linux-i686/egg/sqlobject/col.pys to_pythons cCsA|tjotSnt|to|Sn|i|iSdS(N(svaluesNones isinstancesstrsencodesselfs db_encoding(sselfsvaluesstate((s+build/bdist.linux-i686/egg/sqlobject/col.pys from_python!s  (s__name__s __module__s to_pythons from_python(((s+build/bdist.linux-i686/egg/sqlobject/col.pysUnicodeStringValidators s SOUnicodeColcBstZdZdZRS(NcKs/t|dd|_tt|i|dS(Ns dbEncodingsUTF-8(spopKeyskwsselfs dbEncodingssupers SOUnicodeCols__init__(sselfskw((s+build/bdist.linux-i686/egg/sqlobject/col.pys__init__)scCs*td|igtt|iSdS(Ns db_encoding(sUnicodeStringValidatorsselfs dbEncodingssupers SOUnicodeColscreateValidators(sself((s+build/bdist.linux-i686/egg/sqlobject/col.pyscreateValidators-s(s__name__s __module__s__init__screateValidators(((s+build/bdist.linux-i686/egg/sqlobject/col.pys SOUnicodeCol(s s UnicodeColcBstZeZRS(N(s__name__s __module__s SOUnicodeCols baseClass(((s+build/bdist.linux-i686/egg/sqlobject/col.pys UnicodeCol1ss IntValidatorcBstZdZdZRS(NcCs|tjotSnt|tttifo|Sny2yt|SWntj ot|SnXWn2ti d|i t ||f||nXdS(Ns5expected an int in the IntCol '%s', got %s %r instead(svaluesNones isinstancesintslongs sqlbuilders SQLExpressions OverflowErrors validatorssInvalidsselfsnamestypesstate(sselfsvaluesstate((s+build/bdist.linux-i686/egg/sqlobject/col.pys to_python7s cCsi|tjotSnt|tttif o/tid|i t ||f||n|SdS(Ns5expected an int in the IntCol '%s', got %s %r instead( svaluesNones isinstancesintslongs sqlbuilders SQLExpressions validatorssInvalidsselfsnamestypesstate(sselfsvaluesstate((s+build/bdist.linux-i686/egg/sqlobject/col.pys from_pythonEs  (s__name__s __module__s to_pythons from_python(((s+build/bdist.linux-i686/egg/sqlobject/col.pys IntValidator5s sSOIntColcBs#tZdZdZdZRS(NcCstigSdS(N(sconstssisInt(sself((s+build/bdist.linux-i686/egg/sqlobject/col.pysautoConstraintsPscCs*td|igtt|iSdS(Nsname(s IntValidatorsselfsnamessupersSOIntColscreateValidators(sself((s+build/bdist.linux-i686/egg/sqlobject/col.pyscreateValidatorsSscCsdSdS(NsINT((sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys_sqlTypeWs(s__name__s __module__sautoConstraintsscreateValidatorss_sqlType(((s+build/bdist.linux-i686/egg/sqlobject/col.pysSOIntColMs  sIntColcBstZeZRS(N(s__name__s __module__sSOIntCols baseClass(((s+build/bdist.linux-i686/egg/sqlobject/col.pysIntColZss BoolValidatorcBstZdZdZRS(NcCs3|tjotSn| o tiSntiSdS(N(svaluesNones sqlbuildersFALSEsTRUE(sselfsvaluesstate((s+build/bdist.linux-i686/egg/sqlobject/col.pys to_python_s   cCs2|tjotSn|o tiSntiSdS(N(svaluesNones sqlbuildersTRUEsFALSE(sselfsvaluesstate((s+build/bdist.linux-i686/egg/sqlobject/col.pys from_pythongs   (s__name__s __module__s to_pythons from_python(((s+build/bdist.linux-i686/egg/sqlobject/col.pys BoolValidator]s s SOBoolColcBsYtZdZdZdZdZdZdZdZdZ d Z RS( NcCstigSdS(N(sconstssisBool(sself((s+build/bdist.linux-i686/egg/sqlobject/col.pysautoConstraintspscCs!tgtt|iSdS(N(s BoolValidatorssupers SOBoolColsselfscreateValidators(sself((s+build/bdist.linux-i686/egg/sqlobject/col.pyscreateValidatorssscCsdSdS(NsBOOL((sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _postgresTypewscCsdSdS(NsTINYINT((sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _mysqlTypezscCsdSdS(NsBIT((sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _sybaseType}scCsdSdS(NsBIT((sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _mssqlTypescCsdSdS(NsINT((sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _firebirdTypescCsdSdS(NsBOOLEAN((sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _maxdbTypescCsdSdS(NsTINYINT((sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _sqliteTypes( s__name__s __module__sautoConstraintsscreateValidatorss _postgresTypes _mysqlTypes _sybaseTypes _mssqlTypes _firebirdTypes _maxdbTypes _sqliteType(((s+build/bdist.linux-i686/egg/sqlobject/col.pys SOBoolColos        sBoolColcBstZeZRS(N(s__name__s __module__s SOBoolCols baseClass(((s+build/bdist.linux-i686/egg/sqlobject/col.pysBoolColssFloatValidatorcBstZdZdZRS(NcCs|tjotSnt|ttttifo|Snyt|SWn2ti d|i t ||f||nXdS(Ns8expected a float in the FloatCol '%s', got %s %r instead(svaluesNones isinstancesintslongsfloats sqlbuilders SQLExpressions validatorssInvalidsselfsnamestypesstate(sselfsvaluesstate((s+build/bdist.linux-i686/egg/sqlobject/col.pys to_pythons cCsl|tjotSnt|ttttif o/ti d|i t ||f||n|SdS(Ns8expected a float in the FloatCol '%s', got %s %r instead(svaluesNones isinstancesintslongsfloats sqlbuilders SQLExpressions validatorssInvalidsselfsnamestypesstate(sselfsvaluesstate((s+build/bdist.linux-i686/egg/sqlobject/col.pys from_pythons   (s__name__s __module__s to_pythons from_python(((s+build/bdist.linux-i686/egg/sqlobject/col.pysFloatValidators s SOFloatColcBs,tZdZdZdZdZRS(NcCstigSdS(N(sconstssisFloat(sself((s+build/bdist.linux-i686/egg/sqlobject/col.pysautoConstraintsscCs*td|igtt|iSdS(Nsname(sFloatValidatorsselfsnamessupers SOFloatColscreateValidators(sself((s+build/bdist.linux-i686/egg/sqlobject/col.pyscreateValidatorsscCsdSdS(NsFLOAT((sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys_sqlTypescCsdSdS(NsDOUBLE PRECISION((sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _mysqlTypes(s__name__s __module__sautoConstraintsscreateValidatorss_sqlTypes _mysqlType(((s+build/bdist.linux-i686/egg/sqlobject/col.pys SOFloatCols   sFloatColcBstZeZRS(N(s__name__s __module__s SOFloatCols baseClass(((s+build/bdist.linux-i686/egg/sqlobject/col.pysFloatColssSOKeyColcBsGtZdZdZdZdZdZdZdZRS(NcCsdSdS(NsINT((sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _mysqlTypescCsdSdS(NsINT((sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _sqliteTypescCsdSdS(NsINT((sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _postgresTypescCsdSdS(NsNUMERIC(18,0) NULL((sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _sybaseTypescCsdSdS(NsINT NULL((sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _mssqlTypescCsdSdS(NsINT((sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _firebirdTypescCsdSdS(NsINT((sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _maxdbTypes( s__name__s __module__s _mysqlTypes _sqliteTypes _postgresTypes _sybaseTypes _mssqlTypes _firebirdTypes _maxdbType(((s+build/bdist.linux-i686/egg/sqlobject/col.pysSOKeyCols      sKeyColcBstZeZRS(N(s__name__s __module__sSOKeyCols baseClass(((s+build/bdist.linux-i686/egg/sqlobject/col.pysKeyColss SOForeignKeycBsGtZdZdZdZdZdZdZdZRS(NcKs|d}|dii}|id o |i|i||d None counts as 0; everything else uses len() iN(sobjsNoneslen(sselfsobj((s+build/bdist.linux-i686/egg/sqlobject/col.pys _getlengths ( s__name__s __module__s__init__sautoConstraintsscreateValidatorss _mysqlTypes _postgresTypes _sqliteTypes _sybaseTypes _mssqlTypes _firebirdTypes _maxdbTypes _getlength(((s+build/bdist.linux-i686/egg/sqlobject/col.pys SOEnumColVs          s EnumValidatorcBstZdZdZRS(NcCsD||ijo|Sn)tid|i|i|f||dS(Ns;expected a member of %r in the EnumCol '%s', got %r instead(svaluesselfs enumValuess validatorssInvalidsnamesstate(sselfsvaluesstate((s+build/bdist.linux-i686/egg/sqlobject/col.pys to_pythonscCs|i||SdS(N(sselfs to_pythonsvaluesstate(sselfsvaluesstate((s+build/bdist.linux-i686/egg/sqlobject/col.pys from_pythons(s__name__s __module__s to_pythons from_python(((s+build/bdist.linux-i686/egg/sqlobject/col.pys EnumValidators sEnumColcBstZeZRS(N(s__name__s __module__s SOEnumCols baseClass(((s+build/bdist.linux-i686/egg/sqlobject/col.pysEnumColssDateTimeValidatorcBstZdZdZRS(NcCs|tjotSnt|titititifo|Sntot|t o|i i ddjp|i i ddjo8ti|i |i|i|i|it|iSqLti|i |i|iSqPt|toV|i i ddjotid|iSqLti|i|it|iSqPnyti||i }Wn8tid|i |it||f||nXti|d SdS(Ns%His%Ts%dssecondssZexpected an date/time string of the '%s' format in the DateTimeCol '%s', got %s %r insteadi(svaluesNones isinstancesdatetimesdatestimes sqlbuilders SQLExpressionsmxdatetime_availables DateTimeTypesselfsformatsfindsyearsmonthsdayshoursminutesintssecondsTimeTypes timedeltassecondssstrptimesstimes validatorssInvalidsnamestypesstate(sselfsvaluesstatesstime((s+build/bdist.linux-i686/egg/sqlobject/col.pys to_pythons( (2  *%cCs|tjotSnt|titititifo|Snt|do|i |i Snt i d|it||f||dS(Nsstrftimes>expected a datetime in the DateTimeCol '%s', got %s %r instead(svaluesNones isinstancesdatetimesdatestimes sqlbuilders SQLExpressionshasattrsstrftimesselfsformats validatorssInvalidsnamestypesstate(sselfsvaluesstate((s+build/bdist.linux-i686/egg/sqlobject/col.pys from_pythons ((s__name__s __module__s to_pythons from_python(((s+build/bdist.linux-i686/egg/sqlobject/col.pysDateTimeValidators sMXDateTimeValidatorcBstZdZdZRS(NcCsT|tjotSnt|tttifo|Sntot|tio2t i |i |i |i |i |i|iSqt|tio t i|i |i |i Sqt|tio t i|i |i|iSqnyti||i}Wn8tid|i|it||f||nXt i|SdS(NsZexpected an date/time string of the '%s' format in the DateTimeCol '%s', got %s %r instead(svaluesNones isinstances DateTimeTypesTimeTypes sqlbuilders SQLExpressionsdatetime_availablesdatetimesDateTimesyearsmonthsdayshoursminutessecondsdatesDatestimesTimesstrptimesselfsformatsstimes validatorssInvalidsnamestypesstatesmktime(sselfsvaluesstatesstime((s+build/bdist.linux-i686/egg/sqlobject/col.pys to_pythons$  $%cCs|tjotSnt|tttifo|Snt|do|i|i Snt i d|i t||f||dS(Nsstrftimes@expected a mxDateTime in the DateTimeCol '%s', got %s %r instead(svaluesNones isinstances DateTimeTypesTimeTypes sqlbuilders SQLExpressionshasattrsstrftimesselfsformats validatorssInvalidsnamestypesstate(sselfsvaluesstate((s+build/bdist.linux-i686/egg/sqlobject/col.pys from_pythons (s__name__s __module__s to_pythons from_python(((s+build/bdist.linux-i686/egg/sqlobject/col.pysMXDateTimeValidators s SODateTimeColcBs_tZdZdZdZdZdZdZdZdZ d Z d Z RS( Ns%Y-%m-%d %H:%M:%ScKs=t|d}|o ||_ntt|i|dS(NsdatetimeFormat(spopKeyskwsdatetimeFormatsselfssupers SODateTimeCols__init__(sselfskwsdatetimeFormat((s+build/bdist.linux-i686/egg/sqlobject/col.pys__init__s cCs{tt|i}ttjo t}ntt jo t }nto)|i d|d|i d|i n|SdS(Nisnamesformat(ssupers SODateTimeColsselfscreateValidatorss _validatorssdefault_datetime_implementationsDATETIME_IMPLEMENTATIONsDateTimeValidatorsvalidatorClasssMXDATETIME_IMPLEMENTATIONsMXDateTimeValidatorsinsertsnamesdatetimeFormat(sselfs _validatorssvalidatorClass((s+build/bdist.linux-i686/egg/sqlobject/col.pyscreateValidatorss    )cCsdSdS(NsDATETIME((sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _mysqlTypescCsdSdS(Ns TIMESTAMP((sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _postgresTypescCsdSdS(NsDATETIME((sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _sybaseTypescCsdSdS(NsDATETIME((sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _mssqlTypescCsdSdS(Ns TIMESTAMP((sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _sqliteTypescCsdSdS(Ns TIMESTAMP((sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _firebirdTypescCsdSdS(Ns TIMESTAMP((sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _maxdbTypes( s__name__s __module__sdatetimeFormats__init__screateValidatorss _mysqlTypes _postgresTypes _sybaseTypes _mssqlTypes _sqliteTypes _firebirdTypes _maxdbType(((s+build/bdist.linux-i686/egg/sqlobject/col.pys SODateTimeCols       s DateTimeColcBs#tZeZdZeeZRS(NcCsRttjotiiSn1ttjotiSndptdtdS(NisANo datetime implementation available (DATETIME_IMPLEMENTATION=%r)(sdefault_datetime_implementationsDATETIME_IMPLEMENTATIONsdatetimesnowsMXDATETIME_IMPLEMENTATIONsDateTimesAssertionError(((s+build/bdist.linux-i686/egg/sqlobject/col.pysnow s   (s__name__s __module__s SODateTimeCols baseClasssnows staticmethod(((s+build/bdist.linux-i686/egg/sqlobject/col.pys DateTimeCols s DateValidatorcBstZdZeZRS(NcCsat|tio|Sntt|i||}t|tio|i}n|SdS(N( s isinstancesvaluesdatetimesdatessupers DateValidatorsselfs to_pythonsstate(sselfsvaluesstate((s+build/bdist.linux-i686/egg/sqlobject/col.pys to_pythons (s__name__s __module__s to_pythons from_python(((s+build/bdist.linux-i686/egg/sqlobject/col.pys DateValidators s SODateColcBs_tZdZdZdZdZdZdZdZdZ d Z d Z RS( Ns%Y-%m-%dcKs=t|d}|o ||_ntt|i|dS(Ns dateFormat(spopKeyskws dateFormatsselfssupers SODateCols__init__(sselfskws dateFormat((s+build/bdist.linux-i686/egg/sqlobject/col.pys__init__%s cCs{tt|i}ttjo t}ntt jo t }nto)|i d|d|i d|i n|SdS(sCCreate a validator for the column. Can be overriden in descendants.isnamesformatN(ssupers SODateColsselfscreateValidatorss _validatorssdefault_datetime_implementationsDATETIME_IMPLEMENTATIONs DateValidatorsvalidatorClasssMXDATETIME_IMPLEMENTATIONsMXDateTimeValidatorsinsertsnames dateFormat(sselfs _validatorssvalidatorClass((s+build/bdist.linux-i686/egg/sqlobject/col.pyscreateValidators*s    )cCsdSdS(NsDATE((sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _mysqlType5scCsdSdS(NsDATE((sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _postgresType8scCs|iSdS(N(sselfs _postgresType(sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _sybaseType;scCsdSdS(sW SQL Server doesn't have a DATE data type, to emulate we use a vc(10) s VARCHAR(10)N((sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _mssqlType>scCsdSdS(NsDATE((sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _firebirdTypeDscCsdSdS(NsDATE((sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _maxdbTypeGscCsdSdS(NsDATE((sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _sqliteTypeJs( s__name__s __module__s dateFormats__init__screateValidatorss _mysqlTypes _postgresTypes _sybaseTypes _mssqlTypes _firebirdTypes _maxdbTypes _sqliteType(((s+build/bdist.linux-i686/egg/sqlobject/col.pys SODateCol"s       sDateColcBstZeZRS(N(s__name__s __module__s SODateCols baseClass(((s+build/bdist.linux-i686/egg/sqlobject/col.pysDateColMss TimeValidatorcBstZdZRS(NcCsat|tio|Sntt|i||}t|tio|i}n|SdS(N( s isinstancesvaluesdatetimestimessupers TimeValidatorsselfs to_pythonsstate(sselfsvaluesstate((s+build/bdist.linux-i686/egg/sqlobject/col.pys to_pythonSs (s__name__s __module__s to_python(((s+build/bdist.linux-i686/egg/sqlobject/col.pys TimeValidatorRss SOTimeColcBsVtZdZdZdZdZdZdZdZdZ d Z RS( Ns%H:%M:%ScKs=t|d}|o ||_ntt|i|dS(Ns timeFormat(spopKeyskws timeFormatsselfssupers SOTimeCols__init__(sselfskws timeFormat((s+build/bdist.linux-i686/egg/sqlobject/col.pys__init__^s cCs{tt|i}ttjo t}ntt jo t }nto)|i d|d|i d|i n|SdS(Nisnamesformat(ssupers SOTimeColsselfscreateValidatorss _validatorssdefault_datetime_implementationsDATETIME_IMPLEMENTATIONs TimeValidatorsvalidatorClasssMXDATETIME_IMPLEMENTATIONsMXDateTimeValidatorsinsertsnames timeFormat(sselfs _validatorssvalidatorClass((s+build/bdist.linux-i686/egg/sqlobject/col.pyscreateValidatorsds    )cCsdSdS(NsTIME((sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _mysqlTypenscCsdSdS(NsTIME((sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _postgresTypeqscCsdSdS(NsTIME((sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _sybaseTypetscCsdSdS(NsTIME((sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _sqliteTypewscCsdSdS(NsTIME((sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _firebirdTypezscCsdSdS(NsTIME((sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _maxdbType}s( s__name__s __module__s timeFormats__init__screateValidatorss _mysqlTypes _postgresTypes _sybaseTypes _sqliteTypes _firebirdTypes _maxdbType(((s+build/bdist.linux-i686/egg/sqlobject/col.pys SOTimeCol[s      sTimeColcBstZeZRS(N(s__name__s __module__s SOTimeCols baseClass(((s+build/bdist.linux-i686/egg/sqlobject/col.pysTimeColss SODecimalColcBstZdZdZRS(NcKsxt|dt|_|itj p tdt|dt|_|itj p tdtt|i |dS(NssizesYou must give a size arguments precisions"You must give a precision argument( spopKeyskws NoDefaultsselfssizesAssertionErrors precisionssupers SODecimalCols__init__(sselfskw((s+build/bdist.linux-i686/egg/sqlobject/col.pys__init__s cCsd|i|ifSdS(NsDECIMAL(%i, %i)(sselfssizes precision(sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys_sqlTypes(s__name__s __module__s__init__s_sqlType(((s+build/bdist.linux-i686/egg/sqlobject/col.pys SODecimalCols s DecimalColcBstZeZRS(N(s__name__s __module__s SODecimalCols baseClass(((s+build/bdist.linux-i686/egg/sqlobject/col.pys DecimalColss SOCurrencyColcBstZdZRS(NcKs:t|ddt|ddtt|i|dS(Nssizei s precisioni(spushKeyskwssupers SOCurrencyColsselfs__init__(sselfskw((s+build/bdist.linux-i686/egg/sqlobject/col.pys__init__s(s__name__s __module__s__init__(((s+build/bdist.linux-i686/egg/sqlobject/col.pys SOCurrencyColss CurrencyColcBstZeZRS(N(s__name__s __module__s SOCurrencyCols baseClass(((s+build/bdist.linux-i686/egg/sqlobject/col.pys CurrencyColssBinaryValidatorcBs&tZdZeZdZdZRS(s Validator for binary types. We're assuming that the per-database modules provide some form of wrapper type for binary conversion. cCs |tjotSnt|to@|iii}|iddfjo|i |}n|Snt|t |iii foY|i }|o|d|jo |dSnt|to|iSnt|Sntid|it||f||dS(Nssqlitespysqlite2.dbapi2iis8expected a string in the BLOBCol '%s', got %s %r instead(svaluesNones isinstancesstrsstatessoObjects _connectionsmodules__name__sdecodes buffer_types _binaryTypesselfs _cachedValues cachedValues array_typestostrings validatorssInvalidsnamestype(sselfsvaluesstatesmodules cachedValue((s+build/bdist.linux-i686/egg/sqlobject/col.pys to_pythons    cCsA|tjotSn|iii|}||f|_|SdS(N( svaluesNonesstatessoObjects _connections createBinarysbinarysselfs _cachedValue(sselfsvaluesstatesbinary((s+build/bdist.linux-i686/egg/sqlobject/col.pys from_pythons  (s__name__s __module__s__doc__sNones _cachedValues to_pythons from_python(((s+build/bdist.linux-i686/egg/sqlobject/col.pysBinaryValidators  s SOBLOBColcBs,tZdZdZdZdZRS(NcCs*td|igtt|iSdS(Nsname(sBinaryValidatorsselfsnamessupers SOBLOBColscreateValidators(sself((s+build/bdist.linux-i686/egg/sqlobject/col.pyscreateValidatorsscCs|i}|i}|ddjo|odpdSn|ddjo|odpdSn|ddjo|od pd Sn|od pd SdS( NiisLONGTEXTsLONGBLOBis MEDIUMTEXTs MEDIUMBLOBisTEXTsBLOBsTINYTEXTsTINYBLOB(sselfslengthsvarchar(sselfsvarcharslength((s+build/bdist.linux-i686/egg/sqlobject/col.pys _mysqlTypes  cCsdSdS(NsBYTEA((sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _postgresTypescCsdSdS(NsIMAGE((sself((s+build/bdist.linux-i686/egg/sqlobject/col.pys _mssqlTypes(s__name__s __module__screateValidatorss _mysqlTypes _postgresTypes _mssqlType(((s+build/bdist.linux-i686/egg/sqlobject/col.pys SOBLOBCols  sBLOBColcBstZeZRS(N(s__name__s __module__s SOBLOBCols baseClass(((s+build/bdist.linux-i686/egg/sqlobject/col.pysBLOBColssPickleValidatorcBs tZdZdZdZRS(s  Validator for pickle types. A pickle type is simply a binary type with hidden pickling, so that we can simply store any kind of stuff in a particular column. The support for this relies directly on the support for binary for your database. cCs|tjotSnt|to|id}nt|toti|Snti d|i t ||f||dS(NsasciisAexpected a pickle string in the PickleCol '%s', got %s %r instead(svaluesNones isinstancesunicodesencodesstrspicklesloadss validatorssInvalidsselfsnamestypesstate(sselfsvaluesstate((s+build/bdist.linux-i686/egg/sqlobject/col.pys to_pythons cCs&|tjotSnti|SdS(N(svaluesNonespicklesdumps(sselfsvaluesstate((s+build/bdist.linux-i686/egg/sqlobject/col.pys from_pythons (s__name__s __module__s__doc__s to_pythons from_python(((s+build/bdist.linux-i686/egg/sqlobject/col.pysPickleValidators  s SOPickleColcBstZdZdZRS(NcKs/t|dd|_tt|i|dS(NspickleProtocoli(spopKeyskwsselfspickleProtocolssupers SOPickleCols__init__(sselfskw((s+build/bdist.linux-i686/egg/sqlobject/col.pys__init__scCs3td|id|igtt|iSdS(NsnamespickleProtocol(sPickleValidatorsselfsnamespickleProtocolssupers SOPickleColscreateValidators(sself((s+build/bdist.linux-i686/egg/sqlobject/col.pyscreateValidatorss(s__name__s __module__s__init__screateValidators(((s+build/bdist.linux-i686/egg/sqlobject/col.pys SOPickleCols s PickleColcBstZeZRS(N(s__name__s __module__s SOPickleCols baseClass(((s+build/bdist.linux-i686/egg/sqlobject/col.pys PickleColscCs2|i| o|Sn||}||=|SdS(N(skwshas_keysnamesdefaultsvalue(skwsnamesdefaultsvalue((s+build/bdist.linux-i686/egg/sqlobject/col.pyspopKeys  cCs#|i| o|||scs ||S(N(sdbColumnToPythonAttrsssa(sass(sdbColumnToPythonAttr(s.build/bdist.linux-i686/egg/sqlobject/styles.pysscs ||S(N(spythonClassToDBTablesssa(sass(spythonClassToDBTable(s.build/bdist.linux-i686/egg/sqlobject/styles.pysscs ||S(N(sdbTableToPythonClasssssa(sass(sdbTableToPythonClass(s.build/bdist.linux-i686/egg/sqlobject/styles.pysscs ||S(N(s idForTablesssa(sass(s idForTable(s.build/bdist.linux-i686/egg/sqlobject/styles.pys s(spythonAttrToDBColumnsselfsdbColumnToPythonAttrspythonClassToDBTablesdbTableToPythonClasss idForTableslongID(sselfspythonAttrToDBColumnsdbColumnToPythonAttrspythonClassToDBTablesdbTableToPythonClasss idForTableslongID((spythonAttrToDBColumnsdbColumnToPythonAttrspythonClassToDBTablesdbTableToPythonClasss idForTables.build/bdist.linux-i686/egg/sqlobject/styles.pys__init__scCs|SdS(N(sattr(sselfsattr((s.build/bdist.linux-i686/egg/sqlobject/styles.pyspythonAttrToDBColumn#scCs|SdS(N(scol(sselfscol((s.build/bdist.linux-i686/egg/sqlobject/styles.pysdbColumnToPythonAttr&scCs|SdS(N(s className(sselfs className((s.build/bdist.linux-i686/egg/sqlobject/styles.pyspythonClassToDBTable)scCs|SdS(N(stable(sselfstable((s.build/bdist.linux-i686/egg/sqlobject/styles.pysdbTableToPythonClass,scCs#|io|i|SndSdS(Nsid(sselfslongIDstableReferencestable(sselfstable((s.build/bdist.linux-i686/egg/sqlobject/styles.pys idForTable/s cCst|SdS(N(s lowerwords className(sselfs className((s.build/bdist.linux-i686/egg/sqlobject/styles.pyspythonClassToAttr5scCs |dSdS(NsID(sattr(sselfsattr((s.build/bdist.linux-i686/egg/sqlobject/styles.pysinstanceAttrToIDAttr8scCs |dSdS(Ns_id(stable(sselfstable((s.build/bdist.linux-i686/egg/sqlobject/styles.pystableReference=s(s__name__s __module__s__doc__sNonesFalses__init__spythonAttrToDBColumnsdbColumnToPythonAttrspythonClassToDBTablesdbTableToPythonClasss idForTablespythonClassToAttrsinstanceAttrToIDAttrstableReference(((s.build/bdist.linux-i686/egg/sqlobject/styles.pysStyles        cBsDtZdZdZdZdZdZdZdZRS(s{ This is the default style. Python attributes use mixedCase, while database columns use underscore_separated. cCst|SdS(N(s mixedToUndersattr(sselfsattr((s.build/bdist.linux-i686/egg/sqlobject/styles.pyspythonAttrToDBColumnGscCst|SdS(N(s underToMixedscol(sselfscol((s.build/bdist.linux-i686/egg/sqlobject/styles.pysdbColumnToPythonAttrJscCs |dit|dSdS(Nii(s classNameslowers mixedToUnder(sselfs className((s.build/bdist.linux-i686/egg/sqlobject/styles.pyspythonClassToDBTableMscCs |dit|dSdS(Nii(stablesuppers underToMixed(sselfstable((s.build/bdist.linux-i686/egg/sqlobject/styles.pysdbTableToPythonClassQscCs|i|i|SdS(N(sselfstableReferencespythonClassToDBTables className(sselfs className((s.build/bdist.linux-i686/egg/sqlobject/styles.pyspythonClassToDBTableReferenceUscCs |dSdS(Ns_id(stable(sselfstable((s.build/bdist.linux-i686/egg/sqlobject/styles.pystableReferenceXs( s__name__s __module__s__doc__spythonAttrToDBColumnsdbColumnToPythonAttrspythonClassToDBTablesdbTableToPythonClassspythonClassToDBTableReferencestableReference(((s.build/bdist.linux-i686/egg/sqlobject/styles.pysMixedCaseUnderscoreStyle@s      cBs2tZdZdZdZdZdZRS(st This style leaves columns as mixed-case, and uses long ID names (like ProductID instead of simply id). cCst|SdS(N(scapwordsattr(sselfsattr((s.build/bdist.linux-i686/egg/sqlobject/styles.pyspythonAttrToDBColumndscCst|SdS(N(s lowerwordscol(sselfscol((s.build/bdist.linux-i686/egg/sqlobject/styles.pysdbColumnToPythonAttrgscCst|SdS(N(scapwordstable(sselfstable((s.build/bdist.linux-i686/egg/sqlobject/styles.pysdbTableToPythonClassjscCs |dSdS(NsID(stable(sselfstable((s.build/bdist.linux-i686/egg/sqlobject/styles.pystableReferencems(s__name__s __module__s__doc__spythonAttrToDBColumnsdbColumnToPythonAttrsdbTableToPythonClassstableReference(((s.build/bdist.linux-i686/egg/sqlobject/styles.pysMixedCaseStyle]s    cCs|tjo!t|do |i}q.nt|ido |iio|iiSn!|o|io |iSntSdS(Ns _connectionsstyle(s dbConnectionsNoneshasattrssoClasss _connectionssqlmetasstyles defaultStyle(ssoClasss dbConnection((s.build/bdist.linux-i686/egg/sqlobject/styles.pysgetStylers   s[A-Z]+cCs^|idot|d dSntit|}|ido|d}n|SdS(NsIDis_ids_i(sssendswiths mixedToUnders_mixedToUnderREssubsmixedToUnderSubstranss startswith(ssstrans((s.build/bdist.linux-i686/egg/sqlobject/styles.pys mixedToUnders cCsN|idi}t|djod|d |dfSn d|SdS(Niis_%s_%sis_%s(smatchsgroupslowersmslen(smatchsm((s.build/bdist.linux-i686/egg/sqlobject/styles.pysmixedToUnderSubscCs|di|dSdS(Nii(sssupper(ss((s.build/bdist.linux-i686/egg/sqlobject/styles.pyscapwordscCs|di|dSdS(Nii(ssslower(ss((s.build/bdist.linux-i686/egg/sqlobject/styles.pys lowerwordss_.cCs=|idot|d dSntid|SdS(Ns_idisIDcCs|iddiS(Nii(smsgroupsupper(sm((s.build/bdist.linux-i686/egg/sqlobject/styles.pyss(snamesendswiths underToMixeds_underToMixedREssub(sname((s.build/bdist.linux-i686/egg/sqlobject/styles.pys underToMixeds (sres__all__sTruesFalsesobjectsStylesMixedCaseUnderscoreStyles DefaultStylesMixedCaseStyles defaultStylesNonesgetStylescompiles_mixedToUnderREs mixedToUndersmixedToUnderSubscapwords lowerwords_underToMixedREs underToMixed(s lowerwordsStylesFalses defaultStyles__all__s_underToMixedREsmixedToUnderSubs mixedToUndersresgetStyles DefaultStyles underToMixedsMixedCaseUnderscoreStylesMixedCaseStyles_mixedToUnderREsTruescapword((s.build/bdist.linux-i686/egg/sqlobject/styles.pys?s 8      PKb95^AAsqlobject/joins.pyc; Ec@sdkZeiZdkZdkZdklZdddddgZdZdefd YZ d efd YZ d Z d e fdYZ de fdYZ de fdYZde fdYZde fdYZde fdYZdeifdYZdeifdYZdeifdYZdefdYZdefdYZdZd e fd!YZde fd"YZdS(#N(spopKeys MultipleJoinsSQLMultipleJoins RelatedJoinsSQLRelatedJoins SingleJoincCs/y |iSWntj ot|SnXdS(N(sobjsidsAttributeErrorsint(sobj((s-build/bdist.linux-i686/egg/sqlobject/joins.pysgetID s sJoincBsDtZedZdZdZeeeZeZdZ RS(NcKsL||d<||_|iidot|id|_n t|_dS(Ns otherClasssjoinMethodName(s otherClassskwsselfshas_keyspopKeys_joinMethodNamesNone(sselfs otherClassskw((s-build/bdist.linux-i686/egg/sqlobject/joins.pys__init__s   cCsD|i|jp |itjptd|i|f||_dS(NsXYou have already given an explicit joinMethodName (%s), and you are now setting it to %s(sselfs_joinMethodNamesvaluesNonesAssertionError(sselfsvalue((s-build/bdist.linux-i686/egg/sqlobject/joins.pys_set_joinMethodNames7cCs |iSdS(N(sselfs_joinMethodName(sself((s-build/bdist.linux-i686/egg/sqlobject/joins.pys_get_joinMethodNamescCsZ|iido|id|_|id=n|id|d|d|i|iSdS(NsjoinMethodNamessoClasssjoinDef(sselfskwshas_keys_joinMethodNames baseClassssoClass(sselfssoClass((s-build/bdist.linux-i686/egg/sqlobject/joins.pys withClass#s  ( s__name__s __module__sNones__init__s_set_joinMethodNames_get_joinMethodNamespropertysjoinMethodNamesnames withClass(((s-build/bdist.linux-i686/egg/sqlobject/joins.pysJoins    sSOJoincBs>tZeeeeeedZdZdZdZRS(NcCs||_||_||_ti|iii||i ||_ ||_ ||_ |i o+t i|ii|iii|_ ndS(N(ssoClasssselfsjoinDefs otherClasssotherClassNames classregistrysregistryssqlmetasaddClassCallbacks_setOtherClasss joinColumnsjoinMethodNamesorderBysstylessgetStylestableReferencestable(sselfssoClasss otherClasss joinColumnsjoinMethodNamesorderBysjoinDef((s-build/bdist.linux-i686/egg/sqlobject/joins.pys__init__1s   "    cCs ||_dS(N(sclssselfs otherClass(sselfscls((s-build/bdist.linux-i686/egg/sqlobject/joins.pys_setOtherClassGscCstSdS(N(sFalse(sself((s-build/bdist.linux-i686/egg/sqlobject/joins.pyshasIntermediateTableJscCsU|itjo|ii|_n|itj o|it |in|SdS(N( sselfsorderBys NoDefaultsdefaultSortClassssqlmetas defaultOrdersNonesresultsssortssorter(sselfsresultssdefaultSortClass((s-build/bdist.linux-i686/egg/sqlobject/joins.pys _applyOrderByMs (s__name__s __module__sNones NoDefaults__init__s_setOtherClassshasIntermediateTables _applyOrderBy(((s-build/bdist.linux-i686/egg/sqlobject/joins.pysSOJoin/s  cCst|tp t|toRt|djo|d}qrt|d}t|d}||dSnt|ti ot|i ti od|i i }n!t|ti o |i }n|i do|d}t}nt}||d}|SdS(NiicCs|||p |||S(N(sfheadsasbsfrest(sasbsfheadsfrest((s-build/bdist.linux-i686/egg/sqlobject/joins.pys[ss-cCst||}t||}|o||f\}}n|tjo|tjodSndSn|tjodSnt||SdS(Niii(sgetattrsasattrsbsrevsNonescmp(sasbsattrsrev((s-build/bdist.linux-i686/egg/sqlobject/joins.pyscmperhs   (s isinstancesorderBystupleslistslenssortersfheadsfrests sqlbuildersDESCsexprsSQLObjectFieldsoriginals startswithsTruesreversesFalsescmper(sorderBysfheadsfrestscmpersreverse((s-build/bdist.linux-i686/egg/sqlobject/joins.pyssorterTs  )    sSOMultipleJoincBstZedZdZRS(NcKsti|||i oS|idi|id}|ido|d}n |d}||_n| ot |i|_ n ||_ dS(Niissses( sSOJoins__init__sselfskwsjoinMethodNamesotherClassNameslowersnamesendswiths addRemoveNames capitalize(sselfs addRemoveNameskwsname((s-build/bdist.linux-i686/egg/sqlobject/joins.pys__init__ys   cCs|ii|i|i|i}|ii o |i}nt }|i gi }|D]3\}|t j o||ii||qUqU~|iSdS(N(sinsts _connections_SO_selectJoinsselfs otherClasss joinColumnsidsidsssqlmetas_perConnectionsconnsNones _applyOrderBysappends_[1]sget(sselfsinstsidss_[1]sidsconn((s-build/bdist.linux-i686/egg/sqlobject/joins.pys performJoins   (s__name__s __module__sNones__init__s performJoin(((s-build/bdist.linux-i686/egg/sqlobject/joins.pysSOMultipleJoinws cBstZeZRS(N(s__name__s __module__sSOMultipleJoins baseClass(((s-build/bdist.linux-i686/egg/sqlobject/joins.pys MultipleJoinssSOSQLMultipleJoincBstZdZRS(NcCs|iio |i}nt}|iit |ii |i ii i |i|ijd|}|itjo|iii|_n|i|iSdS(Ns connection(sinstssqlmetas_perConnections _connectionsconnsNonesselfs otherClasssselectsgetattrsqssoClasssstylesdbColumnToPythonAttrs joinColumnsidsresultssorderBys NoDefaults defaultOrder(sselfsinstsresultssconn((s-build/bdist.linux-i686/egg/sqlobject/joins.pys performJoins  E(s__name__s __module__s performJoin(((s-build/bdist.linux-i686/egg/sqlobject/joins.pysSOSQLMultipleJoinscBstZeZRS(N(s__name__s __module__sSOSQLMultipleJoins baseClass(((s-build/bdist.linux-i686/egg/sqlobject/joins.pysSQLMultipleJoinss SORelatedJoincBsGtZeeedZdZdZdZdZdZ RS(NcKsW||_||_||_ti||ti|i i ii |i |i dS(N(sintermediateTablesselfs otherColumnscreateRelatedTablesSOMultipleJoins__init__skws classregistrysregistryssoClassssqlmetasaddClassCallbacksotherClassNames_setOtherRelatedClass(sselfs otherColumnsintermediateTablescreateRelatedTableskw((s-build/bdist.linux-i686/egg/sqlobject/joins.pys__init__s    cCs|i oD|iii|iig}|id|d|df|_n|i o%|iii i |ii|_ndS(Ns%s_%sii( sselfsintermediateTablessoClassssqlmetastables otherClasssnamesssorts otherColumnsstylestableReference(sselfs otherClasssnames((s-build/bdist.linux-i686/egg/sqlobject/joins.pys_setOtherRelatedClasss    cCstSdS(N(sTrue(sself((s-build/bdist.linux-i686/egg/sqlobject/joins.pyshasIntermediateTablescCs|ii|i|i|i|i}|i i o |i}nt }|i gi}|D]3\}|t j o||ii||q[q[~|iSdS(N(sinsts _connections_SO_intermediateJoinsselfsintermediateTables otherColumns joinColumnsidsidsssqlmetas_perConnectionsconnsNones _applyOrderBysappends_[1]s otherClasssget(sselfsinstsidss_[1]sidsconn((s-build/bdist.linux-i686/egg/sqlobject/joins.pys performJoins   cCs5|ii|i|it||it|dS(N( sinsts _connections_SO_intermediateDeletesselfsintermediateTables joinColumnsgetIDs otherColumnsother(sselfsinstsother((s-build/bdist.linux-i686/egg/sqlobject/joins.pysremoves  cCs5|ii|i|it||it|dS(N( sinsts _connections_SO_intermediateInsertsselfsintermediateTables joinColumnsgetIDs otherColumnsother(sselfsinstsother((s-build/bdist.linux-i686/egg/sqlobject/joins.pysadds  ( s__name__s __module__sNonesTrues__init__s_setOtherRelatedClassshasIntermediateTables performJoinsremovesadd(((s-build/bdist.linux-i686/egg/sqlobject/joins.pys SORelatedJoins   cBstZeZRS(N(s__name__s __module__s SORelatedJoins baseClass(((s-build/bdist.linux-i686/egg/sqlobject/joins.pys RelatedJoinssOtherTableToJoincBstZdZdZRS(NcCs(||_||_||_||_dS(N(s otherTablesselfs otherIdNames interTables joinColumn(sselfs otherTables otherIdNames interTables joinColumn((s-build/bdist.linux-i686/egg/sqlobject/joins.pys__init__s   cCs$d|i|i|i|ifSdS(Ns %s.%s = %s.%s(sselfs otherTables otherIdNames interTables joinColumn(sselfsdb((s-build/bdist.linux-i686/egg/sqlobject/joins.pys __sqlrepr__s(s__name__s __module__s__init__s __sqlrepr__(((s-build/bdist.linux-i686/egg/sqlobject/joins.pysOtherTableToJoins s JoinToTablecBstZdZdZRS(NcCs(||_||_||_||_dS(N(stablesselfsidNames interTables joinColumn(sselfstablesidNames interTables joinColumn((s-build/bdist.linux-i686/egg/sqlobject/joins.pys__init__s   cCs$d|i|i|i|ifSdS(Ns %s.%s = %s.%s(sselfs interTables joinColumnstablesidName(sselfsdb((s-build/bdist.linux-i686/egg/sqlobject/joins.pys __sqlrepr__s(s__name__s __module__s__init__s __sqlrepr__(((s-build/bdist.linux-i686/egg/sqlobject/joins.pys JoinToTables s TableToIdcBstZdZdZRS(NcCs||_||_||_dS(N(stablesselfsidNamesidValue(sselfstablesidNamesidValue((s-build/bdist.linux-i686/egg/sqlobject/joins.pys__init__s  cCsd|i|i|ifSdS(Ns %s.%s = %s(sselfstablesidNamesidValue(sselfsdb((s-build/bdist.linux-i686/egg/sqlobject/joins.pys __sqlrepr__s(s__name__s __module__s__init__s __sqlrepr__(((s-build/bdist.linux-i686/egg/sqlobject/joins.pys TableToIds sSOSQLRelatedJoincBstZdZRS(NcCs|iitit|iii|iii|i |i t |i ii|i ii|i |i t|i ii|i ii|id|i ii|iii|i f}|itjo|iii|_n|i|iSdS(Ns clauseTables(sselfs otherClasssselects sqlbuildersANDsOtherTableToJoinssqlmetastablesidNamesintermediateTables otherColumns JoinToTablessoClasss joinColumns TableToIdsinstsidsresultssorderBys NoDefaults defaultOrder(sselfsinstsresults((s-build/bdist.linux-i686/egg/sqlobject/joins.pys performJoins*'*(s__name__s __module__s performJoin(((s-build/bdist.linux-i686/egg/sqlobject/joins.pysSOSQLRelatedJoinscBstZeZRS(N(s__name__s __module__sSOSQLRelatedJoins baseClass(((s-build/bdist.linux-i686/egg/sqlobject/joins.pysSQLRelatedJoinscCs|di|dSdS(Nii(snames capitalize(sname((s-build/bdist.linux-i686/egg/sqlobject/joins.pys capitalizess SOSingleJoincBstZdZdZRS(NcKs)t|dt|_ti||dS(Ns makeDefault(spopKeyskwsFalsesselfs makeDefaultsSOMultipleJoins__init__(sselfskw((s-build/bdist.linux-i686/egg/sqlobject/joins.pys__init__scCs|iio |i}nt}|iiii |i }|i i t|i i||ijd|}|idjo7|i otSqh|d |<}|i |Sn |dSdS(Ns connectionii(sinstssqlmetas_perConnections _connectionsconnsNonesselfssoClasssstylesdbColumnToPythonAttrs joinColumns pythonColumns otherClasssselectsgetattrsqsidsresultsscounts makeDefaultskw(sselfsinsts pythonColumnsresultsskwsconn((s-build/bdist.linux-i686/egg/sqlobject/joins.pys performJoins  $  (s__name__s __module__s__init__s performJoin(((s-build/bdist.linux-i686/egg/sqlobject/joins.pys SOSingleJoins cBstZeZRS(N(s__name__s __module__s SOSingleJoins baseClass(((s-build/bdist.linux-i686/egg/sqlobject/joins.pys SingleJoin6s(s sqlbuilders NoDefaultsstyless classregistryscolspopKeys__all__sgetIDsobjectsJoinsSOJoinssortersSOMultipleJoins MultipleJoinsSOSQLMultipleJoinsSQLMultipleJoins SORelatedJoins RelatedJoins SQLExpressionsOtherTableToJoins JoinToTables TableToIdsSOSQLRelatedJoinsSQLRelatedJoins capitalizes SOSingleJoins SingleJoin(sSOMultipleJoins TableToIdsSOSQLMultipleJoinsgetIDs MultipleJoinspopKeys__all__sSOJoins RelatedJoins JoinToTablesSQLMultipleJoinsstyless NoDefaultsJoinssortersSQLRelatedJoins SORelatedJoins classregistrys capitalizes sqlbuildersSOSQLRelatedJoins SingleJoins SOSingleJoinsOtherTableToJoin((s-build/bdist.linux-i686/egg/sqlobject/joins.pys?s.       % # 9    PKb95/))sqlobject/declarative.pyc; Ec@sdZdklZdkZdddfZdkZydkZeiZWn%e j odZ e ZnXde fdYZ de fd YZ d Zdefd YZde fd YZdS( s Declarative objects. Declarative objects have a simple protocol: you can use classes in lieu of instances and they are equivalent, and any keyword arguments you give to the constructor will override those instance variables. (So if a class is received, we'll simply instantiate an instance with no arguments). You can provide a variable __unpackargs__ (a list of strings), and if the constructor is called with non-keyword arguments they will be interpreted as the given keyword arguments. If __unpackargs__ is ('*', name), then all the arguments will be put in a variable by that name. You can define a __classinit__(cls, new_attrs) method, which will be called when the class is created (including subclasses). Note: you can't use super() in __classinit__ because the class isn't bound to a name. As an analog to __classinit__, Declarative adds __instanceinit__ which is called with the same argument (new_attrs). This is like __init__, but after __unpackargs__ and other factors have been taken into account. If __mutableattributes__ is defined as a sequence of strings, these attributes will not be shared between superclasses and their subclasses. E.g., if you have a class variable that contains a list and you append to that list, changes to subclasses will effect superclasses unless you add the attribute here. Also defines classinstancemethod, which acts as either a class method or an instance method depending on where it is called. (s generatorsNsclassinstancemethodsDeclarativeMetas Declarativeccs'd}xno|d7}|VqWdS(Nii(si(si((s3build/bdist.linux-i686/egg/sqlobject/declarative.pys_counter.s  cBs#tZdZdZedZRS(s Acts like a class method when called from a class, like an instance method when called by an instance. The method should take two arguments, 'self' and 'cls'; one of these will be None depending on how the method was called. cCs ||_dS(N(sfuncsself(sselfsfunc((s3build/bdist.linux-i686/egg/sqlobject/declarative.pys__init__=scCst|id|d|SdS(Nsobjstype(s_methodwrappersselfsfuncsobjstype(sselfsobjstype((s3build/bdist.linux-i686/egg/sqlobject/declarative.pys__get__@s(s__name__s __module__s__doc__s__init__sNones__get__(((s3build/bdist.linux-i686/egg/sqlobject/declarative.pysclassinstancemethod5s  s_methodwrappercBs#tZdZdZdZRS(NcCs||_||_||_dS(N(sfuncsselfsobjstype(sselfsfuncsobjstype((s3build/bdist.linux-i686/egg/sqlobject/declarative.pys__init__Es  cOsP|id o|id p td|i|i|if||SdS(NsselfsclssAYou cannot use 'self' or 'cls' arguments to a classinstancemethod(skwshas_keysAssertionErrorsselfsfuncsobjstypesargs(sselfsargsskw((s3build/bdist.linux-i686/egg/sqlobject/declarative.pys__call__Js,cCsR|itjod|ii|iifSn!d|ii|ii|ifSdS(Nss(sselfsobjsNonestypes__name__sfuncs func_name(sself((s3build/bdist.linux-i686/egg/sqlobject/declarative.pys__repr__Ps(s__name__s __module__s__init__s__call__s__repr__(((s3build/bdist.linux-i686/egg/sqlobject/declarative.pys_methodwrapperCs  csd}|SdS(Ncs=d}yi|_Wntj onX|SdS(Ncs0iz|||SWdiXdS(N(slocksacquiresfnsselfsargsskwargssrelease(sselfsargsskwargs(slocksfn(s3build/bdist.linux-i686/egg/sqlobject/declarative.pys_wrapperZs  (s_wrappersfns func_names TypeError(sfns_wrapper(slock(sfns3build/bdist.linux-i686/egg/sqlobject/declarative.pys decoratorYs (s decorator(slocks decorator((slocks3build/bdist.linux-i686/egg/sqlobject/declarative.pysthreadSafeMethodXs cBstZdZRS(NcCsti||||}|idot|i i |_ n|i |||ido(t i }t||i|_n|SdS(Ns __classinit__s__init__(stypes__new__smetas class_namesbasess new_attrssclsshas_keys staticmethods __classinit__sim_funcs threadingsRLockslocksthreadSafeMethods__init__(smetas class_namesbasess new_attrsslockscls((s3build/bdist.linux-i686/egg/sqlobject/declarative.pys__new__is (s__name__s __module__s__new__(((s3build/bdist.linux-i686/egg/sqlobject/declarative.pysDeclarativeMetagscBs}tZfZfZeZdZdZdZdZ dZ e e Z dZ dZ ee Z e e Z RS(NcCs[ti|_xE|iD]:}|i| o#t|t i t ||qqWdS(N( scountersnextsclssdeclarative_counts__mutableattributes__snames new_attrsshas_keyssetattrscopysgetattr(sclss new_attrssname((s3build/bdist.linux-i686/egg/sqlobject/declarative.pys __classinit__{s  cCsUx*|iD]\}}t|||q W|id oti|_ ndS(Nsdeclarative_count( s new_attrssitemssnamesvaluessetattrsselfshas_keyscountersnextsdeclarative_count(sselfs new_attrssnamesvalue((s3build/bdist.linux-i686/egg/sqlobject/declarative.pys__instanceinit__s  cOs|io|iddjoft|idjptd|i|id}|i|otd|n|||s<%s %s>s (sselfs __class__s__name__snames__dict__scopysvsclsshas_keyskeyssnamessargss _repr_varssnsappendsjoin(sselfsclssnamesargssnsnamessv((s3build/bdist.linux-i686/egg/sqlobject/declarative.pys__repr__s     cCs[gi}|D]2}|id o |djo||qq~}|i|SdS(Ns_sdeclarative_count(sappends_[1]s dictNamessns startswithsnamesssort(s dictNamess_[1]snamessn((s3build/bdist.linux-i686/egg/sqlobject/declarative.pys _repr_varssI (s__name__s __module__s__unpackargs__s__mutableattributes__sDeclarativeMetas __metaclass__s __classinit__s__instanceinit__s__init__s__call__s singletonsclassinstancemethods__repr__s _repr_varss staticmethod(((s3build/bdist.linux-i686/egg/sqlobject/declarative.pys Declarativess        (s__doc__s __future__s generatorss threadings__all__scopys itertoolsscountscounters ImportErrors_countersobjectsclassinstancemethods_methodwrappersthreadSafeMethodstypesDeclarativeMetas Declarative( s_countersclassinstancemethods__all__scountersDeclarativeMetas threadings itertoolss Declaratives generatorssthreadSafeMethodscopys_methodwrapper((s3build/bdist.linux-i686/egg/sqlobject/declarative.pys?!s       PKb95&sqlobject/main.pyc; Ec@sSdZdkZdkZdkZdkZdkZdkZdkZdkZdk Z dk Z dk Z dk l Z dklZlZdkZeid dddfjo edneiZdefd YZd efd YZd d jdd jf\ZZd ZdZedZdZeeedZ dfdYZ!de"fdYZ#ei$Z%de"fdYZ&d a'ea(d ddZ)d edZ*de"fdYZ+dZ,dZ-dZ.dZ/d Z0d!Z1d"e"fd#YZ2d$Z3d%Z4d&ddd'd(dd)d*gZ5dS(+sz SQLObject --------- :author: Ian Bicking SQLObject is a object-relational mapper. See SQLObject.html or SQLObject.txt for more. Modified by Daniel Savard, Xsoli Inc 7 Feb 2004 - Added support for simple table inheritance. Oleg Broytmann, SIA "ANK" 3 Feb 2005 - Split inheritance support into a number of separate modules and classes - InheritableSQLObject at al. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. N(s SelectResults(sschemascompoundiiis(SQLObject requires Python 2.2.0 or latersSQLObjectNotFoundcBstZRS(N(s__name__s __module__(((s,build/bdist.linux-i686/egg/sqlobject/main.pysSQLObjectNotFound7ssSQLObjectIntegrityErrorcBstZRS(N(s__name__s __module__(((s,build/bdist.linux-i686/egg/sqlobject/main.pysSQLObjectIntegrityError8sic sttod}}nd}i}h}x|iD]\}}|i do||i |dhdti|iD]'}t||o|i|qqW|SdS(N(sdependss classregistrysregistrys allClassessklasssfindDependantColumnssnamesappend(snamesregistrysdependssklass((s,build/bdist.linux-i686/egg/sqlobject/main.pysfindDependencies~s cCsVg}xE|iiD]7}|i|jo |itj o|i |qqW|SdS(N( sdependssklassssqlmetas columnListscols foreignKeysnamescascadesNonesappend(snamesklasssdependsscol((s,build/bdist.linux-i686/egg/sqlobject/main.pysfindDependantColumnss   c Csg}xg|iD]Y\}}t||o=|i||o ||_ n|ot ||qlqqW|o|i dn|SdS(sV Finds all attributes in `new_attrs` that are instances of `look_for_class`. Returns them as a list. If `delete` is true they are also removed from the `cls`. If `set_name` is true, then the ``.name`` attribute is set for any matching objects. If `sort` is true, then they will be sorted by ``obj.creationOrder``. cCst|i|iS(N(scmpsas creationOrdersb(sasb((s,build/bdist.linux-i686/egg/sqlobject/main.pyssN(sresults new_attrssitemssattrsvalues isinstanceslook_for_classsappendsset_namesnamesdeletesdelattrsclsssort( sclss new_attrsslook_for_classsdeletesset_namessortsattrsvaluesresult((s,build/bdist.linux-i686/egg/sqlobject/main.pys_collectAttributess   sCreateNewSQLObjectcBstZdZRS(sW Dummy singleton to use in place of an ID, to signal we want a new object. (s__name__s __module__s__doc__(((s,build/bdist.linux-i686/egg/sqlobject/main.pysCreateNewSQLObjects ssqlmetacBsXtZdZeZeZeZeZeZ e Z eZ e ZeZe Ze ZhZgZhZgZgZgZgZeiZdddgZe Ze Ze ZdZ dZ!dZ"e#e"Z"e edZ$e#e$Z$edZ%e#e%Z%e ed Z&e#e&Z&d Z'e#e'Z'd Z(e#e(Z(d Z)e#e)Z)RS( s This object is the object we use to keep track of all sorts of information. Subclasses are made for each SQLObject subclass (dynamically if necessary), and instances are created to go alongside every SQLObject instance. stablesidNamescolumnscCs=x6|iD]+}|i| ot||tq q WdS(N(sclss_unshared_attributessattrs new_attrsshas_keyssetattrsNone(sclss new_attrssattr((s,build/bdist.linux-i686/egg/sqlobject/main.pys __classinit__s cCs ||_dS(N(sinstancesself(sselfsinstance((s,build/bdist.linux-i686/egg/sqlobject/main.pys__init__scCs_||_|i o]ti|_y7|iio |iiio|iii|_nWqqtj oqqXn|itjo|ii |ii |_n|i tjo|ii |i|_ nh|_ h|_h|_h|_h|_h|_h|_h|_g|_|ii|_g|_|i|_g|_|i|_dS(N(ssoClasssclssstylesstyless defaultStyles _connectionsAttributeErrorstablesNonespythonClassToDBTables__name__sidNames idForTables _plainSetterss _plainGetterss_plainForeignSetterss_plainForeignGetterss_plainJoinGetterss_plainJoinAdderss_plainJoinRemoversscolumnss columnListscolumnDefinitionsscopysindexessindexDefinitionssjoinssjoinDefinitions(sclsssoClass((s,build/bdist.linux-i686/egg/sqlobject/main.pyssetClasss4                c CsI|}|i} ~|i| } | i} | djp td| |ijp*td| i | i | |i | |f||i | <| |i| <|i i | |io tdtt| }ntdt| }t| t| |t| t|  p | djo't| t| |d|i| lambda self, val: self._SO_setValue(%s, val, self.%s, self.%s)s_SO_from_python_%ss_SO_to_python_%ssKlambda self: self._SO_foreignKey(self._SO_loadValue(%r), self._SO_class_%s)sJlambda self: self._SO_foreignKey(self._SO_getValue(%s), self._SO_class_%s)sIDis8lambda self, val: setattr(self, %s, self._SO_getID(val))cCst|||S(N(ssetattrsmesattrsforeign(sforeignsmesattr((s,build/bdist.linux-i686/egg/sqlobject/main.pysss _SO_class_%ss^lambda cls, val, connection=None: cls._SO_fetchAlternateID(%s, %s, val, connection=connection)(4sclsssqlmetassoClasss columnDefs withClassscolumnsnamesAssertionErrorscolumnss __module__s__name__scolumnDefinitionss columnListsappends cacheValuessevalsreprs instanceNamesgetterssetattrs rawGetterNameshasattrs getterNames _plainGetterss immutablessetters from_pythons to_pythons rawSetterNames setterNames _plainSetterss foreignKeysorigNamesuppersendswiths_plainForeignGetterss_plainForeignSetterss classregistrysregistrysaddClassCallbacksalternateMethodNamesdbNamesfuncs classmethods changeSchemas connections _connectionsconns addColumnstables_SO_finishedClassCreationsmakeProperties( sclss columnDefs changeSchemas connectionssettersorigNamesconnssqlmetasgettersfuncsnamescolumnssoClass((s,build/bdist.linux-i686/egg/sqlobject/main.pys addColumn"sj  :    $ '$  #   ( cCs|i}|p|i}xm|i|i|D]V}|i|i jo=t |it o|ii d|_n|i |q/q/WdS(Nsascii(ssqlmetassoClasss connections _connectionsconnscolumnsFromSchemastables columnDefsnamescolumnDefinitionss isinstancesunicodesencodes addColumn(ssqlmetas connections columnDefssoClasssconn((s,build/bdist.linux-i686/egg/sqlobject/main.pysaddColumnsFromDatabases cCs5|i}t|to|i|}nt|tioIxF|iiD]!}||i jo |}PqMqMWt d|n|i }|i|=|i |=|ii|t|t||ii|ot|t|nt|t||ii|ot|t|n|iot|t|d |ii|d ot|t|d nt|t|d |ii|d ot|t|d qn|iot||in|o'|p|i}|i |i!|n|i"ot#|ndS(Ns#Column with definition %r not foundi($ssqlmetassoClasss isinstancescolumnsstrscolumnsscolsColsvaluesscs columnDefs IndexErrorsnamescolumnDefinitionss columnListsremovesdelattrs rawGetterNames _plainGettersshas_keys getterNames rawSetterNames _plainSetterss setterNames foreignKeys_plainForeignGetterss_plainForeignSetterssalternateMethodNames changeSchemas connections _connectionsconns delColumnstables_SO_finishedClassCreationsunmakeProperties(ssqlmetascolumns changeSchemas connectionscsnamessoClasssconn((s,build/bdist.linux-i686/egg/sqlobject/main.pys delColumnsD        cCs|}|i}|i|}|i}|ii |t |id}||i jo|i i |nt d|}t|t||t|t| o't|t||d|i|s cCsbttj o t|jot|nttj o t|joti|td|ndS(Ns stacklevel( sexception_levelsNoneslevelsNotImplementedErrorsmessageswarnings_levelswarningsswarnsDeprecationWarnings stacklevel(smessageslevels stacklevel((s,build/bdist.linux-i686/egg/sqlobject/main.pys deprecatedWscCs|a|adS(s" Set the deprecation level for SQLObject. Low levels are more actively being deprecated. Any warning at a level at or below ``warning`` will give a warning. Any warning at a level at or below ``exception`` will give an exception. You can use a higher ``exception`` level for tests to help upgrade your code. ``None`` for either value means never warn or raise exceptions. The levels currently mean: 1) Deprecated in current version (0.7). Will be removed in next version (0.8) 2) Planned to deprecate in next version, remove later. 3) Planned to deprecate sometime, remove sometime much later ;) As the SQLObject versions progress, the deprecation level of specific features will go down, indicating the advancing nature of the feature's doom. We'll try to keep features at 1 for a major revision. As time continues there may be a level 0, which will give a useful error message (better than ``AttributeError``) but where the feature has been fully removed. N(swarningswarnings_levels exceptionsexception_level(swarnings exception((s,build/bdist.linux-i686/egg/sqlobject/main.pyssetDeprecationLevel]ss SQLObjectc Bs=tZeiZeZeZeZ e Z e Z hZ e ZeZdZeddZeddZeddZeddZeddZeddZed dZed dZed dZed dZed dZeddZeddZeddZ eddZ!eddZ"eddZ#dZ$e%e$Z$dZ&e%e&Z&e e dZ'e%e'Z'dZ(e%e(Z(e e dZ)dZ*dZ+dZ,dZ-dZ.dZ/d Z0d!Z1d"Z2d#Z3d$Z4e d%Z5d&Z6e d'Z7e%e7Z7e d(Z8e%e8Z8d)Z9e%e9Z9e e e:e eeee e d* Z;e%e;Z;e d+Z<e%e<Z<ee=ee d,Z>e%e>Z>ee=e=e d-Z?e%e?Z?e=e e=d.Z@e%e@Z@ee d/ZAe%eAZAe d0ZBe%eBZBee d1ZCe%eCZCe d2ZDe%eDZDd3ZEe%eEZEee d4ZFe%eFZFe e=d5ZGe%eGZGd6ZHe d7ZIe%eIZId8ZJe d9ZKe%eKZKd:ZLe%eLZLd;ZMd<ZNe%eNZNRS(=NcCsn|itfj}|i||t||tidt dt }t||t i dt }t||tidt }| o|i|n|ido,|d} |`|id ptn+|ido|d} |`nt} t|_d|jo| oatd|dddxF|dD]6} t| toti| } n|i| q9Wnd |jo| o>td |d ddx#|d D]} |i| qWnh|_xa|iD]V}t!|d o|i"o |i#d jo&||_$t|_%||i|i#| qyW|i?t |_t@|| otAiB||_C|}x{|i$ol|i$}x\|i&i.i8D]H} tE| tiFjoqntG|iC| i*t0|iC| i*qWqWntHiI|i&iIiJ|dS(Nsset_namessorts _connections connections_columnss_The _columns attribute you gave (%r) is deprecated; columns should be added as class attributesslevelis_joinss[The _joins attribute you gave (%r) is deprecated; joins should be added as class attributess _inheritablesInheritableSQLObjects childNames'The column name 'childName' is reserveds;The column '%s' is already defined in an inheritable parentsnameslengthisdefaults__connection__(Ksclss __bases__sobjectsis_bases_SO_setupSqlmetas new_attrss_collectAttributesscolsColsTruesimplicitColumnssjoinssJoins implicitJoinssindexs DatabaseIndexsimplicitIndexess_SO_cleanDeprecatedAttrsshas_keys connections _connectionsAssertionErrorsNonesFalses_SO_finishedClassCreations deprecatedscolumns isinstancesstrsappendsjs _childClassess superclassshasattrs _inheritables__name__s _parentClasss_parentssqlmetascolumnsskeyss parentColssnamescnamesAttributeErrors columnListscolumnDefinitionss StringColsgetattrssyssmoduless __module__smods__connection__s setConnectionskeysvaluess addColumns fromDatabasesaddColumnsFromDatabasesaddJoinsisaddIndexs_notifyFinishClassCreationsmakePropertiess sqlbuildersSQLObjectTablesqs currentClassstypes ForeignKeyssetattrs classregistrysregistrysaddClass(sclss new_attrsskeys superclasssimplicitIndexessis_bases parentColssimplicitColumnss implicitJoinssmodscolumnsjsis connectionscnames currentClass((s,build/bdist.linux-i686/egg/sqlobject/main.pys __classinit__s!          *         *,      #sstyleistablesidNames lazyUpdates defaultOrders cacheValuessregistrysidTypes fromDatabasesexpireds columnListiscolumnss addColumns delColumnsaddJoinsdelJoinsaddIndexcCsJ|id o| otd|ifh|_nt|it o|iiftffjpt d|iixG|iD]$}t |dt }|oPqqWdpt d|it|ii}x?|iD]1}|ido |ido ||=qqWtd|f||_n|ii|dS(s8 This fixes up the sqlmeta attribute. It handles both the case where no sqlmeta was given (in which we need to create another subclass), or the sqlmeta given doesn't have the proper inheritance. Lastly it calls sqlmeta.setClass, which handles much of the setup. ssqlmetasIf you do not inherit your sqlmeta class from sqlobject.sqlmeta, it must not inherit from any other class (your sqlmeta inherits from: %s)isZNo sqlmeta class could be found in any superclass (while fixing up sqlmeta %r inheritance)s__N(s new_attrsshas_keysis_basestypesclsssqlmetas issubclasss __bases__sobjectsAssertionErrorsbasesgetattrsNones superclasssdicts__dict__svaluesskeysskeys startswithsendswithssetClass(sclss new_attrssis_baseskeysbases superclasssvalues((s,build/bdist.linux-i686/egg/sqlobject/main.pys_SO_setupSqlmeta:s$0    c Csxddddddddd d g D]h}|i|oR|d }td ||fd dddt|i|||t||q%q%Wx?dgD]4}|i|otd|d dddqqWdS(s This removes attributes on SQLObject subclasses that have been deprecated; they are moved to the sqlmeta class, and a deprecation warning is given. s_tables _lazyUpdates_styles_idNames _defaultOrders _cacheValuess _registrys_idTypes _fromDatabases _idSequenceis@%r is deprecated; please set the %r attribute in sqlmeta insteadslevelis stacklevelis_expiredsa%r is deprecated and read-only; please do not use it in your classes until it is fully deprecatediN( sattrs new_attrsshas_keysnew_names deprecatedssetattrsclsssqlmetasdelattr(sclss new_attrssnew_namesattr((s,build/bdist.linux-i686/egg/sqlobject/main.pys_SO_cleanDeprecatedAttrsfs%    cCs+|tj ptd|i|ii|}|tjo|ii }n |i }|i ||}|tjo]zH|dd}t ||_ |i||||i|||Wd|i|XnR|o|i o?|iiz|i|t|i_Wd|iiXn|SdS(Ns None is not a possible id for %ss_SO_fetch_no_createi(sidsNonesAssertionErrorsclss__name__ssqlmetasidTypes connections _connectionscachesgetsvalsSQLObjectStates_SO_validatorStates_inits selectResultssputs finishPutsdirtys _SO_writeLocksacquires_SO_selectInitsFalsesexpiredsrelease(sclssids connections selectResultssvalscache((s,build/bdist.linux-i686/egg/sqlobject/main.pysgets,     cCsdS(N((scls((s,build/bdist.linux-i686/egg/sqlobject/main.pys_notifyFinishClassCreationscCs|tj pt||_|ii||_ti|_|tj o||_ t |i_ n| oqgi}|iiD]}||iq~}|i i||}| o td|ii|ifqn|i|h|_t|_dS(Ns)The object %s by the ID %s does not exist(sidsNonesAssertionErrorsselfs __class__ssqlmetas threadingsLocks _SO_writeLocks connections _connectionsTrues_perConnections selectResultssappends_[1]s columnListscolsdbNamesdbNamess _SO_selectOnesSQLObjectNotFounds__name__s_SO_selectInits_SO_createValuessFalsesdirty(sselfsids connections selectResultssdbNamess_[1]scol((s,build/bdist.linux-i686/egg/sqlobject/main.pys_inits   0$  cCsyt||SWntj oz|iiyt||}Wntj onX|St|i_ gi }|ii D]}||iq~}|ii||}| o td|ii|ifn|i|t||}|SWd|iiXnXdS(Ns+The object %s by the ID %s has been deleted(sgetattrsselfsattrNamesAttributeErrors _SO_writeLocksacquiresresultsFalsessqlmetasexpiredsappends_[1]s columnListscolsdbNamesdbNamess _connections _SO_selectOnes selectResultssSQLObjectNotFounds __class__s__name__sids_SO_selectInitsrelease(sselfsattrNames_[1]sdbNamess selectResultssresultscol((s,build/bdist.linux-i686/egg/sqlobject/main.pys _SO_loadValues(  0  cCs|iio|io|in|iizgi}|ii D]}||i qI~}|i i||}| o td|ii|ifn|i|t|i_Wd|iiXdS(Ns+The object %s by the ID %s has been deleted(sselfssqlmetas lazyUpdates_SO_createValuess syncUpdates _SO_writeLocksacquiresappends_[1]s columnListscolsdbNamesdbNamess _connections _SO_selectOnes selectResultssSQLObjectNotFounds __class__s__name__sids_SO_selectInitsFalsesexpiredsrelease(sselfsdbNamess selectResultss_[1]scol((s,build/bdist.linux-i686/egg/sqlobject/main.pyssyncs 0  cCs|i odSn|iiz|iiobgi}|iiD]+}||ii|di |dfqG~}|i i ||nt|_h|_Wd|iiXdS(Nii(sselfs_SO_createValuess _SO_writeLocksacquiressqlmetascolumnssappends_[1]sitemssvsdbNamesvaluess _connections _SO_updatesFalsesdirtysrelease(sselfs_[1]svaluessv((s,build/bdist.linux-i686/egg/sqlobject/main.pys syncUpdates   K  cCs|iiodSn|iizw|iiodSnx*|iiD]}t|t|i qGWt |i_|i i i |i|ih|_Wd|iiXdS(N(sselfssqlmetasexpireds _SO_writeLocksacquires columnListscolumnsdelattrs instanceNamesnamesTrues _connectionscachesexpiresids __class__s_SO_createValuessrelease(sselfscolumn((s,build/bdist.linux-i686/egg/sqlobject/main.pysexpires      cCs|o|||i}n|}|o|||i}n|iip |iio4t |_ ||i |.scs|d S(Ni(s is_columnsitem(sitem(s is_column(s,build/bdist.linux-i686/egg/sqlobject/main.pys/ss_SO_from_python_%ss_SO_to_python_%ss.%s.set() got an unexpected keyword argument %ss%s (with attribute %r)(-sselfssqlmetas _plainSettersshas_keys is_columns f_is_columns f_not_columnskwsitemssdictsfiltersextras _creatings lazyUpdatesnamesvaluesgetattrsNones from_pythons_SO_validatorStatesdbValues to_pythonssetattrs instanceNames_SO_createValuessupdates __class__sAttributeErrorscolumnss TypeErrors__name__sesTruesdirtys _SO_writeLocksacquirestoUpdates cacheValuessappends_[1]sdbNamesargss _connections _SO_updatesrelease(sselfskwsdbValuesextras f_not_columns_[1]s f_is_columnstoUpdatesargss is_columns to_pythonsesnamesitemssvalues from_python((s is_columns,build/bdist.linux-i686/egg/sqlobject/main.pysset&s|     "      "FcCsfx_t|ii|D]H\}}|io|i||i}nt |t |i |qWdS(N( szipsselfssqlmetas columnListsrowscolscolValues to_pythons_SO_validatorStatessetattrs instanceNamesname(sselfsrowscolValuescol((s,build/bdist.linux-i686/egg/sqlobject/main.pys_SO_selectInit{s   cCs|ii ptd|ii|if|ii|}|i i ||i g}|tjptd|ii|if|d}|io|i||i}n|SdS(Ns!%s with id %s has become obsoletes$%s with id %s is not in the databasei(sselfssqlmetas _obsoletesAssertionErrors __class__s__name__sidscolumnssnamescolumns _connections _SO_selectOnesdbNamesresultssNonesvalues to_pythons_SO_validatorState(sselfsnamescolumnsresultssvalue((s,build/bdist.linux-i686/egg/sqlobject/main.pys _SO_getValues+*  cCsM|tjotSn5|iio|i|d|iSn|i|SdS(Ns connection(sidsNonesselfssqlmetas_perConnections joinClasssgets _connection(sselfsids joinClass((s,build/bdist.linux-i686/egg/sqlobject/main.pys_SO_foreignKeys   cKs|idodSn|ido$|d|_t|i_|d=nti|_ |ido!|ii |d}|d=nt }|i ||dS(Ns_SO_fetch_no_creates connectionsid(skwshas_keysselfs _connectionsTruessqlmetas_perConnections threadingsLocks _SO_writeLocksidTypesidsNones_create(sselfskwsid((s,build/bdist.linux-i686/egg/sqlobject/main.pys__init__s    cKst|i_h|_t||_x|iiD]u}|i |i  o|i |i  oG|i }|tjo td|ii|i fn|||i    %  ) ' cCs#|i|d|}|idS(Ns connection(sclssgetsids connectionsobjs destroySelf(sclssids connectionsobj((s,build/bdist.linux-i686/egg/sqlobject/main.pysdeletesc Csdd|ii|idigi}|iD]&\}}|d|t |fq,~fSdS(Ns <%s %r %s>s s%s=%s( sselfs __class__s__name__sidsjoinsappends_[1]s _reprItemssnamesvaluesrepr(sselfs_[1]snamesvalue((s,build/bdist.linux-i686/egg/sqlobject/main.pys__repr__scCs|p|ii|SdS(N(s connectionsclss _connectionssqlreprsvalue(sclssvalues connection((s,build/bdist.linux-i686/egg/sqlobject/main.pyssqlreprscCs/t||o |iSn|ii|SdS(N(s isinstancesvaluesclssidssqlmetasidType(sclssvalue((s,build/bdist.linux-i686/egg/sqlobject/main.pyscoerceIDs cCsg}xu|iiD]g}t||i}t|}t |djo|d d|d}n|i |i|fqW|SdS(Niis...i( sitemssselfssqlmetas columnListscolsgetattrsnamesvaluesreprsrslensappend(sselfsitemssvaluesrscol((s,build/bdist.linux-i686/egg/sqlobject/main.pys _reprItemss  cCs6t|ttfoti|}n||_dS(N(s isinstancesvaluesstrsunicodes dbconnectionsconnectionForURIsclss _connection(sclssvalue((s,build/bdist.linux-i686/egg/sqlobject/main.pys setConnections(Os__name__s __module__s declarativesDeclarativeMetas __metaclass__ssqlhubs _connectionssqlmetasFalses _inheritablesNones _parentClasss_parents _childClassess childNames SelectResultssSelectResultsClasss __classinit__s _sqlmeta_attrs_styles_tables_idNames _lazyUpdates _defaultOrders _cacheValuess _registrys_idTypes _fromDatabases_expireds_columnss _columnDicts addColumns delColumnsaddJoinsdelJoinsaddIndexs_SO_setupSqlmetas classmethods_SO_cleanDeprecatedAttrssgets_notifyFinishClassCreations_inits _SO_loadValuessyncs syncUpdatesexpires _SO_setValuessets_SO_selectInits _SO_getValues_SO_foreignKeys__init__s_creates_SO_finishCreates _SO_getIDs_findAlternateIDs_SO_fetchAlternateIDs _SO_dependss NoDefaultsselectsselectBysTrues dropTables createTablescreateTableSQLscreateJoinTablesscreateJoinTablesSQLs createIndexesscreateIndexesSQLs_getJoinsToCreatesdropJoinTabless clearTables destroySelfsdeletes__repr__ssqlreprscoerceIDs _reprItemss setConnection(((s,build/bdist.linux-i686/egg/sqlobject/main.pys SQLObjects   )            U           $              +        cCs|di|dSdS(Nii(snames capitalize(sname((s,build/bdist.linux-i686/egg/sqlobject/main.pys capitalizescCs d|SdS(Ns_set_%s(sname(sname((s,build/bdist.linux-i686/egg/sqlobject/main.pys setterNamescCs d|SdS(Ns _SO_set_%s(sname(sname((s,build/bdist.linux-i686/egg/sqlobject/main.pys rawSetterNamescCs d|SdS(Ns_get_%s(sname(sname((s,build/bdist.linux-i686/egg/sqlobject/main.pys getterNamescCs d|SdS(Ns _SO_get_%s(sname(sname((s,build/bdist.linux-i686/egg/sqlobject/main.pys rawGetterNamescCs d|SdS(Ns _SO_val_%s(sname(sname((s,build/bdist.linux-i686/egg/sqlobject/main.pys instanceNamessSQLObjectStatecBstZdZRS(NcCs||_d|_dS(Nssql(ssoObjectsselfsprotocol(sselfssoObject((s,build/bdist.linux-i686/egg/sqlobject/main.pys__init__s (s__name__s __module__s__init__(((s,build/bdist.linux-i686/egg/sqlobject/main.pysSQLObjectStatescCst|to |iSnt|tdjo|Snt|tdjot|Sn[t|tdjo,yt|SWqtj o |SqXn|tjotSndS(Nils(s isinstancesobjs SQLObjectsidstypesints ValueErrorsNone(sobj((s,build/bdist.linux-i686/egg/sqlobject/main.pysgetIDs   cCst|tdjo||Sntt|tdjo|t|SnGt|tdjo|t|Sn|tjotSn|SdS(Nils(stypesobjsklasssintsNone(sobjsklass((s,build/bdist.linux-i686/egg/sqlobject/main.pys getObjects s NoDefaultsgetIDs getObjectssqlhubssetDeprecationLevel(6s__doc__s threadings sqlbuilders dbconnectionscolsstylesstypesswarningssjoinssindexs classregistrys declarativessresultss SelectResultss formencodesschemascompoundssyss version_infos ImportErrors NoDefaults LookupErrorsSQLObjectNotFounds ExceptionsSQLObjectIntegrityErrorsTruesFalsesmakePropertiessunmakePropertiessNonesfindDependenciessfindDependantColumnss_collectAttributessCreateNewSQLObjectsobjectssqlmetas ConnectionHubssqlhubs _sqlmeta_attrswarnings_levelsexception_levels deprecatedssetDeprecationLevels SQLObjects capitalizes setterNames rawSetterNames getterNames rawGetterNames instanceNamesSQLObjectStatesgetIDs getObjects__all__(*sSQLObjectIntegrityErrors NoDefaults _sqlmeta_attrsgetIDs instanceNames getObjectsfindDependantColumnss setterNames getterNamesindexs_collectAttributess dbconnectionsSQLObjectStates rawGetterNames SelectResultssunmakePropertiessfindDependenciessmakePropertiessTruesschemasstylessSQLObjectNotFoundssqlmetaswarningsssyss declarativesjoinsscompounds classregistryssetDeprecationLevels capitalizestypess SQLObjects sqlbuildersFalses__all__s deprecatedsCreateNewSQLObjects threadings rawSetterNamescolssqlhub((s,build/bdist.linux-i686/egg/sqlobject/main.pys?!s`                2    &l        PKb953))sqlobject/sresults.pyc; Ec@sAdkZdkZedZdefdYZdgZdS(Nss SelectResultscBstZeiZedZdZdZdZ dZ dZ dZ dZ d Zd Zd Zd Zd ZdZdZdZdZdZdZdZdZdZdZdZdZRS(NcKsz||_|tjpt|to |djo ti}n||_ti|i}d||i i <|ox|D]}d||(sselfs __class__s__name__sid(sself((s0build/bdist.linux-i686/egg/sqlobject/sresults.pys__repr__"scCs!|iidp |iiSdS(Ns connection(sselfsopssgets sourceClasss _connection(sself((s0build/bdist.linux-i686/egg/sqlobject/sresults.pys_getConnection%scCs|i}|i|SdS(N(sselfs_getConnectionsconnsqueryForSelect(sselfsconn((s0build/bdist.linux-i686/egg/sqlobject/sresults.pys__str__(s cCst|to |ido|d}t}nt}t|ttfob||i i i jo1|i i i |i }|o d|Sq|Sq|o d|Sq|Sn|SdS(Ns-i(s isinstancesorderBysstrs startswithsTruesdescsFalsesunicodesselfs sourceClassssqlmetascolumnssdbNamesval(sselfsorderBysvalsdesc((s0build/bdist.linux-i686/egg/sqlobject/sresults.pys _mungeOrderBy,s     cKs?|ii}|i||i|i|i|i|SdS(N( sselfsopsscopysupdatesnewOpss __class__s sourceClasssclauses clauseTables(sselfsnewOpssops((s0build/bdist.linux-i686/egg/sqlobject/sresults.pyscloneAs cCs|id|SdS(NsorderBy(sselfsclonesorderBy(sselfsorderBy((s0build/bdist.linux-i686/egg/sqlobject/sresults.pysorderByGscCs|id|SdS(Ns connection(sselfsclonesconn(sselfsconn((s0build/bdist.linux-i686/egg/sqlobject/sresults.pys connectionJscCs || SdS(N(sselfslimit(sselfslimit((s0build/bdist.linux-i686/egg/sqlobject/sresults.pyslimitMscCs|id|SdS(Ns lazyColumns(sselfsclonesvalue(sselfsvalue((s0build/bdist.linux-i686/egg/sqlobject/sresults.pys lazyColumnsPscCs$|id|iidt SdS(Nsreversed(sselfsclonesopssgetsFalse(sself((s0build/bdist.linux-i686/egg/sqlobject/sresults.pysreversedSscCs|idtSdS(Nsdistinct(sselfsclonesTrue(sself((s0build/bdist.linux-i686/egg/sqlobject/sresults.pysdistinctVscCs#|i|i||i|iSdS(N(sselfs __class__s sourceClasss new_clauses clauseTablessops(sselfs new_clause((s0build/bdist.linux-i686/egg/sqlobject/sresults.pys newClauseYscCsk|tjo|Sn|i}t|ttfotid|i}n|i ti ||SdS(Ns(%s)( s filter_clausesNonesselfsclauses isinstancesstrsunicodes sqlbuilders SQLConstants newClausesAND(sselfs filter_clausesclause((s0build/bdist.linux-i686/egg/sqlobject/sresults.pysfilter]s   cCst|ttdjo5|i p td|i o|i o|Sn|io |idjp|io |idjoY|io:|iot||i|i!Snt||iSnt||i Sn|io|idjpt|i i dd|i}|it j o|idjpt|i|ijo |}q|i|i i dd}|i i dt t j o|d|jo|i d}qq:|i i dt }nd|i i dd}|i|}|i i dt t j o|i d|jo|i d}n|i d|d|Snc|djott||Sn>|i i dd|}t|i d|d|ddSdS(NisSlices do not support stepsisstartsend(stypesvaluesslicesstepsAssertionErrorsstartsstopsselfslistsopssgetsNonesendsclonesiter(sselfsvaluesendsstart((s0build/bdist.linux-i686/egg/sqlobject/sresults.pys __getitem__fs<4    - 0 cCstt|iSdS(N(siterslistsselfslazyIter(sself((s0build/bdist.linux-i686/egg/sqlobject/sresults.pys__iter__scCs|i}|i|SdS(s{ Returns an iterator that will lazily pull rows out of the database and return SQLObject instances N(sselfs_getConnectionsconns iterSelect(sselfsconn((s0build/bdist.linux-i686/egg/sqlobject/sresults.pyslazyIters cGs |i}|i||SdS(s Use accumulate expression(s) to select result using another SQL select through current connection. Return the accumulate result N(sselfs_getConnectionsconnsaccumulateSelects expressions(sselfs expressionssconn((s0build/bdist.linux-i686/egg/sqlobject/sresults.pys accumulates cCs|iido#|iidp|iid p td|iido/|id|iii|iiif}n|id}|iido||id8}n|iido-t |id|iidd|}n|SdS( s- Counting elements of current select results sdistinctsstartsends4distinct-counting of sliced objects is not supportedsCOUNT(DISTINCT %s.%s)sCOUNT(*)iN( sselfsopssgetsAssertionErrors accumulates sourceClassssqlmetastablesidNamescountsmin(sselfscount((s0build/bdist.linux-i686/egg/sqlobject/sresults.pyscountsD/-cGszg}x`|D]X\}}t|tjod||f}ntti ||}|i |q W|i |SdS(s1 Making the expressions for count/sum/min/max/avg of a given select result attributes. `attributes` must be a list/tuple of pairs (func_name, attribute); `attribute` can be a column name (like 'a_column') or a dot-q attribute (like Table.q.aColumn) s%s(%s)N( s expressionss attributess func_names attributestypes StringTypes expressionsgetattrs sqlbuildersfuncsappendsselfs accumulate(sselfs attributess attributes expressions func_names expressions((s0build/bdist.linux-i686/egg/sqlobject/sresults.pysaccumulateManys cCs|i||fSdS(s Making the sum/min/max/avg of a given select result attribute. `attribute` can be a column name (like 'a_column') or a dot-q attribute (like Table.q.aColumn) N(sselfsaccumulateManys func_names attribute(sselfs func_names attribute((s0build/bdist.linux-i686/egg/sqlobject/sresults.pys accumulateOnescCs|id|SdS(NsSUM(sselfs accumulateOnes attribute(sselfs attribute((s0build/bdist.linux-i686/egg/sqlobject/sresults.pyssumscCs|id|SdS(NsMIN(sselfs accumulateOnes attribute(sselfs attribute((s0build/bdist.linux-i686/egg/sqlobject/sresults.pysminscCs|id|SdS(NsAVG(sselfs accumulateOnes attribute(sselfs attribute((s0build/bdist.linux-i686/egg/sqlobject/sresults.pysavgscCs|id|SdS(NsMAX(sselfs accumulateOnes attribute(sselfs attribute((s0build/bdist.linux-i686/egg/sqlobject/sresults.pysmaxs(s__name__s __module__s dbconnections IterationsIterationClasssNones__init__s__repr__s_getConnections__str__s _mungeOrderBysclonesorderBys connectionslimits lazyColumnssreversedsdistincts newClausesfilters __getitem__s__iter__slazyIters accumulatescountsaccumulateManys accumulateOnessumsminsavgsmax(((s0build/bdist.linux-i686/egg/sqlobject/sresults.pys SelectResultss4               1        (s sqlbuilders dbconnectionstypes StringTypesobjects SelectResultss__all__(s StringTypes sqlbuilders__all__s dbconnections SelectResults((s0build/bdist.linux-i686/egg/sqlobject/sresults.pys?s   PKb95O#I I sqlobject/conftest.pyc; Ec@sZdZdZeZdkZdkZdkZhdd<dd<dd<d d<d d <d d ei<dd<dd<dd for each table this method to work.""" table = soInstance.sqlmeta.table idName = soInstance.sqlmeta.idName sequenceName = soInstance.sqlmeta.idSequence or \ 'GEN_%s' % table c = conn.cursor() if id is None: c.execute('SELECT gen_id(%s,1) FROM rdb$database' % sequenceName) id = c.fetchone()[0] names = [idName] + names values = [id] + values q = self._insertSQL(table, names, values) if self.debug: self.printDebug(conn, q, 'QueryIns') c.execute(q) if self.debugOutput: self.printDebug(conn, id, 'QueryIns', 'result') return id def _queryAddLimitOffset(self, query, start, end): """Firebird slaps the limit and offset (actually 'first' and 'skip', respectively) statement right after the select.""" if not start: limit_str = "SELECT FIRST %i" % end if not end: limit_str = "SELECT SKIP %i" % start else: limit_str = "SELECT FIRST %i SKIP %i" % (end-start, start) match = self.limit_re.match(query) if match and len(match.groups()) == 2: return ' '.join([limit_str, match.group(2)]) else: return query def createTable(self, soClass): self.query('CREATE TABLE %s (\n%s\n)' % \ (soClass.sqlmeta.table, self.createColumns(soClass))) self.query("CREATE GENERATOR GEN_%s" % soClass.sqlmeta.table) def createColumn(self, soClass, col): return col.firebirdCreateSQL() def createIDColumn(self, soClass): return '%s INT NOT NULL PRIMARY KEY' % soClass.sqlmeta.idName def createIndexSQL(self, soClass, index): return index.firebirdCreateIndexSQL(soClass) def joinSQLType(self, join): return 'INT NOT NULL' def tableExists(self, tableName): # there's something in the database by this name...let's # assume it's a table. By default, fb 1.0 stores EVERYTHING # it cares about in uppercase. result = self.queryOne("SELECT COUNT(rdb$relation_name) FROM rdb$relations WHERE rdb$relation_name = '%s'" % tableName.upper()) return result[0] def addColumn(self, tableName, column): self.query('ALTER TABLE %s ADD %s' % (tableName, column.firebirdCreateSQL())) def dropTable(self, tableName, cascade=False): self.query("DROP TABLE %s" % tableName) self.query("DROP GENERATOR GEN_%s" % tableName) def delColumn(self, tableName, column): self.query('ALTER TABLE %s DROP %s' % (tableName, column.dbName)) def columnsFromSchema(self, tableName, soClass): """ Look at the given table and create Col instances (or subclasses of Col) for the fields it finds in that table. """ fieldqry = """\ SELECT RDB$RELATION_FIELDS.RDB$FIELD_NAME as field, RDB$TYPES.RDB$TYPE_NAME as t, RDB$FIELDS.RDB$FIELD_LENGTH as flength, RDB$FIELDS.RDB$FIELD_SCALE as fscale, RDB$RELATION_FIELDS.RDB$NULL_FLAG as nullAllowed, RDB$RELATION_FIELDS.RDB$DEFAULT_VALUE as thedefault, RDB$FIELDS.RDB$FIELD_SUB_TYPE as blobtype FROM RDB$RELATION_FIELDS INNER JOIN RDB$FIELDS ON (RDB$RELATION_FIELDS.RDB$FIELD_SOURCE = RDB$FIELDS.RDB$FIELD_NAME) INNER JOIN RDB$TYPES ON (RDB$FIELDS.RDB$FIELD_TYPE = RDB$TYPES.RDB$TYPE) WHERE (RDB$RELATION_FIELDS.RDB$RELATION_NAME = '%s') AND (RDB$TYPES.RDB$FIELD_NAME = 'RDB$FIELD_TYPE')""" colData = self.queryAll(fieldqry % tableName.upper()) results = [] for field, t, flength, fscale, nullAllowed, thedefault, blobType in colData: if field == 'id': continue colClass, kw = self.guessClass(t, flength, fscale) kw['name'] = soClass.sqlmeta.style.dbColumnToPythonAttr(field) kw['notNone'] = not nullAllowed kw['default'] = thedefault results.append(colClass(**kw)) return results _intTypes=['INT64', 'SHORT','LONG'] _dateTypes=['DATE','TIME','TIMESTAMP'] def guessClass(self, t, flength, fscale=None): """ An internal method that tries to figure out what Col subclass is appropriate given whatever introspective information is available -- both very database-specific. """ if t in self._intTypes: return col.IntCol, {} elif t == 'VARYING': return col.StringCol, {'length': flength} elif t == 'TEXT': return col.StringCol, {'length': flength, 'varchar': False} elif t in self._dateTypes: return col.DateTimeCol, {} else: return col.Col, {} PKb95O__sqlobject/firebird/__init__.pyc; Ec@s9dklZdZdZeddgeedS((sregisterConnectioncCsdk}|iSdS(N(sfirebirdconnectionsFirebirdConnection(sfirebirdconnection((s9build/bdist.linux-i686/egg/sqlobject/firebird/__init__.pysbuilders cCs/y dk}Wntj o tSnXtSdS(N(s kinterbasdbs ImportErrorsFalsesTrue(s kinterbasdb((s9build/bdist.linux-i686/egg/sqlobject/firebird/__init__.pys isSupporteds   sfirebirds interbaseN(ssqlobject.dbconnectionsregisterConnectionsbuilders isSupported(s isSupportedsbuildersregisterConnection((s9build/bdist.linux-i686/egg/sqlobject/firebird/__init__.pys?s   PKb95**)sqlobject/firebird/firebirdconnection.pyc; Ec@s?dklZeadkZdkZdefdYZdS((sDBAPINsFirebirdConnectioncBstZeZdZegZdddeeedZdZe eZdZ dZ d Z d Z d Zd Zd ZdZdZdZdZdZedZdZdZdddgZdddgZedZRS(Nsfirebirdssysdbas masterkeyic Ksttjo dkant|_tidti|_||_||_ ||_ ||_ |ot ||_ n t|_ ||_||_ti|| dS(Ns^\s*(select )(.*)(s kinterbasdbsNonesselfsmodulesrescompiles IGNORECASEslimit_reshostsdbsuserspasswdsdialectsintsrolescharsetsDBAPIs__init__skw( sselfshostsdbsuserspasswds autoCommitsdialectsrolescharsetskw((sCbuild/bdist.linux-i686/egg/sqlobject/firebird/firebirdconnection.pys__init__ s          c Cs|i|\}}}}}}| o d}n| o d}nt i djo|ddjo|d}n|i dt i }||d|d|d ||SdS( Ns masterkeyssysdbasntis/isdbsuserspasswd( sclss _parseURIsurisauthspasswordshostsportspathsargssossnamesreplacessep(sclssurisargssauthshostspathspasswordsport((sCbuild/bdist.linux-i686/egg/sqlobject/firebird/firebirdconnection.pysconnectionFromURI#s!  !cGs|i oti|||Sn|i}y|iWnt i j onXz:|||}y|i Wnt i j onXWd|i |X|SdS(N(sselfs autoCommitsDBAPIs_runWithConnectionsmethsargss getConnectionsconnsbegins kinterbasdbsProgrammingErrorsvalscommitsreleaseConnection(sselfsmethsargssvalsconn((sCbuild/bdist.linux-i686/egg/sqlobject/firebird/firebirdconnection.pys_runWithConnection0s    cCsdS(N((sselfsconnsauto((sCbuild/bdist.linux-i686/egg/sqlobject/firebird/firebirdconnection.pys_setAutoCommitCscCshh}|io|i|d for each table this method to work.sGEN_%ss%SELECT gen_id(%s,1) FROM rdb$databaseisQueryInssresultN(s soInstancessqlmetastablesidNames idSequences sequenceNamesconnscursorscsidsNonesexecutesfetchonesnamessvaluessselfs _insertSQLsqsdebugs printDebugs debugOutput( sselfsconns soInstancesidsnamessvaluesscsidNamesqs sequenceNamestable((sCbuild/bdist.linux-i686/egg/sqlobject/firebird/firebirdconnection.pys_queryInsertIDVs"         cCs| od|}n| od|}nd|||f}|ii|}|ot|idjo di ||i dgSn|SdS(syFirebird slaps the limit and offset (actually 'first' and 'skip', respectively) statement right after the select.sSELECT FIRST %isSELECT SKIP %isSELECT FIRST %i SKIP %iis N( sstartsends limit_strsselfslimit_resmatchsqueryslensgroupssjoinsgroup(sselfsquerysstartsends limit_strsmatch((sCbuild/bdist.linux-i686/egg/sqlobject/firebird/firebirdconnection.pys_queryAddLimitOffsetms  cCsA|id|ii|i|f|id|iidS(NsCREATE TABLE %s ( %s )sCREATE GENERATOR GEN_%s(sselfsqueryssoClassssqlmetastables createColumns(sselfssoClass((sCbuild/bdist.linux-i686/egg/sqlobject/firebird/firebirdconnection.pys createTable}s&cCs|iSdS(N(scolsfirebirdCreateSQL(sselfssoClassscol((sCbuild/bdist.linux-i686/egg/sqlobject/firebird/firebirdconnection.pys createColumnscCsd|iiSdS(Ns%s INT NOT NULL PRIMARY KEY(ssoClassssqlmetasidName(sselfssoClass((sCbuild/bdist.linux-i686/egg/sqlobject/firebird/firebirdconnection.pyscreateIDColumnscCs|i|SdS(N(sindexsfirebirdCreateIndexSQLssoClass(sselfssoClasssindex((sCbuild/bdist.linux-i686/egg/sqlobject/firebird/firebirdconnection.pyscreateIndexSQLscCsdSdS(Ns INT NOT NULL((sselfsjoin((sCbuild/bdist.linux-i686/egg/sqlobject/firebird/firebirdconnection.pys joinSQLTypescCs%|id|i}|dSdS(NsQSELECT COUNT(rdb$relation_name) FROM rdb$relations WHERE rdb$relation_name = '%s'i(sselfsqueryOnes tableNamesuppersresult(sselfs tableNamesresult((sCbuild/bdist.linux-i686/egg/sqlobject/firebird/firebirdconnection.pys tableExistsscCs!|id||ifdS(NsALTER TABLE %s ADD %s(sselfsquerys tableNamescolumnsfirebirdCreateSQL(sselfs tableNamescolumn((sCbuild/bdist.linux-i686/egg/sqlobject/firebird/firebirdconnection.pys addColumnscCs&|id||id|dS(Ns DROP TABLE %ssDROP GENERATOR GEN_%s(sselfsquerys tableName(sselfs tableNamescascade((sCbuild/bdist.linux-i686/egg/sqlobject/firebird/firebirdconnection.pys dropTablescCs|id||ifdS(NsALTER TABLE %s DROP %s(sselfsquerys tableNamescolumnsdbName(sselfs tableNamescolumn((sCbuild/bdist.linux-i686/egg/sqlobject/firebird/firebirdconnection.pys delColumnscCsd}|i||i}g}x|D]\}} }} } }}|djoq,n|i| || \} } |iii|| d<| | d<|| d<|i| | q,W|SdS(s Look at the given table and create Col instances (or subclasses of Col) for the fields it finds in that table. s SELECT RDB$RELATION_FIELDS.RDB$FIELD_NAME as field, RDB$TYPES.RDB$TYPE_NAME as t, RDB$FIELDS.RDB$FIELD_LENGTH as flength, RDB$FIELDS.RDB$FIELD_SCALE as fscale, RDB$RELATION_FIELDS.RDB$NULL_FLAG as nullAllowed, RDB$RELATION_FIELDS.RDB$DEFAULT_VALUE as thedefault, RDB$FIELDS.RDB$FIELD_SUB_TYPE as blobtype FROM RDB$RELATION_FIELDS INNER JOIN RDB$FIELDS ON (RDB$RELATION_FIELDS.RDB$FIELD_SOURCE = RDB$FIELDS.RDB$FIELD_NAME) INNER JOIN RDB$TYPES ON (RDB$FIELDS.RDB$FIELD_TYPE = RDB$TYPES.RDB$TYPE) WHERE (RDB$RELATION_FIELDS.RDB$RELATION_NAME = '%s') AND (RDB$TYPES.RDB$FIELD_NAME = 'RDB$FIELD_TYPE')sidsnamesnotNonesdefaultN(sfieldqrysselfsqueryAlls tableNamesupperscolDatasresultssfieldstsflengthsfscales nullAlloweds thedefaultsblobTypes guessClassscolClassskwssoClassssqlmetasstylesdbColumnToPythonAttrsappend(sselfs tableNamessoClasssblobTypesflengthsfieldscolDatasresultssfieldqrys nullAllowedskwstscolClasssfscales thedefault((sCbuild/bdist.linux-i686/egg/sqlobject/firebird/firebirdconnection.pyscolumnsFromSchemas   sINT64sSHORTsLONGsDATEsTIMEs TIMESTAMPcCs||ijotihfSn|djotihd||i }|t j o$|i |i|d|d|Sq~n|}xD|io|i o.|ii|d|dt|_|i}qW|SdS(Ns childNames connections selectResultss childUpdate(ssupersInheritableSQLObjectsclssgetsids connections selectResultssvals childUpdatessqlmetascolumnss childNamesNones _childClassess childResultssinsts _parentClasss_parentsTrue( sclssids connections selectResultss childResultss childUpdatesvals childNamesinst((s<build/bdist.linux-i686/egg/sqlobject/inheritance/__init__.pysgets  (!cCsH|ii o|iitn|ii o|iitndS(N(sclsssqlmetas columnLists addColumnsNonesjoinssaddJoin(scls((s<build/bdist.linux-i686/egg/sqlobject/inheritance/__init__.pys_notifyFinishClassCreationsc Ks<|ido|d}n|io|i}h}h}xB|iD]4\}}t ||o||| 1 or (MySQLdb.version_info[0] == 1 and \ (MySQLdb.version_info[1] > 2 or \ (MySQLdb.version_info[1] == 2 and MySQLdb.version_info[2] >= 1))): self.need_unicode = True else: self.need_unicode = False for key in ("unix_socket", "init_command", "read_default_file", "read_default_group", "charset"): if key in kw: self.kw[key] = col.popKey(kw, key) for key in ("connect_timeout", "compress", "named_pipe", "use_unicode", "client_flag", "local_infile"): if key in kw: self.kw[key] = int(col.popKey(kw, key)) if "sqlobject_encoding" in kw: self.encoding = col.popKey(kw, "sqlobject_encoding") else: self.encoding = 'ascii' DBAPI.__init__(self, **kw) def connectionFromURI(cls, uri): user, password, host, port, path, args = cls._parseURI(uri) return cls(db=path.strip('/'), user=user or '', passwd=password or '', host=host or 'localhost', port=port or 0, **args) connectionFromURI = classmethod(connectionFromURI) def makeConnection(self): try: conn = self.module.connect(host=self.host, port=self.port, db=self.db, user=self.user, passwd=self.password, **self.kw) except self.module.OperationalError, e: raise self.module.OperationalError( "%s; used connection string: host=%s, port=%s, db=%s, user=%s, pwd=%s" % ( e, self.host, self.port, self.db, self.user, self.password) ) if hasattr(conn, 'autocommit'): conn.autocommit(bool(self.autoCommit)) return conn def _setAutoCommit(self, conn, auto): if hasattr(conn, 'autocommit'): conn.autocommit(auto) def _executeRetry(self, conn, cursor, query): while 1: try: if self.need_unicode: # For MysqlDB 1.2.1 and later, we go # encoding->unicode->charset (in the mysql db) myquery = unicode(query, self.encoding) return cursor.execute(myquery) else: return cursor.execute(query) except MySQLdb.OperationalError, e: if e.args[0] == 2013: # SERVER_LOST error if self.debug: self.printDebug(conn, str(e), 'ERROR') else: raise def _queryInsertID(self, conn, soInstance, id, names, values): table = soInstance.sqlmeta.table idName = soInstance.sqlmeta.idName c = conn.cursor() if id is not None: names = [idName] + names values = [id] + values q = self._insertSQL(table, names, values) if self.debug: self.printDebug(conn, q, 'QueryIns') self._executeRetry(conn, c, q) if id is None: try: id = c.lastrowid except AttributeError: id = c.insert_id() if self.debugOutput: self.printDebug(conn, id, 'QueryIns', 'result') return id def _queryAddLimitOffset(self, query, start, end): if not start: return "%s LIMIT %i" % (query, end) if not end: return "%s LIMIT %i, -1" % (query, start) return "%s LIMIT %i, %i" % (query, start, end-start) def createColumn(self, soClass, col): return col.mysqlCreateSQL() def createIndexSQL(self, soClass, index): return index.mysqlCreateIndexSQL(soClass) def createIDColumn(self, soClass): return '%s INT PRIMARY KEY AUTO_INCREMENT' % soClass.sqlmeta.idName def joinSQLType(self, join): return 'INT NOT NULL' def tableExists(self, tableName): try: # Use DESCRIBE instead of SHOW TABLES because SHOW TABLES # assumes there is a default database selected # which is not always True (for an embedded application, e.g.) self.query('DESCRIBE %s' % (tableName)) return True except MySQLdb.ProgrammingError, e: if e.args[0] == 1146: # ER_NO_SUCH_TABLE return False raise def addColumn(self, tableName, column): self.query('ALTER TABLE %s ADD COLUMN %s' % (tableName, column.mysqlCreateSQL())) def delColumn(self, tableName, column): self.query('ALTER TABLE %s DROP COLUMN %s' % (tableName, column.dbName)) def columnsFromSchema(self, tableName, soClass): colData = self.queryAll("SHOW COLUMNS FROM %s" % tableName) results = [] for field, t, nullAllowed, key, default, extra in colData: if field == 'id': continue colClass, kw = self.guessClass(t) if self.kw['use_unicode'] and colClass is col.StringCol: colClass = col.UnicodeCol kw['name'] = soClass.sqlmeta.style.dbColumnToPythonAttr(field) kw['notNone'] = not nullAllowed if default and t.startswith('int'): kw['default'] = int(default) else: kw['default'] = default # @@ skip key... # @@ skip extra... results.append(colClass(**kw)) return results def guessClass(self, t): if t.startswith('int'): return col.IntCol, {} elif t.startswith('varchar'): if t.endswith('binary'): return col.StringCol, {'length': int(t[8:-8]), 'char_binary': True} else: return col.StringCol, {'length': int(t[8:-1])} elif t.startswith('char'): if t.endswith('binary'): return col.StringCol, {'length': int(t[5:-8]), 'varchar': False, 'char_binary': True} else: return col.StringCol, {'length': int(t[5:-1]), 'varchar': False} elif t.startswith('datetime'): return col.DateTimeCol, {} elif t.startswith('bool'): return col.BoolCol, {} elif t.startswith('tinyblob'): return col.BLOBCol, {"length": 2**8-1} elif t.startswith('tinytext'): return col.StringCol, {"length": 2**8-1, "varchar": True} elif t.startswith('blob'): return col.BLOBCol, {"length": 2**16-1} elif t.startswith('text'): return col.StringCol, {"length": 2**16-1, "varchar": True} elif t.startswith('mediumblob'): return col.BLOBCol, {"length": 2**24-1} elif t.startswith('mediumtext'): return col.StringCol, {"length": 2**24-1, "varchar": True} elif t.startswith('longblob'): return col.BLOBCol, {"length": 2**32} elif t.startswith('longtext'): return col.StringCol, {"length": 2**32, "varchar": True} else: return col.Col, {} PKb95 M11sqlobject/mysql/__init__.pyc; Ec@s6dklZdZdZedgeedS((sregisterConnectioncCsdk}|iSdS(N(smysqlconnectionsMySQLConnection(smysqlconnection((s6build/bdist.linux-i686/egg/sqlobject/mysql/__init__.pysbuilders cCs/y dk}Wntj o tSnXtSdS(N(sMySQLdbs ImportErrorsFalsesTrue(sMySQLdb((s6build/bdist.linux-i686/egg/sqlobject/mysql/__init__.pys isSupporteds   smysqlN(ssqlobject.dbconnectionsregisterConnectionsbuilders isSupported(s isSupportedsbuildersregisterConnection((s6build/bdist.linux-i686/egg/sqlobject/mysql/__init__.pys?s   PKb95'+fR&R&#sqlobject/mysql/mysqlconnection.pyc; Ec@s:dklZdklZeadefdYZdS((sDBAPI(scolsMySQLConnectioncBstZeZdZegZddedZdZe eZdZ dZ dZ d Z d Zd Zd Zd ZdZdZdZdZdZdZRS(Nsmysqlss localhostcKsttjo dkant|_||_||_||_||_||_ h|_ ti ddjpMti ddjo9ti ddjp%ti ddjoti ddjo t |_ n t|_ xGdddddfD]0}||joti|||i ||io#t||i}|i|Sn|i|SWqti j oK}|i ddjo+|i o|i |t|dqqqXq WdS(NiiisERROR(sselfs need_unicodesunicodesquerysencodingsmyqueryscursorsexecutesMySQLdbsOperationalErrorsesargssdebugs printDebugsconnsstr(sselfsconnscursorsquerysesmyquery((s=build/bdist.linux-i686/egg/sqlobject/mysql/mysqlconnection.pys _executeRetryCs  !c Cs|ii} |ii}|i}|tj o|g|}|g|}n|i | ||}|io|i||dn|i||||tjo3y |i}Wqtj o|i}qXn|io|i||ddn|SdS(NsQueryInssresult(s soInstancessqlmetastablesidNamesconnscursorscsidsNonesnamessvaluessselfs _insertSQLsqsdebugs printDebugs _executeRetrys lastrowidsAttributeErrors insert_ids debugOutput( sselfsconns soInstancesidsnamessvaluesscsidNamesqstable((s=build/bdist.linux-i686/egg/sqlobject/mysql/mysqlconnection.pys_queryInsertIDTs$         cCsM| od||fSn| od||fSnd||||fSdS(Ns %s LIMIT %is%s LIMIT %i, -1s%s LIMIT %i, %i(sstartsquerysend(sselfsquerysstartsend((s=build/bdist.linux-i686/egg/sqlobject/mysql/mysqlconnection.pys_queryAddLimitOffseths cCs|iSdS(N(scolsmysqlCreateSQL(sselfssoClassscol((s=build/bdist.linux-i686/egg/sqlobject/mysql/mysqlconnection.pys createColumnoscCs|i|SdS(N(sindexsmysqlCreateIndexSQLssoClass(sselfssoClasssindex((s=build/bdist.linux-i686/egg/sqlobject/mysql/mysqlconnection.pyscreateIndexSQLrscCsd|iiSdS(Ns!%s INT PRIMARY KEY AUTO_INCREMENT(ssoClassssqlmetasidName(sselfssoClass((s=build/bdist.linux-i686/egg/sqlobject/mysql/mysqlconnection.pyscreateIDColumnuscCsdSdS(Ns INT NOT NULL((sselfsjoin((s=build/bdist.linux-i686/egg/sqlobject/mysql/mysqlconnection.pys joinSQLTypexscCsWy|id|tSWn7tij o(}|iddjotSnnXdS(Ns DESCRIBE %siiz( sselfsquerys tableNamesTruesMySQLdbsProgrammingErrorsesargssFalse(sselfs tableNamese((s=build/bdist.linux-i686/egg/sqlobject/mysql/mysqlconnection.pys tableExists{scCs!|id||ifdS(NsALTER TABLE %s ADD COLUMN %s(sselfsquerys tableNamescolumnsmysqlCreateSQL(sselfs tableNamescolumn((s=build/bdist.linux-i686/egg/sqlobject/mysql/mysqlconnection.pys addColumnscCs|id||ifdS(NsALTER TABLE %s DROP COLUMN %s(sselfsquerys tableNamescolumnsdbName(sselfs tableNamescolumn((s=build/bdist.linux-i686/egg/sqlobject/mysql/mysqlconnection.pys delColumnsc Cs|id|}g}x|D]\}} } } }}|djoq n|i | \}} |i do |tijo ti}n|iii|| d<| | d<|o | idot|| d0'90"+"+"+'(s__name__s __module__sFalsessupportTransactionssdbNamesschemessNones__init__sconnectionFromURIs classmethodsmakeConnections_setAutoCommits _executeRetrys_queryInsertIDs_queryAddLimitOffsets createColumnscreateIndexSQLscreateIDColumns joinSQLTypes tableExistss addColumns delColumnscolumnsFromSchemas guessClass(((s=build/bdist.linux-i686/egg/sqlobject/mysql/mysqlconnection.pysMySQLConnections(               N(ssqlobject.dbconnectionsDBAPIs sqlobjectscolsNonesMySQLdbsMySQLConnection(sMySQLConnectionscolsDBAPI((s=build/bdist.linux-i686/egg/sqlobject/mysql/mysqlconnection.pys?s  PKa95ŋ11"sqlobject/postgres/pgconnection.pyfrom sqlobject.dbconnection import DBAPI import re from sqlobject import col from sqlobject import sqlbuilder from sqlobject.converters import registerConverter psycopg = None pgdb = None class PostgresConnection(DBAPI): supportTransactions = True dbName = 'postgres' schemes = [dbName, 'postgresql', 'psycopg'] def __init__(self, dsn=None, host=None, port=None, db=None, user=None, passwd=None, usePygresql=False, unicodeCols=False, **kw): global psycopg, pgdb self.usePygresql = usePygresql if usePygresql: if pgdb is None: import pgdb self.module = pgdb else: if psycopg is None: try: import psycopg2 as psycopg except ImportError: import psycopg self.module = psycopg # Register a converter for psycopg Binary type. registerConverter(type(psycopg.Binary('')), PsycoBinaryConverter) self.user = user self.host = host self.port = port self.db = db self.password = passwd self.dsn_dict = dsn_dict = {} if host: dsn_dict["host"] = host if port: if usePygresql: dsn_dict["host"] = "%s:%d" % (host, port) else: dsn_dict["port"] = str(port) if db: dsn_dict["database"] = db if user: dsn_dict["user"] = user if passwd: dsn_dict["password"] = passwd self.use_dsn = dsn is not None if dsn is None: if usePygresql: dsn = '' if host: dsn += host dsn += ':' if db: dsn += db dsn += ':' if user: dsn += user dsn += ':' if passwd: dsn += passwd else: dsn = [] if db: dsn.append('dbname=%s' % db) if user: dsn.append('user=%s' % user) if passwd: dsn.append('password=%s' % passwd) if host: dsn.append('host=%s' % host) if port: dsn.append('port=%d' % port) dsn = ' '.join(dsn) self.dsn = dsn self.unicodeCols = unicodeCols DBAPI.__init__(self, **kw) # Server version cache self._server_version = None # Not yet initialized def connectionFromURI(cls, uri): user, password, host, port, path, args = cls._parseURI(uri) path = path.strip('/') if (host is None) and path.count('/'): # Non-default unix socket path_parts = path.split('/') host = '/' + '/'.join(path_parts[:-1]) path = path_parts[-1] return cls(host=host, port=port, db=path, user=user, passwd=password, **args) connectionFromURI = classmethod(connectionFromURI) def _setAutoCommit(self, conn, auto): # psycopg2 does not have an autocommit method. if hasattr(conn, 'autocommit'): conn.autocommit(auto) def makeConnection(self): try: if self.use_dsn: conn = self.module.connect(self.dsn) else: conn = self.module.connect(**self.dsn_dict) except self.module.OperationalError, e: raise self.module.OperationalError("%s; used connection string %r" % (e, self.dsn)) if self.autoCommit: # psycopg2 does not have an autocommit method. if hasattr(conn, 'autocommit'): conn.autocommit(1) return conn def _queryInsertID(self, conn, soInstance, id, names, values): table = soInstance.sqlmeta.table idName = soInstance.sqlmeta.idName sequenceName = soInstance.sqlmeta.idSequence or \ '%s_%s_seq' % (table, idName) c = conn.cursor() if id is None: c.execute("SELECT NEXTVAL('%s')" % sequenceName) id = c.fetchone()[0] names = [idName] + names values = [id] + values q = self._insertSQL(table, names, values) if self.debug: self.printDebug(conn, q, 'QueryIns') c.execute(q) if self.debugOutput: self.printDebug(conn, id, 'QueryIns', 'result') return id def _queryAddLimitOffset(self, query, start, end): if not start: return "%s LIMIT %i" % (query, end) if not end: return "%s OFFSET %i" % (query, start) return "%s LIMIT %i OFFSET %i" % (query, end-start, start) def createColumn(self, soClass, col): return col.postgresCreateSQL() def createIndexSQL(self, soClass, index): return index.postgresCreateIndexSQL(soClass) def createIDColumn(self, soClass): return '%s SERIAL PRIMARY KEY' % soClass.sqlmeta.idName def dropTable(self, tableName, cascade=False): if self.server_version[:3] <= "7.2": cascade=False self.query("DROP TABLE %s %s" % (tableName, cascade and 'CASCADE' or '')) def joinSQLType(self, join): return 'INT NOT NULL' def tableExists(self, tableName): if '.' in tableName and self.server_version[:3] >= "7.4": (table_schema, table_name) = tableName.split('.') query = """ SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = %s AND table_name = %s """ % (self.sqlrepr(table_schema), self.sqlrepr(table_name)) else: query = """ SELECT COUNT(relname) FROM pg_class WHERE relname = %s """ % self.sqlrepr(tableName) result = self.queryOne(query) return result[0] def addColumn(self, tableName, column): if hasattr(column, "postgresCreateColumnSQL"): postgresCreateSQL = column.postgresCreateColumnSQL else: postgresCreateSQL = column.postgresCreateSQL self.query('ALTER TABLE %s ADD COLUMN %s' % (tableName, postgresCreateSQL())) def delColumn(self, tableName, column): self.query('ALTER TABLE %s DROP COLUMN %s' % (tableName, column.dbName)) def columnsFromSchema(self, tableName, soClass): keyQuery = """ SELECT pg_catalog.pg_get_constraintdef(oid) as condef FROM pg_catalog.pg_constraint r WHERE r.conrelid = %s::regclass AND r.contype = 'f'""" colQuery = """ SELECT a.attname, pg_catalog.format_type(a.atttypid, a.atttypmod), a.attnotnull, (SELECT substring(d.adsrc for 128) FROM pg_catalog.pg_attrdef d WHERE d.adrelid=a.attrelid AND d.adnum = a.attnum) FROM pg_catalog.pg_attribute a WHERE a.attrelid =%s::regclass AND a.attnum > 0 AND NOT a.attisdropped ORDER BY a.attnum""" primaryKeyQuery = """ SELECT pg_index.indisprimary, pg_catalog.pg_get_indexdef(pg_index.indexrelid) FROM pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_index AS pg_index WHERE c.relname = %s AND c.oid = pg_index.indrelid AND pg_index.indexrelid = c2.oid AND pg_index.indisprimary """ keyData = self.queryAll(keyQuery % self.sqlrepr(tableName)) keyRE = re.compile(r"\((.+)\) REFERENCES (.+)\(") keymap = {} for (condef,) in keyData: match = keyRE.search(condef) if match: field, reftable = match.groups() keymap[field] = reftable.capitalize() primaryData = self.queryAll(primaryKeyQuery % self.sqlrepr(tableName)) primaryRE = re.compile(r'CREATE .*? USING .* \((.+?)\)') primaryKey = None for isPrimary, indexDef in primaryData: match = primaryRE.search(indexDef) assert match, "Unparseable contraint definition: %r" % indexDef assert primaryKey is None, "Already found primary key (%r), then found: %r" % (primaryKey, indexDef) primaryKey = match.group(1) assert primaryKey, "No primary key found in table %r" % tableName if primaryKey.startswith('"'): assert primaryKey.endswith('"') primaryKey = primaryKey[1:-1] colData = self.queryAll(colQuery % self.sqlrepr(tableName)) results = [] if self.unicodeCols: client_encoding = self.queryOne("SHOW client_encoding")[0] for field, t, notnull, defaultstr in colData: if field == primaryKey: continue colClass, kw = self.guessClass(t) if self.unicodeCols and colClass is col.StringCol: colClass = col.UnicodeCol kw['dbEncoding'] = client_encoding kw['name'] = soClass.sqlmeta.style.dbColumnToPythonAttr(field) kw['dbName'] = field kw['notNone'] = notnull if defaultstr is not None: kw['default'] = self.defaultFromSchema(colClass, defaultstr) elif not notnull: kw['default'] = None if keymap.has_key(field): kw['foreignKey'] = keymap[field] results.append(colClass(**kw)) return results def guessClass(self, t): if t.count('int'): return col.IntCol, {} elif t.count('varying') or t.count('varchar'): if '(' in t: return col.StringCol, {'length': int(t[t.index('(')+1:-1])} else: # varchar without length in Postgres means any length return col.StringCol, {} elif t.startswith('character('): return col.StringCol, {'length': int(t[t.index('(')+1:-1]), 'varchar': False} elif t.count('float') or t.count('real') or t.count('double'): return col.FloatCol, {} elif t == 'text': return col.StringCol, {} elif t.startswith('timestamp'): return col.DateTimeCol, {} elif t.startswith('datetime'): return col.DateTimeCol, {} elif t.startswith('date'): return col.DateCol, {} elif t.startswith('bool'): return col.BoolCol, {} elif t.startswith('bytea'): return col.BLOBCol, {} else: return col.Col, {} def defaultFromSchema(self, colClass, defaultstr): """ If the default can be converted to a python constant, convert it. Otherwise return is as a sqlbuilder constant. """ if colClass == col.BoolCol: if defaultstr == 'false': return False elif defaultstr == 'true': return True return getattr(sqlbuilder.const, defaultstr) def server_version(self): if self._server_version is None: # The result is something like # ' PostgreSQL 7.2.1 on i686-pc-linux-gnu, compiled by GCC 2.95.4' server_version = self.queryOne("SELECT version()")[0] self._server_version = server_version.split()[1] return self._server_version server_version = property(server_version) def createEmptyDatabase(self): # We have to connect to *some* database, so we'll connect to # template1, which is a common open database. # @@: This doesn't use self.use_dsn or self.dsn_dict if self.usePygresql: dsn = '%s:template1:%s:%s' % ( self.host or '', self.user or '', self.password or '') else: dsn = 'dbname=template1' if self.user: dsn += ' user=%s' % self.user if self.password: dsn += ' password=%s' % self.password if self.host: dsn += ' host=%s' % self.host conn = self.module.connect(dsn) cur = conn.cursor() # We must close the transaction with a commit so that # the CREATE DATABASE can work (which can't be in a transaction): cur.execute('COMMIT') cur.execute('CREATE DATABASE %s' % self.db) cur.close() conn.close() # Converter for psycopg Binary type. def PsycoBinaryConverter(value, db): assert db == 'postgres' return str(value) PKa95~esqlobject/postgres/__init__.pyfrom sqlobject.dbconnection import registerConnection def builder(): import pgconnection return pgconnection.PostgresConnection def isSupported(): try: import psycopg2 except ImportError: try: import psycopg except ImportError: return False return True registerConnection(['postgres', 'postgresql', 'psycopg'], builder, isSupported) PKb95 99#sqlobject/postgres/pgconnection.pyc; Ec@sldklZdkZdklZdklZdklZea ea defdYZ dZ dS((sDBAPIN(scol(s sqlbuilder(sregisterConvertersPostgresConnectionc BstZeZdZeddgZeeeeeeeedZdZ e e Z dZ dZ dZ d Zd Zd Zd Zed ZdZdZdZdZdZdZdZdZeeZdZRS(Nspostgress postgresqlspsycopgc Ks||_|o'ttjo dkant|_ncttjo0y dkaWqttj odkaqtXnt|_tt ti dt ||_ ||_ ||_||_||_h|_} |o|| d 0 AND NOT a.attisdropped ORDER BY a.attnumsm SELECT pg_index.indisprimary, pg_catalog.pg_get_indexdef(pg_index.indexrelid) FROM pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_index AS pg_index WHERE c.relname = %s AND c.oid = pg_index.indrelid AND pg_index.indexrelid = c2.oid AND pg_index.indisprimary s\((.+)\) REFERENCES (.+)\(sCREATE .*? USING .* \((.+?)\)s$Unparseable contraint definition: %rs.Already found primary key (%r), then found: %ris No primary key found in table %rs"isSHOW client_encodingis dbEncodingsnamesdbNamesnotNonesdefaults foreignKey(2skeyQueryscolQuerysprimaryKeyQuerysselfsqueryAllssqlreprs tableNameskeyDatasrescompileskeyREskeymapscondefssearchsmatchsgroupssfieldsreftables capitalizes primaryDatas primaryREsNones primaryKeys isPrimarysindexDefsAssertionErrorsgroups startswithsendswithscolDatasresultss unicodeColssqueryOnesclient_encodingstsnotnulls defaultstrs guessClassscolClassskwscols StringCols UnicodeColssoClassssqlmetasstylesdbColumnToPythonAttrsdefaultFromSchemashas_keysappend(sselfs tableNamessoClasssresultss isPrimarys primaryREsfieldsnotnullscolQueryskeyQuerysmatchstsclient_encodings primaryDataskeyREscolDatasprimaryKeyQuerys defaultstrscondefskeyDataskeymapskwsreftablescolClasssindexDefs primaryKey((s=build/bdist.linux-i686/egg/sqlobject/postgres/pgconnection.pyscolumnsFromSchemas`    !      cCs|idotihfSn|idp |idoRd|jo4tihdt||iddd!|djotSq>ntti|SdS(s If the default can be converted to a python constant, convert it. Otherwise return is as a sqlbuilder constant. sfalsestrueN( scolClassscolsBoolCols defaultstrsFalsesTruesgetattrs sqlbuildersconst(sselfscolClasss defaultstr((s=build/bdist.linux-i686/egg/sqlobject/postgres/pgconnection.pysdefaultFromSchema's   cCsE|itjo*|idd}|id|_n|iSdS(NsSELECT version()ii(sselfs_server_versionsNonesqueryOnesserver_versionssplit(sselfsserver_version((s=build/bdist.linux-i686/egg/sqlobject/postgres/pgconnection.pysserver_version3scCs|io5d|ipd|ipd|ipdf}ndd}|io|d|i7}n|io|d|i7}n|io|d|i7}n|ii|}|i }|i d|i d|i |i |i dS( Ns%s:template1:%s:%sssdbname=template1s user=%ss password=%ss host=%ssCOMMITsCREATE DATABASE %s(sselfs usePygresqlshostsuserspasswordsdsnsmodulesconnectsconnscursorscursexecutesdbsclose(sselfsdsnscursconn((s=build/bdist.linux-i686/egg/sqlobject/postgres/pgconnection.pyscreateEmptyDatabase<s 5      (s__name__s __module__sTruessupportTransactionssdbNamesschemessNonesFalses__init__sconnectionFromURIs classmethods_setAutoCommitsmakeConnections_queryInsertIDs_queryAddLimitOffsets createColumnscreateIndexSQLscreateIDColumns dropTables joinSQLTypes tableExistss addColumns delColumnscolumnsFromSchemas guessClasssdefaultFromSchemasserver_versionspropertyscreateEmptyDatabase(((s=build/bdist.linux-i686/egg/sqlobject/postgres/pgconnection.pysPostgresConnection s0!K              J   cCs"|djptt|SdS(Nspostgres(sdbsAssertionErrorsstrsvalue(svaluesdb((s=build/bdist.linux-i686/egg/sqlobject/postgres/pgconnection.pysPsycoBinaryConverterVs( ssqlobject.dbconnectionsDBAPIsres sqlobjectscols sqlbuilderssqlobject.converterssregisterConvertersNonespsycopgspgdbsPostgresConnectionsPsycoBinaryConverter(s sqlbuildersPsycoBinaryConvertersregisterConvertersresPostgresConnectionscolsDBAPI((s=build/bdist.linux-i686/egg/sqlobject/postgres/pgconnection.pys?s     NPKb95Uའsqlobject/postgres/__init__.pyc; Ec@s<dklZdZdZedddgeedS((sregisterConnectioncCsdk}|iSdS(N(s pgconnectionsPostgresConnection(s pgconnection((s9build/bdist.linux-i686/egg/sqlobject/postgres/__init__.pysbuilders cCsRy dk}Wn:tj o.y dk}WqJtj o tSqJXnXtSdS(N(spsycopg2s ImportErrorspsycopgsFalsesTrue(spsycopg2spsycopg((s9build/bdist.linux-i686/egg/sqlobject/postgres/__init__.pys isSupporteds  spostgress postgresqlspsycopgN(ssqlobject.dbconnectionsregisterConnectionsbuilders isSupported(s isSupportedsbuildersregisterConnection((s9build/bdist.linux-i686/egg/sqlobject/postgres/__init__.pys?s   PKa951v55sqlobject/sqlite/__init__.pyfrom sqlobject.dbconnection import registerConnection def builder(): import sqliteconnection return sqliteconnection.SQLiteConnection def isSupported(): try: import sqlite except ImportError: return False return True registerConnection(['sqlite'], builder, isSupported) PKa95y$sqlobject/sqlite/sqliteconnection.pyfrom sqlobject.dbconnection import DBAPI from sqlobject.col import popKey import thread sqlite = None using_sqlite2 = False sqlite2_Binary = None class SQLiteConnection(DBAPI): supportTransactions = True dbName = 'sqlite' schemes = [dbName] def __init__(self, filename, autoCommit=1, **kw): global sqlite global using_sqlite2 if sqlite is None: try: from pysqlite2 import dbapi2 as sqlite using_sqlite2 = True except ImportError: import sqlite using_sqlite2 = False self.module = sqlite self.filename = filename # full path to sqlite-db-file self._memory = filename == ':memory:' if self._memory: if not using_sqlite2: raise ValueError( "You must use sqlite2 to use in-memory databases") # connection options opts = {} if using_sqlite2: if autoCommit: opts["isolation_level"] = None if 'encoding' in kw: import warnings warnings.warn(DeprecationWarning("pysqlite2 does not support the encoding option")) opts["detect_types"] = sqlite.PARSE_DECLTYPES for col_type in "text", "char", "varchar": sqlite.register_converter(col_type, stop_pysqlite2_converting_strings_to_unicode) sqlite.register_converter(col_type.upper(), stop_pysqlite2_converting_strings_to_unicode) try: from sqlite import encode, decode except ImportError: import base64 sqlite.encode = base64.encodestring sqlite.decode = base64.decodestring else: sqlite.encode = encode sqlite.decode = decode global sqlite2_Binary if sqlite2_Binary is None: sqlite2_Binary = sqlite.Binary sqlite.Binary = lambda s: sqlite2_Binary(sqlite.encode(s)) else: opts['autocommit'] = bool(autoCommit) if 'encoding' in kw: opts['encoding'] = popKey(kw, 'encoding') if 'mode' in kw: opts['mode'] = int(popKey(kw, 'mode'), 0) if 'timeout' in kw: if using_sqlite2: opts['timeout'] = float(popKey(kw, 'timeout')) else: opts['timeout'] = int(float(popKey(kw, 'timeout')) * 1000) if 'check_same_thread' in kw: opts["check_same_thread"] = bool(popKey(kw, 'check_same_thread')) # use only one connection for sqlite - supports multiple) # cursors per connection self._connOptions = opts DBAPI.__init__(self, **kw) self._threadPool = {} self._threadOrigination = {} if self._memory: self._memoryConn = sqlite.connect( self.filename, **self._connOptions) def connectionFromURI(cls, uri): user, password, host, port, path, args = cls._parseURI(uri) assert host is None, ( "SQLite can only be used locally (with a URI like " "sqlite:///file or sqlite:/file, not %r)" % uri) assert user is None and password is None, ( "You may not provide usernames or passwords for SQLite " "databases") if path == "/:memory:": path = ":memory:" return cls(filename=path, **args) connectionFromURI = classmethod(connectionFromURI) def uri(self): return 'sqlite:///%s' % self.filename def getConnection(self): # SQLite can't share connections between threads, and so can't # pool connections. Since we are isolating threads here, we # don't have to worry about locking as much. if self._memory: conn = self.makeConnection() self._connectionNumbers[id(conn)] = self._connectionCount self._connectionCount += 1 return conn threadid = thread.get_ident() if (self._pool is not None and self._threadPool.has_key(threadid)): conn = self._threadPool[threadid] del self._threadPool[threadid] if conn in self._pool: self._pool.remove(conn) else: conn = self.makeConnection() if self._pool is not None: self._threadOrigination[id(conn)] = threadid self._connectionNumbers[id(conn)] = self._connectionCount self._connectionCount += 1 if self.debug: s = 'ACQUIRE' if self._pool is not None: s += ' pool=[%s]' % ', '.join([str(self._connectionNumbers[id(v)]) for v in self._pool]) self.printDebug(conn, s, 'Pool') return conn def releaseConnection(self, conn, explicit=False): if self._memory: return threadid = self._threadOrigination.get(id(conn)) DBAPI.releaseConnection(self, conn, explicit=explicit) if (self._pool is not None and threadid and not self._threadPool.has_key(threadid)): self._threadPool[threadid] = conn else: if self._pool and conn in self._pool: self._pool.remove(conn) conn.close() def _setAutoCommit(self, conn, auto): if using_sqlite2: if auto: conn.isolation_level = None else: conn.isolation_level = "" else: conn.autocommit = auto def _setIsolationLevel(self, conn, level): if not using_sqlite2: return conn.isolation_level = level def makeConnection(self): if self._memory: return self._memoryConn return sqlite.connect(self.filename, **self._connOptions) def _queryInsertID(self, conn, soInstance, id, names, values): table = soInstance.sqlmeta.table idName = soInstance.sqlmeta.idName c = conn.cursor() if id is not None: names = [idName] + names values = [id] + values q = self._insertSQL(table, names, values) if self.debug: self.printDebug(conn, q, 'QueryIns') c.execute(q) # lastrowid is a DB-API extension from "PEP 0249": if id is None: id = int(c.lastrowid) if self.debugOutput: self.printDebug(conn, id, 'QueryIns', 'result') return id def _insertSQL(self, table, names, values): if not names: assert not values # INSERT INTO table () VALUES () isn't allowed in # SQLite (though it is in other databases) return ("INSERT INTO %s VALUES (NULL)" % table) else: return DBAPI._insertSQL(self, table, names, values) def _queryAddLimitOffset(self, query, start, end): if not start: return "%s LIMIT %i" % (query, end) if not end: return "%s LIMIT 0 OFFSET %i" % (query, start) return "%s LIMIT %i OFFSET %i" % (query, end-start, start) def createColumn(self, soClass, col): return col.sqliteCreateSQL() def createIDColumn(self, soClass): return '%s INTEGER PRIMARY KEY' % soClass.sqlmeta.idName def joinSQLType(self, join): return 'INT NOT NULL' def tableExists(self, tableName): result = self.queryOne("SELECT tbl_name FROM sqlite_master WHERE type='table' AND tbl_name = '%s'" % tableName) # turn it into a boolean: return not not result def createIndexSQL(self, soClass, index): return index.sqliteCreateIndexSQL(soClass) def addColumn(self, tableName, column): self.query('ALTER TABLE %s ADD COLUMN %s' % (tableName, column.sqliteCreateSQL())) def delColumn(self, tableName, column): pass # Oops! There is no DROP COLUMN in SQLite def stop_pysqlite2_converting_strings_to_unicode(s): return s PKb95{x66sqlobject/sqlite/__init__.pyc; Ec@s6dklZdZdZedgeedS((sregisterConnectioncCsdk}|iSdS(N(ssqliteconnectionsSQLiteConnection(ssqliteconnection((s7build/bdist.linux-i686/egg/sqlobject/sqlite/__init__.pysbuilders cCs/y dk}Wntj o tSnXtSdS(N(ssqlites ImportErrorsFalsesTrue(ssqlite((s7build/bdist.linux-i686/egg/sqlobject/sqlite/__init__.pys isSupporteds   ssqliteN(ssqlobject.dbconnectionsregisterConnectionsbuilders isSupported(s isSupportedsbuildersregisterConnection((s7build/bdist.linux-i686/egg/sqlobject/sqlite/__init__.pys?s   PKb951]A((%sqlobject/sqlite/sqliteconnection.pyc; Ec@sXdklZdklZdkZeaeaea defdYZ dZ dS((sDBAPI(spopKeyNsSQLiteConnectioncBstZeZdZegZddZdZeeZdZ dZ e dZ dZ d Zd Zd Zd Zd ZdZdZdZdZdZdZdZRS(Nssqliteic Ksttjo@ydklataWqMtj odkataqMXnt|_ ||_ |dj|_ |i ot ot dqnh} to|ot| d8ss autocommitsmodeistimeoutischeck_same_thread(*ssqlitesNones pysqlite2sdbapi2sTrues using_sqlite2s ImportErrorsFalsesselfsmodulesfilenames_memorys ValueErrorsoptss autoCommitskwswarningsswarnsDeprecationWarningsPARSE_DECLTYPESscol_typesregister_converters,stop_pysqlite2_converting_strings_to_unicodesuppersencodesdecodesbase64s encodestrings decodestringssqlite2_BinarysBinarysboolspopKeysintsfloats _connOptionssDBAPIs__init__s _threadPools_threadOriginationsconnects _memoryConn( sselfsfilenames autoCommitskwsbase64sdecodesencodeswarningsscol_typesopts((s?build/bdist.linux-i686/egg/sqlobject/sqlite/sqliteconnection.pys__init__sp                    '     cCs|i|\}}}}}}|t jpt d||t jo |t jp t d|djo d}n|d||SdS(NsXSQLite can only be used locally (with a URI like sqlite:///file or sqlite:/file, not %r)s?You may not provide usernames or passwords for SQLite databasess /:memory:s:memory:sfilename( sclss _parseURIsurisuserspasswordshostsportspathsargssNonesAssertionError(sclssurisargsshostsuserspathspasswordsport((s?build/bdist.linux-i686/egg/sqlobject/sqlite/sqliteconnection.pysconnectionFromURIPs !$  cCsd|iSdS(Ns sqlite:///%s(sselfsfilename(sself((s?build/bdist.linux-i686/egg/sqlobject/sqlite/sqliteconnection.pysuri]sc Cs|io9|i}|i|it|<|id7_|Snti}|i t j o|i i |o?|i |}|i |=||i jo|i i|q nY|i}|i t j o||it|>sqlobject/sybase/__init__.pyc; Ec@s6dklZdZdZedgeedS((sregisterConnectioncCsdk}|iSdS(N(ssybaseconnectionsSybaseConnection(ssybaseconnection((s7build/bdist.linux-i686/egg/sqlobject/sybase/__init__.pysbuilders cCs/y dk}Wntj o tSnXtSdS(N(sSybases ImportErrorsFalsesTrue(sclssSybase((s7build/bdist.linux-i686/egg/sqlobject/sybase/__init__.pys isSupporteds   ssybaseN(ssqlobject.dbconnectionsregisterConnectionsbuilders isSupported(s isSupportedsbuildersregisterConnection((s7build/bdist.linux-i686/egg/sqlobject/sybase/__init__.pys?s   PKb956I"I"%sqlobject/sybase/sybaseconnection.pyc; Ec@s:dklZdklZeadefdYZdS((sDBAPI(scolsSybaseConnectioncBstZeZdZegZddddZdZeeZdZ dZ d Z d Z d Z d Zd ZdZdZdZdZdZdZdZdZdZdZdZRS(Nssybasess localhostic Ks|id}ttjoFdkadti_dkl} dkl}l } || | nt|_ t ||_ ||_||_||_||_|id}|ot |} nt}||d|i|iD]*\}|i|ijotSqqWtSdS(N(sselfsqueryAlls SHOW_TABLESstableslowers tableNamesTruesFalse(sselfs tableNamestable((s?build/bdist.linux-i686/egg/sqlobject/sybase/sybaseconnection.pys tableExiststs   cCs!|id||ifdS(NsALTER TABLE %s ADD COLUMN %s(sselfsquerys tableNamescolumnssybaseCreateSQL(sselfs tableNamescolumn((s?build/bdist.linux-i686/egg/sqlobject/sybase/sybaseconnection.pys addColumnzscCs|id||ifdS(NsALTER TABLE %s DROP COLUMN %s(sselfsquerys tableNamescolumnsdbName(sselfs tableNamescolumn((s?build/bdist.linux-i686/egg/sqlobject/sybase/sybaseconnection.pys delColumnssrSELECT COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_DEFAULT FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '%s'c Cs|i|i|}g}x|D]\}} }}|djoq#n|i | \} }|iii||d<| |d<||d 27 April 2004 This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. connection creation sample __connection__ = DBConnection.maxdbConnection( host=hostname, database=dbname, user=user_name, password=user_password,autoCommit=1,debug=1) """ from sqlobject.dbconnection import DBAPI from sqlobject import col dbapi = None class maxdbException(Exception): def __init__(self, value): self.value = value def __str__(self): return repr(self.value) class LowerBoundOfSliceIsNotSupported(maxdbException): def __init__(self, value): maxdbException.__init__(self, '') class IncorrectIDStyleError(maxdbException) : def __init__(self,value): maxdbException.__init__( self, 'This primary key name is not in the expected style, ' 'please rename the column to %r or switch to another style' % value) class StyleMismatchError(maxdbException): def __init__(self, value): maxdbException.__init__( self, 'The name %r is only permitted for primary key, change the ' 'column name or switch to another style' % value) class PrimaryKeyNotFounded(maxdbException): def __init__(self, value): maxdbException.__init__( self, "No primary key was defined on table %r" % value) SAPDBMAX_ID_LENGTH=32 class MaxdbConnection(DBAPI): supportTransactions = True dbName = 'maxdb' schemes = [dbName] def __init__ (self, user, password, database, host='', autoCommit=1, sqlmode='internal', isolation=None, timeout=None, **kw): global dbapi if dbapi is None: from sapdb import dbapi self.module = dbapi self.autoCommit = autoCommit self.user = user self.password = password self.database = database self.host = host self.sqlmode = sqlmode self.isolation = isolation self.timeout = timeout DBAPI.__init__(self, **kw) def connectionFromURI(cls, uri): auth, password, host, port, path, args = cls._parseURI(uri) path = path.replace('/', os.path.sep) return cls(host, db=path, user=auth, passwd=password, **args) connectionFromURI = classmethod(connectionFromURI) def _getConfigParams(self,sqlmode,auto): autocommit='off' if auto: autocommit='on' opt = {} opt["autocommit"] = autocommit opt["sqlmode"] = sqlmode if self.isolation: opt["isolation"]=self.isolation if self.timeout : opt["timeout"]=self.timeout return opt def _setAutoCommit(self, conn, auto): conn.close() conn.__init__(self.user, self.password, self.database, self.host, **self._getConfigParams(self.sqlmode,auto)) def createSequenceName(self,table): """ sequence name are builded with the concatenation of the table name with '_SEQ' word we truncate the name of the sequence_name because sapdb identifier cannot exceed 32 characters so that the name of the sequence does not exceed 32 characters """ return '%s_SEQ'%(table[:SAPDBMAX_ID_LENGTH -4]) def makeConnection(self): conn = dbapi.Connection( self.user, self.password, self.database, self.host, **self._getConfigParams(self.sqlmode,self.autoCommit)) return conn def _queryInsertID(self, conn, soInstance, id, names, values): table = soInstance.sqlmeta.table idName = soInstance.sqlmeta.idName c = conn.cursor() if id is None: c.execute('SELECT %s.NEXTVAL FROM DUAL' % (self.createSequenceName(table))) id = c.fetchone()[0] names = [idName] + names values = [id] + values q = self._insertSQL(table, names, values) if self.debug: self.printDebug(conn, q, 'QueryIns') c.execute(q) if self.debugOutput: self.printDebug(conn, id, 'QueryIns', 'result') return id def sqlAddLimit(self,query,limit): sql = query sql = sql.replace("SELECT","SELECT ROWNO, ") if sql.find('WHERE') != -1: sql = sql + ' AND ' + limit else: sql = sql + 'WHERE ' + limit return sql def _queryAddLimitOffset(self, query, start, end): if start: raise LowerBoundOfSliceIsNotSupported limit = ' ROWNO <= %d ' % (end) return self.sqlAddLimit(query,limit) def createTable(self, soClass): #we create the table in a transaction because the addition of the #table and the sequence must be atomic #i tried to use the transaction class but i get a recursion limit error #t=self.transaction() # t.query('CREATE TABLE %s (\n%s\n)' % \ # (soClass.sqlmeta.table, self.createColumns(soClass))) # # t.query("CREATE SEQUENCE %s" % self.createSequenceName(soClass.sqlmeta.table)) # t.commit() #so use transaction when the problem will be solved self.query('CREATE TABLE %s (\n%s\n)' % \ (soClass.sqlmeta.table, self.createColumns(soClass))) self.query("CREATE SEQUENCE %s" % self.createSequenceName(soClass.sqlmeta.table)) def createColumn(self, soClass, col): return col.maxdbCreateSQL() def createIDColumn(self, soClass): return '%s INT PRIMARY KEY' % soClass.sqlmeta.idName def createIndexSQL(self, soClass, index): return index.maxdbCreateIndexSQL(soClass) def dropTable(self, tableName,cascade=False): #we drop the table in a transaction because the removal of the #table and the sequence must be atomic #i tried to use the transaction class but i get a recursion limit error # try: # t=self.transaction() # t.query("DROP TABLE %s" % tableName) # t.query("DROP SEQUENCE %s" % self.createSequenceName(tableName)) # t.commit() # except: # t.rollback() #so use transaction when the problem will be solved self.query("DROP TABLE %s" % tableName) self.query("DROP SEQUENCE %s" % self.createSequenceName(tableName)) def joinSQLType(self, join): return 'INT NOT NULL' def tableExists(self, tableName): for (table,) in self.queryAll("SELECT OBJECT_NAME FROM ALL_OBJECTS WHERE OBJECT_TYPE='TABLE'"): if table.lower() == tableName.lower(): return True return False def addColumn(self, tableName, column): self.query('ALTER TABLE %s ADD %s' % (tableName, column.maxdbCreateSQL())) def delColumn(self, tableName, column): self.query('ALTER TABLE %s DROP COLUMN %s' % (tableName, column.dbName)) GET_COLUMNS = """ SELECT COLUMN_NAME, NULLABLE, DATA_DEFAULT, DATA_TYPE, DATA_LENGTH, DATA_SCALE FROM USER_TAB_COLUMNS WHERE TABLE_NAME=UPPER('%s')""" GET_PK_AND_FK = """ SELECT constraint_cols.column_name, constraints.constraint_type, refname,reftablename FROM user_cons_columns constraint_cols INNER JOIN user_constraints constraints ON constraint_cols.constraint_name = constraints.constraint_name LEFT OUTER JOIN show_foreign_key fk ON constraint_cols.column_name = fk.columnname WHERE constraints.table_name =UPPER('%s')""" def columnsFromSchema(self, tableName, soClass): colData = self.queryAll(self.GET_COLUMNS % tableName) results = [] keymap = {} pkmap={} fkData = self.queryAll(self.GET_PK_AND_FK% tableName) for col, cons_type, refcol, reftable in fkData: col_name= col.lower() pkmap[col_name]=False if cons_type == 'R': keymap[col_name]=reftable.lower() elif cons_type == 'P': pkmap[col_name]=True if len(pkmap) == 0: raise PrimaryKeyNotFounded, tableName for (field, nullAllowed, default, data_type, data_len, data_scale) in colData: # id is defined as primary key --> ok # We let sqlobject raise error if the 'id' is used for another column field_name = field.lower() if field_name == 'id' and pkmap[field_name]: continue colClass, kw = self.guessClass(data_type,data_len,data_scale) kw['name'] = field_name if nullAllowed == 'Y' : nullAllowed=False else: nullAllowed=True kw['notNone'] = nullAllowed if default is not None: kw['default'] = default if keymap.has_key(field_name): kw['foreignKey'] = keymap[field_name] results.append(colClass(**kw)) return results _numericTypes=['INTEGER', 'INT','SMALLINT'] _dateTypes=['DATE','TIME','TIMESTAMP'] def guessClass(self, t, flength, fscale=None): """ An internal method that tries to figure out what Col subclass is appropriate given whatever introspective information is available -- both very database-specific. """ if t in self._numericTypes: return col.IntCol, {} # The type returned by the sapdb library for LONG is # SapDB_LongReader To get the data call the read member with # desired size (default =-1 means get all) elif t.find('LONG') != -1: return col.StringCol, {'length': flength, 'varchar': False} elif t in self._dateTypes: return col.DateTimeCol, {} elif t == 'FIXED': return CurrencyCol,{'size':flength, 'precision':fscale} else: return col.Col, {} PKa95177sqlobject/maxdb/__init__.pyfrom sqlobject.dbconnection import registerConnection def builder(): import maxdbconnection return maxdbconnection.MaxdbConnection def isSupported(): try: import sapdb except ImportError: return False return True registerConnection(['maxdb','sapdb'],builder, isSupported) PKb95x8Pm:m:#sqlobject/maxdb/maxdbconnection.pyc; Ec@sdZdklZdklZeadefdYZdefdYZ defdYZ d efd YZ d efd YZ d Z defdYZdS(s Contributed by Edigram SAS,Paris France Tel:01 44 77 94 00 Ahmed MOHAMED ALI 27 April 2004 This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. connection creation sample __connection__ = DBConnection.maxdbConnection( host=hostname, database=dbname, user=user_name, password=user_password,autoCommit=1,debug=1) (sDBAPI(scolsmaxdbExceptioncBstZdZdZRS(NcCs ||_dS(N(svaluesself(sselfsvalue((s=build/bdist.linux-i686/egg/sqlobject/maxdb/maxdbconnection.pys__init__scCst|iSdS(N(sreprsselfsvalue(sself((s=build/bdist.linux-i686/egg/sqlobject/maxdb/maxdbconnection.pys__str__s(s__name__s __module__s__init__s__str__(((s=build/bdist.linux-i686/egg/sqlobject/maxdb/maxdbconnection.pysmaxdbExceptions sLowerBoundOfSliceIsNotSupportedcBstZdZRS(NcCsti|ddS(Ns(smaxdbExceptions__init__sself(sselfsvalue((s=build/bdist.linux-i686/egg/sqlobject/maxdb/maxdbconnection.pys__init__s(s__name__s __module__s__init__(((s=build/bdist.linux-i686/egg/sqlobject/maxdb/maxdbconnection.pysLowerBoundOfSliceIsNotSupportedssIncorrectIDStyleErrorcBstZdZRS(NcCsti|d|dS(NsmThis primary key name is not in the expected style, please rename the column to %r or switch to another style(smaxdbExceptions__init__sselfsvalue(sselfsvalue((s=build/bdist.linux-i686/egg/sqlobject/maxdb/maxdbconnection.pys__init__"s (s__name__s __module__s__init__(((s=build/bdist.linux-i686/egg/sqlobject/maxdb/maxdbconnection.pysIncorrectIDStyleError!ssStyleMismatchErrorcBstZdZRS(NcCsti|d|dS(Ns`The name %r is only permitted for primary key, change the column name or switch to another style(smaxdbExceptions__init__sselfsvalue(sselfsvalue((s=build/bdist.linux-i686/egg/sqlobject/maxdb/maxdbconnection.pys__init__*s (s__name__s __module__s__init__(((s=build/bdist.linux-i686/egg/sqlobject/maxdb/maxdbconnection.pysStyleMismatchError)ssPrimaryKeyNotFoundedcBstZdZRS(NcCsti|d|dS(Ns&No primary key was defined on table %r(smaxdbExceptions__init__sselfsvalue(sselfsvalue((s=build/bdist.linux-i686/egg/sqlobject/maxdb/maxdbconnection.pys__init__1s (s__name__s __module__s__init__(((s=build/bdist.linux-i686/egg/sqlobject/maxdb/maxdbconnection.pysPrimaryKeyNotFounded0si sMaxdbConnectioncBstZeZdZegZdddeedZdZe eZdZ dZ d Z d Z d Zd Zd ZdZdZdZdZedZdZdZdZdZdZdZdZdddgZdddgZed Z RS(!Nsmaxdbsisinternalc Ksttjodklant|_||_||_||_||_||_ ||_ ||_ ||_ t i|| dS(N(sdbapi(sdbapisNonessapdbsselfsmodules autoCommitsuserspasswordsdatabaseshostssqlmodes isolationstimeoutsDBAPIs__init__skw( sselfsuserspasswordsdatabaseshosts autoCommitssqlmodes isolationstimeoutskw((s=build/bdist.linux-i686/egg/sqlobject/maxdb/maxdbconnection.pys__init__>s          c Cs\|i|\}}}}}}|i dt ii }||d|d|d||SdS(Ns/sdbsuserspasswd( sclss _parseURIsurisauthspasswordshostsportspathsargssreplacesosssep(sclssurisargssauthshostspathspasswordsport((s=build/bdist.linux-i686/egg/sqlobject/maxdb/maxdbconnection.pysconnectionFromURIPs!cCsod}|o d}nh}||d<||d<|io|i|dtZdZeidZeidZeidZRS(NcCsh|id self.max_args: self.runner.invalid( self.max_args_error % {'max_args': self.max_args, 'actual_args': len(self.args)}) for var_name, option_name in self.required_args: if not getattr(self.options, var_name, None): self.runner.invalid( 'You must provide the option %s' % option_name) conf = self.config() if conf and conf.get('sys_path'): update_sys_path(conf['sys_path'], self.options.verbose) if conf and conf.get('database'): conn = sqlobject.connectionForURI(conf['database']) sqlobject.sqlhub.processConnection = conn for egg_spec in getattr(self.options, 'eggs', []): self.load_options_from_egg(egg_spec) self.command() def classes(self, require_connection=True, require_some=False): all = [] conf = self.config() for module_name in self.options.modules: all.extend(self.classes_from_module( moduleloader.load_module(module_name))) for package_name in self.options.packages: all.extend(self.classes_from_package(package_name)) for egg_spec in self.options.eggs: all.extend(self.classes_from_egg(egg_spec)) if self.options.class_matchers: filtered = [] for soClass in all: name = soClass.__name__ for matcher in self.options.class_matchers: if fnmatch.fnmatch(name, matcher): filtered.append(soClass) break all = filtered conn = self.connection() if conn: for soClass in all: soClass._connection = conn else: missing = [] for soClass in all: try: if not soClass._connection: missing.append(soClass) except AttributeError: missing.append(soClass) if missing and require_connection: self.runner.invalid( 'These classes do not have connections set:\n * %s\n' 'You must indicate --connection=URI' % '\n * '.join([soClass.__name__ for soClass in missing])) if require_some and not all: print 'No classes found!' if self.options.modules: print 'Looked in modules: %s' % ', '.join(self.options.modules) else: print 'No modules specified' if self.options.packages: print 'Looked in packages: %s' % ', '.join(self.options.packages) else: print 'No packages specified' if self.options.class_matchers: print 'Matching class pattern: %s' % self.options.class_matches if self.options.eggs: print 'Looked in eggs: %s' % ', '.join(self.options.eggs) else: print 'No eggs specified' sys.exit(1) return all def classes_from_module(self, module): all = [] if hasattr(module, 'soClasses'): for name_or_class in module.soClasses: if isinstance(name_or_class, str): name_or_class = getattr(module, name_or_class) all.append(name_or_class) else: for name in dir(module): value = getattr(module, name) if (isinstance(value, type) and issubclass(value, sqlobject.SQLObject) and value.__module__ == module.__name__): all.append(value) return all def connection(self): config = self.config() if config is not None: assert config.get('database'), ( "No database variable found in config file %s" % self.options.config_file) return sqlobject.connectionForURI(config['database']) elif getattr(self.options, 'connection_uri', None): return sqlobject.connectionForURI(self.options.connection_uri) else: return None def config(self): if not getattr(self.options, 'config_file', None): return None if pyconfig and self.options.config_fn.endswith('.conf'): config = pyconfig.Config(with_default=True) config.load(self.options.config_file) CONFIG.push_process_config(config) return config else: return self.ini_config(self.options.config_file) def ini_config(self, conf_fn): conf_section = 'main' if '#' in conf_fn: conf_fn, conf_section = conf_fn.split('#', 1) from ConfigParser import ConfigParser p = ConfigParser() # Case-sensitive: p.optionxform = str if not os.path.exists(conf_fn): # Stupid RawConfigParser doesn't give an error for # non-existant files: raise OSError( "Config file %s does not exist" % self.options.config_file) p.read([conf_fn]) p._defaults.setdefault( 'here', os.path.dirname(os.path.abspath(conf_fn))) possible_sections = [] for section in p.sections(): name = section.strip().lower() if (conf_section == name or (conf_section == name.split(':')[-1] and name.split(':')[0] in ('app', 'application'))): possible_sections.append(section) if not possible_sections: raise OSError( "Config file %s does not have a section [%s] or [*:%s]" % (conf_fn, conf_section, conf_section)) if len(possible_sections) > 1: raise OSError( "Config file %s has multiple sections matching %s: %s" % (conf_fn, conf_section, ', '.join(possible_sections))) config = {} for op in p.options(possible_sections[0]): config[op] = p.get(possible_sections[0], op) return config def classes_from_package(self, package_name): all = [] package = moduleloader.load_module(package_name) package_dir = os.path.dirname(package.__file__) def find_classes_in_file(arg, dir_name, filenames): if dir_name.startswith('.svn'): return filenames = filter(lambda fname: fname.endswith('.py') and fname != '__init__.py', filenames) for fname in filenames: module_name = os.path.join(dir_name, fname) module_name = module_name[module_name.find(package_name):] module_name = module_name.replace(os.path.sep,'.')[:-3] try: module = moduleloader.load_module(module_name) except ImportError, err: if self.options.verbose: print 'Could not import module "%s". Error was : "%s"' % (module_name, err) continue except Exception, exc: if self.options.verbose: print 'Unknown exception while processing module "%s" : "%s"' % (module_name, exc) continue classes = self.classes_from_module(module) all.extend(classes) os.path.walk(package_dir, find_classes_in_file, None) return all def classes_from_egg(self, egg_spec): modules = [] dist, conf = self.config_from_egg(egg_spec, warn_no_sqlobject=True) for mod in conf.get('db_module', '').split(','): mod = mod.strip() if not mod: continue if self.options.verbose: print 'Looking in module %s' % mod modules.extend(self.classes_from_module( moduleloader.load_module(mod))) return modules def load_options_from_egg(self, egg_spec): dist, conf = self.config_from_egg(egg_spec) if (hasattr(self.options, 'output_dir') and not self.options.output_dir and conf.get('history_dir')): dir = conf['history_dir'] dir = dir.replace('$base', dist.location) self.options.output_dir = dir def config_from_egg(self, egg_spec, warn_no_sqlobject=True): import pkg_resources dist = pkg_resources.get_distribution(egg_spec) if not dist.has_metadata('sqlobject.txt'): if warn_no_sqlobject: print 'No sqlobject.txt in %s egg info' % egg_spec return {} result = {} for line in dist.get_metadata_lines('sqlobject.txt'): line = line.strip() if not line or line.startswith('#'): continue name, value = line.split('=', 1) name = name.strip().lower() if name in result: print 'Warning: %s appears more than one in sqlobject.txt' % name result[name.strip().lower()] = value.strip() return dist, result def command(self): raise NotImplementedError def _get_prog_name(self): return os.path.basename(self.invoked_as) prog_name = property(_get_prog_name) def ask(self, prompt, safe=False, default=True): if self.options.interactive >= 2: default = safe if default: prompt += ' [Y/n]? ' else: prompt += ' [y/N]? ' while 1: response = raw_input(prompt).strip() if not response.strip(): return default if response and response[0].lower() in ('y', 'n'): return response[0].lower() == 'y' print 'Y or N please' def shorten_filename(self, fn): """ Shortens a filename to make it relative to the current directory (if it can). For display purposes. """ if fn.startswith(os.getcwd() + '/'): fn = fn[len(os.getcwd())+1:] return fn def open_editor(self, pretext, breaker=None, extension='.txt'): """ Open an editor with the given text. Return the new text, or None if no edits were made. If given, everything after `breaker` will be ignored. """ fn = nowarning_tempnam() + extension f = open(fn, 'w') f.write(pretext) f.close() print '$EDITOR %s' % fn os.system('$EDITOR %s' % fn) f = open(fn, 'r') content = f.read() f.close() if breaker: content = content.split(breaker)[0] pretext = pretext.split(breaker)[0] if content == pretext or not content.strip(): return None return content class CommandSQL(Command): name = 'sql' summary = 'Show SQL CREATE statements' parser = standard_parser(simulate=False) def command(self): classes = self.classes() for cls in classes: if self.options.verbose >= 1: print '-- %s from %s' % ( cls.__name__, cls.__module__) print cls.createTableSQL().strip() + ';\n' class CommandList(Command): name = 'list' summary = 'Show all SQLObject classes found' parser = standard_parser(simulate=False, connection=False) def command(self): if self.options.verbose >= 1: print 'Classes found:' classes = self.classes(require_connection=False) for soClass in classes: print '%s.%s' % (soClass.__module__, soClass.__name__) if self.options.verbose >= 1: print ' Table: %s' % soClass.sqlmeta.table class CommandCreate(Command): name = 'create' summary = 'Create tables' parser = standard_parser(interactive=True) parser.add_option('--create-db', action='store_true', dest='create_db', help="Create the database") def command(self): v = self.options.verbose created = 0 existing = 0 dbs_created = [] for soClass in self.classes(require_some=True): if (self.options.create_db and soClass._connection not in dbs_created): if not self.options.simulate: try: soClass._connection.createEmptyDatabase() except soClass._connection.module.ProgrammingError, e: if str(e).find('already exists') != -1: print 'Database already exists' else: raise else: print '(simulating; cannot create database)' dbs_created.append(soClass._connection) exists = soClass._connection.tableExists(soClass.sqlmeta.table) if v >= 1: if exists: existing += 1 print '%s already exists.' % soClass.__name__ else: print 'Creating %s' % soClass.__name__ if v >= 2: print soClass.createTableSQL() if (not self.options.simulate and not exists): if self.options.interactive: if self.ask('Create %s' % soClass.__name__): created += 1 soClass.createTable() else: print 'Cancelled' else: created += 1 soClass.createTable() if v >= 1: print '%i tables created (%i already exist)' % ( created, existing) class CommandDrop(Command): name = 'drop' summary = 'Drop tables' parser = standard_parser(interactive=True) def command(self): v = self.options.verbose dropped = 0 not_existing = 0 for soClass in self.classes(): exists = soClass._connection.tableExists(soClass.sqlmeta.table) if v >= 1: if exists: print 'Dropping %s' % soClass.__name__ else: not_existing += 1 print '%s does not exist.' % soClass.__name__ if (not self.options.simulate and exists): if self.options.interactive: if self.ask('Drop %s' % soClass.__name__): dropped += 1 soClass.dropTable() else: print 'Cancelled' else: dropped += 1 soClass.dropTable() if v >= 1: print '%i tables dropped (%i didn\'t exist)' % ( dropped, not_existing) class CommandStatus(Command): name = 'status' summary = 'Show status of classes vs. database' help = ('This command checks the SQLObject definition and checks if ' 'the tables in the database match. It can always test for ' 'missing tables, and on some databases can test for the ' 'existance of other tables. Column types are not currently ' 'checked.') parser = standard_parser(simulate=False) def print_class(self, soClass): if self.printed: return self.printed = True print 'Checking %s...' % soClass.__name__ def command(self): good = 0 bad = 0 missing_tables = 0 columnsFromSchema_warning = False for soClass in self.classes(require_some=True): conn = soClass._connection self.printed = False if self.options.verbose: self.print_class(soClass) if not conn.tableExists(soClass.sqlmeta.table): self.print_class(soClass) print ' Does not exist in database' missing_tables += 1 continue try: columns = conn.columnsFromSchema(soClass.sqlmeta.table, soClass) except AttributeError: if not columnsFromSchema_warning: print 'Database does not support reading columns' columnsFromSchema_warning = True good += 1 continue except AssertionError, e: print 'Cannot read db table %s: %s' % ( soClass.sqlmeta.table, e) continue existing = {} for col in columns: col = col.withClass(soClass) existing[col.dbName] = col missing = {} for col in soClass.sqlmeta.columnList: if existing.has_key(col.dbName): del existing[col.dbName] else: missing[col.dbName] = col if existing: self.print_class(soClass) for col in existing.values(): print ' Database has extra column: %s' % col.dbName if missing: self.print_class(soClass) for col in missing.values(): print ' Database missing column: %s' % col.dbName if existing or missing: bad += 1 else: good += 1 if self.options.verbose: print '%i in sync; %i out of sync; %i not in database' % ( good, bad, missing_tables) class CommandHelp(Command): name = 'help' summary = 'Show help' parser = optparse.OptionParser() max_args = 1 def command(self): if self.args: the_runner.run([self.invoked_as, self.args[0], '-h']) else: print 'Available commands:' print ' (use "%s help COMMAND" or "%s COMMAND -h" ' % ( self.prog_name, self.prog_name) print ' for more information)' items = the_runner.commands.items() items.sort() max_len = max([len(cn) for cn, c in items]) for command_name, command in items: print '%s:%s %s' % (command_name, ' '*(max_len-len(command_name)), command.summary) if command.aliases: print '%s (Aliases: %s)' % ( ' '*max_len, ', '.join(command.aliases)) class CommandExecute(Command): name = 'execute' summary = 'Execute SQL statements' help = ('Runs SQL statements directly in the database, with no ' 'intervention. Useful when used with a configuration file. ' 'Each argument is executed as an individual statement.') parser = standard_parser(find_modules=False) parser.add_option('--stdin', help="Read SQL from stdin (normally takes SQL from the command line)", dest="use_stdin", action="store_true") max_args = None def command(self): args = self.args if self.options.use_stdin: if self.options.verbose: print "Reading additional SQL from stdin (Ctrl-D or Ctrl-Z to finish)..." args.append(sys.stdin.read()) self.conn = self.connection().getConnection() self.cursor = self.conn.cursor() for sql in args: self.execute_sql(sql) def execute_sql(self, sql): if self.options.verbose: print sql try: self.cursor.execute(sql) except Exception, e: if not self.options.verbose: print sql print "****Error:" print ' ', e return desc = self.cursor.description rows = self.cursor.fetchall() if self.options.verbose: if not self.cursor.rowcount: print "No rows accessed" else: print "%i rows accessed" % self.cursor.rowcount if desc: for name, type_code, display_size, internal_size, precision, scale, null_ok in desc: sys.stdout.write("%s\t" % name) sys.stdout.write("\n") for row in rows: for col in row: sys.stdout.write("%r\t" % col) sys.stdout.write("\n") print class CommandRecord(Command): name = 'record' summary = 'Record historical information about the database status' help = ('Record state of table definitions. The state of each ' 'table is written out to a separate file in a directory, ' 'and that directory forms a "version". A table is also ' 'added to you datebase (%s) that reflects the version the ' 'database is currently at. Use the upgrade command to ' 'sync databases with code.' % SQLObjectVersionTable.sqlmeta.table) parser = standard_parser() parser.add_option('--output-dir', help="Base directory for recorded definitions", dest="output_dir", metavar="DIR", default=None) parser.add_option('--no-db-record', help="Don't record version to database", dest="db_record", action="store_false", default=True) parser.add_option('--force-create', help="Create a new version even if appears to be " "identical to the last version", action="store_true", dest="force_create") parser.add_option('--name', help="The name to append to the version. The " "version should sort after previous versions (so " "any versions from the same day should come " "alphabetically before this version).", dest="version_name", metavar="NAME") parser.add_option('--force-db-version', help="Update the database version, and include no " "database information. This is for databases that " "were developed without any interaction with " "this tool, to create a 'beginning' revision.", metavar="VERSION_NAME", dest="force_db_version") parser.add_option('--edit', help="Open an editor for the upgrader in the last " "version (using $EDITOR).", action="store_true", dest="open_editor") version_regex = re.compile(r'^\d\d\d\d-\d\d-\d\d') def command(self): if self.options.force_db_version: self.command_force_db_version() return v = self.options.verbose sim = self.options.simulate classes = self.classes() if not classes: print "No classes found!" return output_dir = self.find_output_dir() version = os.path.basename(output_dir) print "Creating version %s" % version conns = [] files = {} for cls in self.classes(): dbName = cls._connection.dbName if cls._connection not in conns: conns.append(cls._connection) fn = os.path.join(cls.__name__ + '_' + dbName + '.sql') if sim: continue # @@: This is a little hacky, but sometimes I'm getting string # results here, and sometimes tuples (apparently, if the code is # meant to work?), so we'll allow for both result = cls.createTableSQL() if isinstance(result, basestring): create = result constraints = [] else: create, constraints = result if constraints: constraints = '\n-- Constraints:\n%s\n' % ( '\n'.join(constraints)) else: constraints = '' files[fn] = ''.join([ '-- Exported definition from %s\n' % time.strftime('%Y-%m-%dT%H:%M:%S'), '-- Class %s.%s\n' % (cls.__module__, cls.__name__), '-- Database: %s\n' % dbName, create.strip(), '\n', constraints]) last_version_dir = self.find_last_version() if last_version_dir and not self.options.force_create: if v > 1: print "Checking %s to see if it is current" % last_version_dir files_copy = files.copy() for fn in os.listdir(last_version_dir): if not fn.endswith('.sql'): continue if not files_copy.has_key(fn): if v > 1: print "Missing file %s" % fn break f = open(os.path.join(last_version_dir, fn), 'r') content = f.read() f.close() if (self.strip_comments(files_copy[fn]) != self.strip_comments(content)): if v > 1: print "Content does not match: %s" % fn break del files_copy[fn] else: # No differences so far if not files_copy: # Used up all files print ("Current status matches version %s" % os.path.basename(last_version_dir)) return if v > 1: print "Extra files: %s" % ', '.join(files_copy.keys()) if v: print ("Current state does not match %s" % os.path.basename(last_version_dir)) if v > 1 and not last_version_dir: print "No last version to check" if not sim: os.mkdir(output_dir) if v: print 'Making directory %s' % self.shorten_filename(output_dir) files = files.items() files.sort() for fn, content in files: if v: print ' Writing %s' % self.shorten_filename(fn) if not sim: f = open(os.path.join(output_dir, fn), 'w') f.write(content) f.close() all_diffs = [] for cls in self.classes(): for conn in conns: diffs = db_differences(cls, conn) for diff in diffs: if len(conns) > 1: diff = ' (%s).%s: %s' % ( conn.uri(), cls.sqlmeta.table, diff) else: diff = ' %s: %s' % (cls.sqlmeta.table, diff) all_diffs.append(diff) if all_diffs: print 'Database does not match schema:' print '\n'.join(all_diffs) if self.options.db_record: print '(Not updating database version)' elif self.options.db_record: for conn in conns: self.update_db(version, conn) if self.options.open_editor: if not last_version_dir: print ("Cannot edit upgrader because there is no " "previous version") else: breaker = ('-'*20 + ' lines below this will be ignored ' + '-'*20) pre_text = breaker + '\n' + '\n'.join(all_diffs) text = self.open_editor('\n\n' + pre_text, breaker=breaker, extension='.sql') if text is not None: fn = os.path.join(last_version_dir, 'upgrade_%s_%s.sql' % (dbName, version)) f = open(fn, 'w') f.write(text) f.close() print 'Wrote to %s' % fn def update_db(self, version, conn): v = self.options.verbose if not conn.tableExists(SQLObjectVersionTable.sqlmeta.table): if v: print ('Creating table %s' % SQLObjectVersionTable.sqlmeta.table) sql = SQLObjectVersionTable.createTableSQL(connection=conn) if v > 1: print sql if not self.options.simulate: SQLObjectVersionTable.createTable(connection=conn) if not self.options.simulate: SQLObjectVersionTable.clearTable(connection=conn) SQLObjectVersionTable( version=version, connection=conn) def strip_comments(self, sql): lines = [l for l in sql.splitlines() if not l.strip().startswith('--')] return '\n'.join(lines) def base_dir(self): base = self.options.output_dir if base is None: base = CONFIG.get('sqlobject_history_dir', '.') if not os.path.exists(base): print 'Creating history directory %s' % self.shorten_filename(base) if not self.options.simulate: os.makedirs(base) return base def find_output_dir(self): today = time.strftime('%Y-%m-%d', time.localtime()) if self.options.version_name: dir = os.path.join(self.base_dir(), today + '-' + self.options.version_name) if os.path.exists(dir): print ("Error, directory already exists: %s" % dir) sys.exit(1) return dir extra = '' while 1: dir = os.path.join(self.base_dir(), today + extra) if not os.path.exists(dir): return dir if not extra: extra = 'a' else: extra = chr(ord(extra)+1) def find_last_version(self): names = [] for fn in os.listdir(self.base_dir()): if not self.version_regex.search(fn): continue names.append(fn) if not names: return None names.sort() return os.path.join(self.base_dir(), names[-1]) def command_force_db_version(self): v = self.options.verbose sim = self.options.simulate version = self.options.force_db_version if not self.version_regex.search(version): print "Versions must be in the format YYYY-MM-DD..." print "You version %s does not fit this" % version return version_dir = os.path.join(self.base_dir(), version) if not os.path.exists(version_dir): if v: print 'Creating %s' % self.shorten_filename(version_dir) if not sim: os.mkdir(version_dir) elif v: print ('Directory %s exists' % self.shorten_filename(version_dir)) if self.options.db_record: self.update_db(version, self.connection()) class CommandUpgrade(CommandRecord): name = 'upgrade' summary = 'Update the database to a new version (as created by record)' help = ('This command runs scripts (that you write by hand) to ' 'upgrade a database. The database\'s current version is in ' 'the sqlobject_version table (use record --force-db-version ' 'if a database does not have a sqlobject_version table), ' 'and upgrade scripts are in the version directory you are ' 'upgrading FROM, named upgrade_DBNAME_VERSION.sql, like ' '"upgrade_mysql_2004-12-01b.sql".') parser = standard_parser(find_modules=False) parser.add_option('--upgrade-to', help="Upgrade to the given version (default: newest version)", dest="upgrade_to", metavar="VERSION") parser.add_option('--output-dir', help="Base directory for recorded definitions", dest="output_dir", metavar="DIR", default=None) upgrade_regex = re.compile(r'^upgrade_([a-z]*)_([^.]*)\.sql$', re.I) def command(self): v = self.options.verbose sim = self.options.simulate if self.options.upgrade_to: version_to = self.options.upgrade_to else: version_to = os.path.basename(self.find_last_version()) current = self.current_version() if v: print 'Current version: %s' % current version_list = self.make_plan(current, version_to) if not version_list: print 'Database up to date' return if v: print 'Plan:' for next_version, upgrader in version_list: print ' Use %s to upgrade to %s' % ( self.shorten_filename(upgrader), next_version) conn = self.connection() for next_version, upgrader in version_list: f = open(upgrader) sql = f.read() f.close() if v: print "Running:" print sql print '-'*60 if not sim: try: conn.query(sql) except: print "Error in script: %s" % upgrader raise self.update_db(next_version, conn) print 'Done.' def current_version(self): conn = self.connection() if not conn.tableExists(SQLObjectVersionTable.sqlmeta.table): print 'No sqlobject_version table!' sys.exit(1) versions = list(SQLObjectVersionTable.select(connection=conn)) if not versions: print 'No rows in sqlobject_version!' sys.exit(1) if len(versions) > 1: print 'Ambiguous sqlobject_version_table' sys.exit(1) return versions[0].version def make_plan(self, current, dest): if current == dest: return [] dbname = self.connection().dbName next_version, upgrader = self.best_upgrade(current, dest, dbname) if not upgrader: print 'No way to upgrade from %s to %s' % (current, dest) print ('(you need a %s/upgrade_%s_%s.sql script)' % (current, dbname, dest)) sys.exit(1) plan = [(next_version, upgrader)] if next_version == dest: return plan else: return plan + self.make_plan(next_version, dest) def best_upgrade(self, current, dest, target_dbname): current_dir = os.path.join(self.base_dir(), current) if self.options.verbose > 1: print ('Looking in %s for upgraders' % self.shorten_filename(current_dir)) upgraders = [] for fn in os.listdir(current_dir): match = self.upgrade_regex.search(fn) if not match: if self.options.verbose > 1: print 'Not an upgrade script: %s' % fn continue dbname = match.group(1) version = match.group(2) if dbname != target_dbname: if self.options.verbose > 1: print 'Not for this database: %s (want %s)' % ( dbname, target_dbname) continue if version > dest: if self.options.verbose > 1: print 'Version too new: %s (only want %s)' % ( version, dest) upgraders.append((version, os.path.join(current_dir, fn))) if not upgraders: if self.options.verbose > 1: print 'No upgraders found in %s' % current_dir return None, None upgraders.sort() return upgraders[-1] def update_sys_path(paths, verbose): if isinstance(paths, (str, unicode)): paths = [paths] for path in paths: path = os.path.abspath(path) if path not in sys.path: if verbose > 1: print 'Adding %s to path' % path sys.path.insert(0, path) if __name__ == '__main__': the_runner.run(sys.argv) PKa95sqlobject/manager/__init__.py# PKb95 sqlobject/manager/command.pyc; Ec@sEdkZdkZdkZdkZdkZdkZdkZydklZdkl Z Wn!e j oZ e ZhZ nXdk Z dkZdklZdklZdklZeiddedd d Zd eifd YZd ZdefdYZeZeiZeeeedZ defdYZ!de!fdYZ"de!fdYZ#de!fdYZ$de!fdYZ%de!fdYZ&de!fdYZ'de!fd YZ(d!e!fd"YZ)d#e)fd$YZ*d%Z+e,d&joei-ei.ndS('N(spyconfig(sCONFIG(scol(s moduleloader(sDeclarativeMetasignores&tempnam is a potential security risk.*s .*commandicOsti||SdS(N(sosstempnamsargsskw(sargsskw((s7build/bdist.linux-i686/egg/sqlobject/manager/command.pysnowarning_tempnamssSQLObjectVersionTablecBsEtZdZdfdYZeiZeideiiZ RS(s This table is used to store information about the database and its version (used with record and update commands). ssqlmetacBstZdZRS(Nssqlobject_db_version(s__name__s __module__stable(((s7build/bdist.linux-i686/egg/sqlobject/manager/command.pyssqlmeta#ssdefault( s__name__s __module__s__doc__ssqlmetascols StringColsversions DateTimeColsnowsupdated(((s7build/bdist.linux-i686/egg/sqlobject/manager/command.pysSQLObjectVersionTables  cCsMg}|i|ii o"|iio|idqEny|i|ii|}Wnt j onXh}x*|D]"}|i |}|||i {ss.is.Could not import module "%s". Error was : "%s"s5Unknown exception while processing module "%s" : "%s"(sdir_names startswithsfilters filenamessfnamesosspathsjoins module_namesfinds package_namesreplacesseps moduleloaders load_modulesmodules ImportErrorserrsselfsoptionssverboses Exceptionsexcsclasses_from_modulesclassessallsextend( sargsdir_names filenamesserrsmodulesclassessfnames module_namesexc(s package_namesselfsall(s7build/bdist.linux-i686/egg/sqlobject/manager/command.pysfind_classes_in_filexs*    ( salls moduleloaders load_modules package_namespackagesosspathsdirnames__file__s package_dirsfind_classes_in_fileswalksNone(sselfs package_namesallspackagesfind_classes_in_files package_dir((sselfs package_namesalls7build/bdist.linux-i686/egg/sqlobject/manager/command.pysclasses_from_packagess cCsg}|i|dt\}}xw|iddidD]Z}|i }| oq=n|i i o d|GHn|i |iti|q=W|SdS(Nswarn_no_sqlobjects db_moduless,sLooking in module %s(smodulessselfsconfig_from_eggsegg_specsTruesdistsconfsgetssplitsmodsstripsoptionssverbosesextendsclasses_from_modules moduleloaders load_module(sselfsegg_specsdistsmodulessconfsmod((s7build/bdist.linux-i686/egg/sqlobject/manager/command.pysclasses_from_eggs   #cCsy|i|\}}t|ido|ii o |ido/|d}|i d|i }||i_ndS(Ns output_dirs history_dirs$base( sselfsconfig_from_eggsegg_specsdistsconfshasattrsoptionss output_dirsgetsdirsreplaceslocation(sselfsegg_specsdistsconfsdir((s7build/bdist.linux-i686/egg/sqlobject/manager/command.pysload_options_from_eggs 1 c Csdk}|i|}|id o|o d|GHnhSnh}x|idD]}|i }| p |i doq[n|i dd\}}|i i}||jo d|GHn|i ||i iRead SQL from stdin (normally takes SQL from the command line)sdests use_stdinsactions store_truecCs|i}|iio0|iio dGHn|itiin|i i |_ |i i |_ x|D]}|i|qtWdS(NsAReading additional SQL from stdin (Ctrl-D or Ctrl-Z to finish)...(sselfsargssoptionss use_stdinsverbosesappendssyssstdinsreads connections getConnectionsconnscursorssqls execute_sql(sselfsargsssql((s7build/bdist.linux-i686/egg/sqlobject/manager/command.pyscommands    cCs]|iio |GHny|ii|Wn>tj o2}|ii o |GHndGHdG|GHdSnX|ii} |ii }|iio*|ii o dGHqd|ii GHn| oNx7| D]/\}} } } }}}tiid|qWtiidnxC|D];} x"| D]}tiid|q&WtiidqWHdS(Ns ****Error:s sNo rows accesseds%i rows accesseds%s s s%r (sselfsoptionssverbosessqlscursorsexecutes Exceptionses descriptionsdescsfetchallsrowssrowcountsnames type_codes display_sizes internal_sizes precisionsscalesnull_okssyssstdoutswritesrowscol(sselfssqlsrowssesnamesnull_oks precisionscolsscales type_codesrows internal_sizes display_sizesdesc((s7build/bdist.linux-i686/egg/sqlobject/manager/command.pys execute_sqls8        ( s__name__s __module__snamessummaryshelpsstandard_parsersFalsesparsers add_optionsNonesmax_argsscommands execute_sql(((s7build/bdist.linux-i686/egg/sqlobject/manager/command.pysCommandExecutes   s CommandRecordc BsAtZdZdZdeiiZeZ e i dddddd d d e e i d dd ddddd e e i ddddddde i dddddd de i dddd ddde i ddddddde id Zd!Zd"Zd#Zd$Zd%Zd&Zd'ZRS((Nsrecords7Record historical information about the database statuss-Record state of table definitions. The state of each table is written out to a separate file in a directory, and that directory forms a "version". A table is also added to you datebase (%s) that reflects the version the database is currently at. Use the upgrade command to sync databases with code.s --output-dirshelps'Base directory for recorded definitionssdests output_dirsmetavarsDIRsdefaults--no-db-records Don't record version to databases db_recordsactions store_falses--force-createsHCreate a new version even if appears to be identical to the last versions store_trues force_creates--namesThe name to append to the version. The version should sort after previous versions (so any versions from the same day should come alphabetically before this version).s version_namesNAMEs--force-db-versionsUpdate the database version, and include no database information. This is for databases that were developed without any interaction with this tool, to create a 'beginning' revision.s VERSION_NAMEsforce_db_versions--editsDOpen an editor for the upgrader in the last version (using $EDITOR).s open_editors^\d\d\d\d-\d\d-\d\dcCs|iio|idSn|ii} |ii} |i}| o dGHdSn|i }t i i |}d|GHg} h} x|iD] } | ii}| i| jo| i| int i i| id|d}| oqn| i}t|to|}g}n |\}}|oddi|}nd}didtid d | i | ifd ||i!d|g| ||f}nd| i=i>|f}|i|q\Wq@Wq3W|o-dGHdi|GH|ii?o dGHq-n3|ii?o%x"| D]}|i@||qWn|iiAo| o dGHqddd dd}|ddi|}|iAd!|d"|d#d}|tEj oRt i i|d$||f}t*|d}|i5||i.d%|GHqndS(&NsNo classes found!sCreating version %ss_s.sqls -- Constraints: %s s ss-- Exported definition from %s s%Y-%m-%dT%H:%M:%Ss-- Class %s.%s s-- Database: %s is#Checking %s to see if it is currentsMissing file %ssrsContent does not match: %ss!Current status matches version %ssExtra files: %ss, sCurrent state does not match %ssNo last version to checksMaking directory %ss Writing %ssws (%s).%s: %ss %s: %ssDatabase does not match schema:s(Not updating database version)s9Cannot edit upgrader because there is no previous versions-is" lines below this will be ignored s sbreakers extensionsupgrade_%s_%s.sqls Wrote to %s(Fsselfsoptionssforce_db_versionscommand_force_db_versionsverbosesvssimulatessimsclassessfind_output_dirs output_dirsosspathsbasenamesversionsconnssfilessclss _connectionsdbNamesappendsjoins__name__sfnscreateTableSQLsresults isinstances basestringscreates constraintsstimesstrftimes __module__sstripsfind_last_versionslast_version_dirs force_createscopys files_copyslistdirsendswithshas_keysopensfsreadscontentsclosesstrip_commentsskeyssmkdirsshorten_filenamesitemsssortswrites all_diffssconnsdb_differencessdiffssdiffslensurissqlmetastables db_records update_dbs open_editorsbreakerspre_textstextsNone(sselfstextsresultsdiffslast_version_dirsconnscontentsversions output_dirsconnsssimsclssfilessvsfnsdiffsspre_texts files_copysfsdbNamesclassess all_diffssbreakerscreates constraints((s7build/bdist.linux-i686/egg/sqlobject/manager/command.pyscommand4s         !   P        #          #          cCs|ii}|itii oh|odtiiGHnti d|}|djo |GHn|ii oti d|qn|ii o'ti d|td|d|ndS(NsCreating table %ss connectionisversion(sselfsoptionssverbosesvsconns tableExistssSQLObjectVersionTablessqlmetastablescreateTableSQLssqlssimulates createTables clearTablesversion(sselfsversionsconnsvssql((s7build/bdist.linux-i686/egg/sqlobject/manager/command.pys update_dbs    cCsYgi}|iD]+}|iid o||qq~}di|SdS(Ns--s ( sappends_[1]ssqls splitlinesslsstrips startswithslinessjoin(sselfssqls_[1]slinessl((s7build/bdist.linux-i686/egg/sqlobject/manager/command.pysstrip_commentssHcCs|ii}|tjotidd}ntii | o5d|i |GH|ii oti |qxn|SdS(Nssqlobject_history_dirs.sCreating history directory %s( sselfsoptionss output_dirsbasesNonesCONFIGsgetsosspathsexistssshorten_filenamessimulatesmakedirs(sselfsbase((s7build/bdist.linux-i686/egg/sqlobject/manager/command.pysbase_dirs  cCstidti}|iio^tii |i |d|ii}tii |od|GHt idn|Snd}xonogtii |i ||}tii | o|Sn| o d}qtt|d}qWdS(Ns%Y-%m-%ds-s#Error, directory already exists: %sissa(stimesstrftimes localtimestodaysselfsoptionss version_namesosspathsjoinsbase_dirsdirsexistsssyssexitsextraschrsord(sselfsextrastodaysdir((s7build/bdist.linux-i686/egg/sqlobject/manager/command.pysfind_output_dirs  )  cCsg}xEti|iD].}|ii| oqn|i|qW| ot Sn|i ti i |i|dSdS(Ni( snamessosslistdirsselfsbase_dirsfns version_regexssearchsappendsNonessortspathsjoin(sselfsnamessfn((s7build/bdist.linux-i686/egg/sqlobject/manager/command.pysfind_last_versions cCs|ii}|ii}|ii}|ii | odGHd|GHdSnt i i |i |}t i i| o:|od|i|GHn| ot i|qn|od|i|GHn|iio|i||indS(Ns,Versions must be in the format YYYY-MM-DD...s You version %s does not fit thiss Creating %ssDirectory %s exists(sselfsoptionssverbosesvssimulatessimsforce_db_versionsversions version_regexssearchsosspathsjoinsbase_dirs version_dirsexistssshorten_filenamesmkdirs db_records update_dbs connection(sselfs version_dirsversionsvssim((s7build/bdist.linux-i686/egg/sqlobject/manager/command.pyscommand_force_db_versions"     (s__name__s __module__snamessummarysSQLObjectVersionTablessqlmetastableshelpsstandard_parsersparsers add_optionsNonesTruesrescompiles version_regexscommands update_dbsstrip_commentssbase_dirsfind_output_dirsfind_last_versionscommand_force_db_version(((s7build/bdist.linux-i686/egg/sqlobject/manager/command.pys CommandRecordsL                 sCommandUpgradec BstZdZdZdZedeZeiddddd d d eid dd ddd dde e i de i Z dZdZdZdZRS(Nsupgrades;Update the database to a new version (as created by record)ssThis command runs scripts (that you write by hand) to upgrade a database. The database's current version is in the sqlobject_version table (use record --force-db-version if a database does not have a sqlobject_version table), and upgrade scripts are in the version directory you are upgrading FROM, named upgrade_DBNAME_VERSION.sql, like "upgrade_mysql_2004-12-01b.sql".s find_moduless --upgrade-toshelps6Upgrade to the given version (default: newest version)sdests upgrade_tosmetavarsVERSIONs --output-dirs'Base directory for recorded definitionss output_dirsDIRsdefaults^upgrade_([a-z]*)_([^.]*)\.sql$c Cs|ii}|ii} |iio|ii}nti i |i }|i }|o d|GHn|i||} | o dGHdSn|o8dGHx0| D]$\}}d|i||fGHqWn|i}x| D]\}}t|}|i}|i|odGH|GHddGHn| o+y|i|Wqed|GHqeXn|i||qWd GHdS( NsCurrent version: %ssDatabase up to datesPlan:s Use %s to upgrade to %ssRunning:s-i<sError in script: %ssDone.(sselfsoptionssverbosesvssimulatessims upgrade_tos version_tososspathsbasenamesfind_last_versionscurrent_versionscurrents make_plans version_lists next_versionsupgradersshorten_filenames connectionsconnsopensfsreadssqlsclosesquerys update_db( sselfsfssqlscurrents version_tos next_versionsupgradersvsconns version_listssim((s7build/bdist.linux-i686/egg/sqlobject/manager/command.pyscommand'sF               cCs|i}|itii odGHtidnt ti d|}| odGHtidnt |djodGHtidn|di SdS(NsNo sqlobject_version table!is connectionsNo rows in sqlobject_version!s!Ambiguous sqlobject_version_tablei(sselfs connectionsconns tableExistssSQLObjectVersionTablessqlmetastablessyssexitslistsselectsversionsslensversion(sselfsversionssconn((s7build/bdist.linux-i686/egg/sqlobject/manager/command.pyscurrent_versionMs cCs||jogSn|ii}|i|||\}}| o2d||fGHd|||fGHt i dn||fg}||jo|Sn||i ||SdS(NsNo way to upgrade from %s to %ss((you need a %s/upgrade_%s_%s.sql script)i( scurrentsdestsselfs connectionsdbNamesdbnames best_upgrades next_versionsupgraderssyssexitsplans make_plan(sselfscurrentsdestsplansupgradersdbnames next_version((s7build/bdist.linux-i686/egg/sqlobject/manager/command.pys make_plan[s  c Cstii|i|}|iidjod|i |GHng}x ti |D]} |i i| }| o'|iidjo d| GHqZqZn|id}|id}||jo-|iidjod||fGHqZqZn||jo*|iidjod||fGHq0n|i|tii|| fqZW| o.|iidjo d|GHnttfSn|i|dSdS( NisLooking in %s for upgraderssNot an upgrade script: %sis#Not for this database: %s (want %s)s"Version too new: %s (only want %s)sNo upgraders found in %si(sosspathsjoinsselfsbase_dirscurrents current_dirsoptionssverbosesshorten_filenames upgradersslistdirsfns upgrade_regexssearchsmatchsgroupsdbnamesversions target_dbnamesdestsappendsNonessort( sselfscurrentsdests target_dbnames upgraderss current_dirsversionsmatchsdbnamesfn((s7build/bdist.linux-i686/egg/sqlobject/manager/command.pys best_upgradeks6   &  (s__name__s __module__snamessummaryshelpsstandard_parsersFalsesparsers add_optionsNonesrescompilesIs upgrade_regexscommandscurrent_versions make_plans best_upgrade(((s7build/bdist.linux-i686/egg/sqlobject/manager/command.pysCommandUpgrades$     &  cCst|ttfo |g}nxa|D]Y}tii|}|tijo1|djo d|GHntii d|q*q*WdS(NisAdding %s to pathi( s isinstancespathssstrsunicodespathsossabspathssyssverbosesinsert(spathssverbosespath((s7build/bdist.linux-i686/egg/sqlobject/manager/command.pysupdate_sys_paths   s__main__(/soptparsesfnmatchsresosssysstextwrapswarningsspastespyconfigsCONFIGs ImportErrorsesNonestimes sqlobjectscolssqlobject.utils moduleloaderssqlobject.declarativesDeclarativeMetasfilterwarningssRuntimeWarningsnowarning_tempnams SQLObjectsSQLObjectVersionTablesdb_differencessobjects CommandRunners the_runnersregistersTruesFalsesstandard_parsersCommands CommandSQLs CommandLists CommandCreates CommandDrops CommandStatuss CommandHelpsCommandExecutes CommandRecordsCommandUpgradesupdate_sys_paths__name__srunsargv(!snowarning_tempnamspyconfigs CommandListsdb_differencessSQLObjectVersionTables the_runners CommandRunnersstandard_parsersres moduleloaders CommandSQLswarningssoptparsesCommandExecutestextwraps CommandCreatesDeclarativeMetas CommandHelpsCommands CommandDrops sqlobjectssyssesossregistersupdate_sys_paths CommandStatuss CommandRecordstimesfnmatchsCONFIGscolsCommandUpgrade((s7build/bdist.linux-i686/egg/sqlobject/manager/command.pys?sR                  &$  7D7"H7 | PKb95`sqlobject/manager/__init__.pyc; Ec@sdS(N((((s8build/bdist.linux-i686/egg/sqlobject/manager/__init__.pys?sPKa95"=~~sqlobject/mssql/__init__.pyfrom sqlobject.dbconnection import registerConnection def builder(): import mssqlconnection return mssqlconnection.MSSQLConnection def isSupported(cls): try: import pymssql except ImportError: try: import adodbapi except ImportError: return False return True registerConnection(['mssql'], builder, isSupported) PKa95_%%"sqlobject/mssql/mssqlconnection.pyfrom sqlobject.dbconnection import DBAPI from sqlobject import col import re sqlmodule = None class MSSQLConnection(DBAPI): supportTransactions = True dbName = 'mssql' schemes = [dbName] def __init__(self, db, user, password='', host='localhost', autoCommit=0, **kw): global sqlmodule if not sqlmodule: try: import adodbapi as sqlmodule self.dbconnection = sqlmodule.connect # ADO uses unicode only (AFAIK) self.usingUnicodeStrings = True # Need to use SQLNCLI provider for SQL Server Express Edition if kw.get("ncli"): conn_str = "Provider=SQLNCLI;" else: conn_str = "Provider=SQLOLEDB;" conn_str += "Data Source=%s;Initial Catalog=%s;" # MSDE does not allow SQL server login if kw.get("sspi"): conn_str += "Integrated Security=SSPI;Persist Security Info=False" self.make_conn_str = lambda keys: [conn_str % (keys.host, keys.db)] else: conn_str += "User Id=%s;Password=%s" self.make_conn_str = lambda keys: [conn_str % (keys.host, keys.db, keys.user, keys.password)] col.popKey(kw, "sspi") col.popKey(kw, "ncli") except ImportError: # raise the exceptions other than ImportError for adodbapi absence import pymssql as sqlmodule self.dbconnection = sqlmodule.connect sqlmodule.Binary = lambda st: str(st) # don't know whether pymssql uses unicode self.usingUnicodeStrings = False self.make_conn_str = lambda keys: \ ["", keys.user, keys.password, keys.host, keys.db] self.autoCommit=int(autoCommit) self.host = host self.db = db self.user = user self.password = password self.limit_re = re.compile('^\s*(select )(.*)', re.IGNORECASE) self.password = password self.module = sqlmodule DBAPI.__init__(self, **kw) def connectionFromURI(cls, uri): user, password, host, port, path, args = cls._parseURI(uri) path = path.strip('/') return cls(user=user, password=password, host=host or 'localhost', db=path, **args) connectionFromURI = classmethod(connectionFromURI) def insert_id(self, conn): """ insert_id method. """ c = conn.cursor() # converting the identity to an int is ugly, but it gets returned # as a decimal otherwise :S c.execute('SELECT CONVERT(INT, @@IDENTITY)') return c.fetchone()[0] def makeConnection(self): con = self.dbconnection( *self.make_conn_str(self) ) cur = con.cursor() cur.execute('SET ANSI_NULLS ON') cur.close() return con HAS_IDENTITY = """ SELECT col.name, col.status, obj.name FROM syscolumns col JOIN sysobjects obj ON obj.id = col.id WHERE obj.name = '%s' and col.autoval is not null """ def _hasIdentity(self, conn, table): query = self.HAS_IDENTITY % table c = conn.cursor() c.execute(query) r = c.fetchone() return r is not None def _queryInsertID(self, conn, soInstance, id, names, values): """ Insert the Initial with names and values, using id. """ table = soInstance.sqlmeta.table idName = soInstance.sqlmeta.idName c = conn.cursor() has_identity = self._hasIdentity(conn, table) if id is not None: names = [idName] + names values = [id] + values elif has_identity and idName in names: try: i = names.index( idName ) if i: del names[i] del values[i] except ValueError: pass if has_identity: if id is not None: c.execute('SET IDENTITY_INSERT %s ON' % table) else: c.execute('SET IDENTITY_INSERT %s OFF' % table) q = self._insertSQL(table, names, values) if self.debug: print 'QueryIns: %s' % q c.execute(q) if has_identity: c.execute('SET IDENTITY_INSERT %s OFF' % table) if id is None: id = self.insert_id(conn) if self.debugOutput: self.printDebug(conn, id, 'QueryIns', 'result') return id def _queryAddLimitOffset(self, query, start, end): if end and not start: limit_str = "SELECT TOP %i" % end match = self.limit_re.match(query) if match and len(match.groups()) == 2: return ' '.join([limit_str, match.group(2)]) else: return query def createColumn(self, soClass, col): return col.mssqlCreateSQL() def createIDColumn(self, soClass): key_type = {int: "INT", str: "TEXT"}[soClass.sqlmeta.idType] return '%s %s IDENTITY UNIQUE' % (soClass.sqlmeta.idName, key_type) def createIndexSQL(self, soClass, index): return index.mssqlCreateIndexSQL(soClass) def joinSQLType(self, join): return 'INT NOT NULL' SHOW_TABLES="SELECT name FROM sysobjects WHERE type='U'" def tableExists(self, tableName): for (table,) in self.queryAll(self.SHOW_TABLES): if table.lower() == tableName.lower(): return True return False def addColumn(self, tableName, column): self.query('ALTER TABLE %s ADD %s' % (tableName, column.mssqlCreateSQL())) def delColumn(self, tableName, column): self.query('ALTER TABLE %s DROP COLUMN %s' % (tableName, column.dbName)) # precision and scale is gotten from column table so that we can create # decimal columns if needed SHOW_COLUMNS = """ select name, length, ( select name from systypes where cast(xusertype as int)= cast(sc.xtype as int) ) datatype, prec, scale, isnullable, cdefault, m.text default_text, isnull(len(autoval),0) is_identity from syscolumns sc LEFT OUTER JOIN syscomments m on sc.cdefault = m.id AND m.colid = 1 where sc.id in (select id from sysobjects where name = '%s') order by colorder""" def columnsFromSchema(self, tableName, soClass): colData = self.queryAll(self.SHOW_COLUMNS % tableName) results = [] for field, size, t, precision, scale, nullAllowed, default, defaultText, is_identity in colData: # Seems strange to skip the pk column? What if it's not 'id'? if field == 'id': continue # precision is needed for decimal columns colClass, kw = self.guessClass(t, size, precision, scale) kw['name'] = soClass.sqlmeta.style.dbColumnToPythonAttr(field) kw['notNone'] = not nullAllowed if (defaultText): # Strip ( and ) defaultText = defaultText[1:-1] if defaultText[0] == "'": defaultText = defaultText[1:-1] else: if t == "int" : defaultText = int(defaultText) if t == "float" : defaultText = float(defaultText) if t == "numeric": defaultText = float(defaultText) # TODO need to access the "column" to_python method here--but the object doesn't exists yet # @@ skip key... kw['default'] = defaultText results.append(colClass(**kw)) return results def _setAutoCommit(self, conn, auto): #raise Exception(repr(auto)) return #conn.auto_commit = auto option = "ON" if auto == 0: option = "OFF" c = conn.cursor() c.execute("SET AUTOCOMMIT " + option) conn.setconnectoption(SQL.AUTOCOMMIT, option) # precision and scale is needed for decimal columns def guessClass(self, t, size, precision, scale): """ Here we take raw values coming out of syscolumns and map to SQLObject class types. """ if t.startswith('int'): return col.IntCol, {} elif t.startswith('varchar'): if self.usingUnicodeStrings: return col.UnicodeCol, {'length': size} return col.StringCol, {'length': size} elif t.startswith('char'): if self.usingUnicodeStrings: return col.UnicodeCol, {'length': size, 'varchar': False} return col.StringCol, {'length': size, 'varchar': False} elif t.startswith('datetime'): return col.DateTimeCol, {} elif t.startswith('decimal'): return col.DecimalCol, {'size': precision, # be careful for awkward naming 'precision': scale} else: return col.Col, {} PKb95W||sqlobject/mssql/__init__.pyc; Ec@s6dklZdZdZedgeedS((sregisterConnectioncCsdk}|iSdS(N(smssqlconnectionsMSSQLConnection(smssqlconnection((s6build/bdist.linux-i686/egg/sqlobject/mssql/__init__.pysbuilders cCsRy dk}Wn:tj o.y dk}WqJtj o tSqJXnXtSdS(N(spymssqls ImportErrorsadodbapisFalsesTrue(sclssadodbapispymssql((s6build/bdist.linux-i686/egg/sqlobject/mssql/__init__.pys isSupporteds  smssqlN(ssqlobject.dbconnectionsregisterConnectionsbuilders isSupported(s isSupportedsbuildersregisterConnection((s6build/bdist.linux-i686/egg/sqlobject/mssql/__init__.pys?s   PKb95..#sqlobject/mssql/mssqlconnection.pyc; Ec@sCdklZdklZdkZeadefdYZdS((sDBAPI(scolNsMSSQLConnectioncBstZeZdZegZddddZdZeeZdZ dZ d Z d Z d Z d Zd ZdZdZdZdZdZdZdZdZdZdZdZRS(Nsmssqlss localhostic s{t oydkati|_t|_|ido dndd7|idod7d|_ nd7d |_ t i |dt i |dWq t j o=dkati|_d t_t|_d |_ q Xnt||_||_||_||_||_tid ti|_||_t|_ti||dS( NsnclisProvider=SQLNCLI;sProvider=SQLOLEDB;s"Data Source=%s;Initial Catalog=%s;ssspis4Integrated Security=SSPI;Persist Security Info=Falsecs|i|ifgS(N(sconn_strskeysshostsdb(skeys(sconn_str(s=build/bdist.linux-i686/egg/sqlobject/mssql/mssqlconnection.pys"ssUser Id=%s;Password=%scs#|i|i|i|ifgS(N(sconn_strskeysshostsdbsuserspassword(skeys(sconn_str(s=build/bdist.linux-i686/egg/sqlobject/mssql/mssqlconnection.pys%scCs t|S(N(sstrsst(sst((s=build/bdist.linux-i686/egg/sqlobject/mssql/mssqlconnection.pys-scCsd|i|i|i|igS(Ns(skeyssuserspasswordshostsdb(skeys((s=build/bdist.linux-i686/egg/sqlobject/mssql/mssqlconnection.pys0ss^\s*(select )(.*)(s sqlmodulesadodbapisconnectsselfs dbconnectionsTruesusingUnicodeStringsskwsgetsconn_strs make_conn_strscolspopKeys ImportErrorspymssqlsBinarysFalsesints autoCommitshostsdbsuserspasswordsrescompiles IGNORECASEslimit_resmodulesDBAPIs__init__(sselfsdbsuserspasswordshosts autoCommitskwsconn_str((sconn_strs=build/bdist.linux-i686/egg/sqlobject/mssql/mssqlconnection.pys__init__ s@                 c Cs]|i|\}}}}}}|i d}|d|d|d|pdd||SdS(Ns/suserspasswordshosts localhostsdb( sclss _parseURIsurisuserspasswordshostsportspathsargssstrip(sclssurisargsshostsuserspathspasswordsport((s=build/bdist.linux-i686/egg/sqlobject/mssql/mssqlconnection.pysconnectionFromURI<s!cCs+|i}|id|idSdS(s# insert_id method. sSELECT CONVERT(INT, @@IDENTITY)iN(sconnscursorscsexecutesfetchone(sselfsconnsc((s=build/bdist.linux-i686/egg/sqlobject/mssql/mssqlconnection.pys insert_idCs  cCsC|i|i|}|i}|id|i|SdS(NsSET ANSI_NULLS ON(sselfs dbconnections make_conn_strsconscursorscursexecutesclose(sselfscurscon((s=build/bdist.linux-i686/egg/sqlobject/mssql/mssqlconnection.pysmakeConnectionMs    s SELECT col.name, col.status, obj.name FROM syscolumns col JOIN sysobjects obj ON obj.id = col.id WHERE obj.name = '%s' and col.autoval is not null cCs@|i|}|i}|i||i}|t j SdS(N( sselfs HAS_IDENTITYstablesquerysconnscursorscsexecutesfetchonesrsNone(sselfsconnstablescsrsquery((s=build/bdist.linux-i686/egg/sqlobject/mssql/mssqlconnection.pys _hasIdentity]s     c Cs|ii} |ii}|i}|i|| } |t j o|g|}|g|}n[| o ||joFy,|i|}|o||=||=nWqtj oqXn| o7|t j o|id| q|id| n|i| ||} |io d| GHn|i| | o|id| n|t jo|i|}n|io|i||ddn|SdS(sI Insert the Initial with names and values, using id. sSET IDENTITY_INSERT %s ONsSET IDENTITY_INSERT %s OFFs QueryIns: %ssQueryInssresultN(s soInstancessqlmetastablesidNamesconnscursorscsselfs _hasIdentitys has_identitysidsNonesnamessvaluessindexsis ValueErrorsexecutes _insertSQLsqsdebugs insert_ids debugOutputs printDebug( sselfsconns soInstancesidsnamessvaluesscsisidNamesqstables has_identity((s=build/bdist.linux-i686/egg/sqlobject/mssql/mssqlconnection.pys_queryInsertIDds>            cCsw|o| o`d|}|ii|}|ot|idjo di ||i dgSqsn|SdS(Ns SELECT TOP %iis ( sendsstarts limit_strsselfslimit_resmatchsqueryslensgroupssjoinsgroup(sselfsquerysstartsends limit_strsmatch((s=build/bdist.linux-i686/egg/sqlobject/mssql/mssqlconnection.pys_queryAddLimitOffsets   $cCs|iSdS(N(scolsmssqlCreateSQL(sselfssoClassscol((s=build/bdist.linux-i686/egg/sqlobject/mssql/mssqlconnection.pys createColumnscCs:htd<td<|ii}d|ii|fSdS(NsINTsTEXTs%s %s IDENTITY UNIQUE(sintsstrssoClassssqlmetasidTypeskey_typesidName(sselfssoClassskey_type((s=build/bdist.linux-i686/egg/sqlobject/mssql/mssqlconnection.pyscreateIDColumns"cCs|i|SdS(N(sindexsmssqlCreateIndexSQLssoClass(sselfssoClasssindex((s=build/bdist.linux-i686/egg/sqlobject/mssql/mssqlconnection.pyscreateIndexSQLscCsdSdS(Ns INT NOT NULL((sselfsjoin((s=build/bdist.linux-i686/egg/sqlobject/mssql/mssqlconnection.pys joinSQLTypess*SELECT name FROM sysobjects WHERE type='U'cCsIx>|i|iD]*\}|i|ijotSqqWtSdS(N(sselfsqueryAlls SHOW_TABLESstableslowers tableNamesTruesFalse(sselfs tableNamestable((s=build/bdist.linux-i686/egg/sqlobject/mssql/mssqlconnection.pys tableExistss   cCs!|id||ifdS(NsALTER TABLE %s ADD %s(sselfsquerys tableNamescolumnsmssqlCreateSQL(sselfs tableNamescolumn((s=build/bdist.linux-i686/egg/sqlobject/mssql/mssqlconnection.pys addColumnscCs|id||ifdS(NsALTER TABLE %s DROP COLUMN %s(sselfsquerys tableNamescolumnsdbName(sselfs tableNamescolumn((s=build/bdist.linux-i686/egg/sqlobject/mssql/mssqlconnection.pys delColumnss select name, length, ( select name from systypes where cast(xusertype as int)= cast(sc.xtype as int) ) datatype, prec, scale, isnullable, cdefault, m.text default_text, isnull(len(autoval),0) is_identity from syscolumns sc LEFT OUTER JOIN syscomments m on sc.cdefault = m.id AND m.colid = 1 where sc.id in (select id from sysobjects where name = '%s') order by colorderc CsT|i|i|}g}x-|D]%\ } }} }}} }}}| djoq#n|i| |||\} } |iii| | d<| | d<|o|dd!}|ddjo|dd!}q+| djot|}n| d jot|}n| d jot|}q+n|| d <|i| | q#W|SdS( NsidsnamesnotNoneiiis'sintsfloatsnumericsdefault(sselfsqueryAlls SHOW_COLUMNSs tableNamescolDatasresultssfieldssizests precisionsscales nullAllowedsdefaults defaultTexts is_identitys guessClassscolClassskwssoClassssqlmetasstylesdbColumnToPythonAttrsintsfloatsappend(sselfs tableNamessoClasssscalesdefaultscolDatas is_identitysresultss precisionsfields nullAllowedskwstscolClasss defaultTextssize((s=build/bdist.linux-i686/egg/sqlobject/mssql/mssqlconnection.pyscolumnsFromSchemas,!       cCsUdSd}|djo d}n|i}|id||iti|dS(NsONisOFFsSET AUTOCOMMIT ( soptionsautosconnscursorscsexecutessetconnectoptionsSQLs AUTOCOMMIT(sselfsconnsautoscsoption((s=build/bdist.linux-i686/egg/sqlobject/mssql/mssqlconnection.pys_setAutoCommits   cCs4|idotihfSn|ido>|iotihd|`_ installable with ``easy_install SQLObject==dev`` The 0.7 bugfix branch is `also available `_ installable with ``easy_install SQLObject==bugfix``. Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL) Classifier: Programming Language :: Python Classifier: Topic :: Database Classifier: Topic :: Database :: Front-Ends Classifier: Topic :: Software Development :: Libraries :: Python Modules PKb95ֳkddEGG-INFO/SOURCES.txtMANIFEST.in README.txt release setup.cfg setup.py SQLObject.egg-info/PKG-INFO SQLObject.egg-info/SOURCES.txt SQLObject.egg-info/dependency_links.txt SQLObject.egg-info/requires.txt SQLObject.egg-info/top_level.txt debian/changelog debian/control debian/copyright debian/docs debian/examples debian/rules docs/Authors.txt docs/DeveloperGuide.txt docs/FAQ.txt docs/Inheritance.txt docs/News.txt docs/SQLBuilder.txt docs/SQLObject.txt docs/TODO.txt docs/community.txt docs/default.css docs/download.txt docs/index.txt docs/interface.py docs/links.txt docs/rebuild docs/sqlobject-admin.txt docs/test.py docs/europython/europython_sqlobj.py docs/europython/main.css docs/europython/person.py docs/presentation-2004-11/sqlobject-and-database-programming.html docs/presentation-2004-11/ui/bodybg.gif docs/presentation-2004-11/ui/custom.css docs/presentation-2004-11/ui/framing.css docs/presentation-2004-11/ui/opera.css docs/presentation-2004-11/ui/pretty.css docs/presentation-2004-11/ui/print.css docs/presentation-2004-11/ui/s5-core.css docs/presentation-2004-11/ui/slides.css docs/presentation-2004-11/ui/slides.js ez_setup/README.txt ez_setup/__init__.py scripts/sqlobject-admin sqlobject/__init__.py sqlobject/boundattributes.py sqlobject/cache.py sqlobject/classregistry.py sqlobject/col.py sqlobject/conftest.py sqlobject/constraints.py sqlobject/converters.py sqlobject/dbconnection.py sqlobject/declarative.py sqlobject/index.py sqlobject/joins.py sqlobject/main.py sqlobject/sqlbuilder.py sqlobject/sresults.py sqlobject/styles.py sqlobject/firebird/__init__.py sqlobject/firebird/firebirdconnection.py sqlobject/inheritance/__init__.py sqlobject/inheritance/iteration.py sqlobject/inheritance/tests/__init__.py sqlobject/inheritance/tests/testDestroyCascade.py sqlobject/inheritance/tests/test_deep_inheritance.py sqlobject/inheritance/tests/test_inheritance.py sqlobject/inheritance/tests/test_inherited_foreignKey.py sqlobject/manager/__init__.py sqlobject/manager/command.py sqlobject/maxdb/__init__.py sqlobject/maxdb/maxdbconnection.py sqlobject/maxdb/readme.txt sqlobject/mssql/__init__.py sqlobject/mssql/mssqlconnection.py sqlobject/mysql/__init__.py sqlobject/mysql/mysqlconnection.py sqlobject/postgres/__init__.py sqlobject/postgres/pgconnection.py sqlobject/sqlite/__init__.py sqlobject/sqlite/sqliteconnection.py sqlobject/sybase/__init__.py sqlobject/sybase/sybaseconnection.py sqlobject/tests/__init__.py sqlobject/tests/dbtest.py sqlobject/tests/test_NoneValuedResultItem.py sqlobject/tests/test_SQLMultipleJoin.py sqlobject/tests/test_SQLRelatedJoin.py sqlobject/tests/test_SingleJoin.py sqlobject/tests/test_aliases.py sqlobject/tests/test_auto.py sqlobject/tests/test_auto_old.py sqlobject/tests/test_basic.py sqlobject/tests/test_basic_old.py sqlobject/tests/test_blob.py sqlobject/tests/test_boundattributes.py sqlobject/tests/test_cache.py sqlobject/tests/test_constraints.py sqlobject/tests/test_converters.py sqlobject/tests/test_create_drop.py sqlobject/tests/test_datetime.py sqlobject/tests/test_decimal.py sqlobject/tests/test_declarative.py sqlobject/tests/test_delete.py sqlobject/tests/test_distinct.py sqlobject/tests/test_empty.py sqlobject/tests/test_enum.py sqlobject/tests/test_expire.py sqlobject/tests/test_foreignKey.py sqlobject/tests/test_indexes.py sqlobject/tests/test_inheritance.py sqlobject/tests/test_joins.py sqlobject/tests/test_joins_conditional.py sqlobject/tests/test_joins_old.py sqlobject/tests/test_lazy.py sqlobject/tests/test_minmax.py sqlobject/tests/test_parse.py sqlobject/tests/test_picklecol.py sqlobject/tests/test_reparent_sqlmeta.py sqlobject/tests/test_select.py sqlobject/tests/test_setters.py sqlobject/tests/test_slice.py sqlobject/tests/test_sorting.py sqlobject/tests/test_sorting_old.py sqlobject/tests/test_sqlite_threaded.py sqlobject/tests/test_stringid.py sqlobject/tests/test_stringid_old.py sqlobject/tests/test_style.py sqlobject/tests/test_style_old.py sqlobject/tests/test_subqueries.py sqlobject/tests/test_transactions.py sqlobject/tests/test_unicode.py sqlobject/tests/test_validation.py sqlobject/util/__init__.py sqlobject/util/backports.py sqlobject/util/moduleloader.py sqlobject/util/threadinglocal.py PKb952EGG-INFO/dependency_links.txt PKb95Zt3EGG-INFO/requires.txtFormEncode>=0.2.2 [sqlite] pysqlite [sapdb] sapdb [postgresql] psycopg [firebird] kinterbasdb [sybase] Sybase [mysql] MySQLdb [mssql] adodbapiPKb95ǘ EGG-INFO/top_level.txtsqlobject PKb952EGG-INFO/not-zip-safe PKb95 EGG-INFO/scripts/sqlobject-admin#!/usr/bin/python2.3 import sys import os try: import pkg_resources pkg_resources.require('SQLObject>0.6.1') except (ImportError, pkg_resources.DistributionNotFound): # Oh well, we tried... pass try: import sqlobject.manager except ImportError: try: here = __file__ except NameError: here = sys.argv[0] updir = os.path.join( os.path.dirname(os.path.dirname(os.path.abspath(here))), 'sqlobject') if os.path.exists(updir): sys.path.insert(0, os.path.dirname(updir)) else: print 'I cannot find the sqlobject module' print 'If SQLObject is installed, you may need to set $PYTHONPATH' sys.exit(3) # Now we have to get rid of possibly stale modules from that import # up there for name, value in sys.modules.items(): if name.startswith('sqlobject'): del sys.modules[name] from sqlobject.manager import command command.the_runner.run(sys.argv) PKa95 khhsqlobject/boundattributes.pyPKa95~~~sqlobject/converters.pyPKa95"199U(sqlobject/classregistry.pyPKa95Q6;sqlobject/__init__.pyPKa95K%%Dsqlobject/cache.pyPKa95Rjsqlobject/dbconnection.pyPKa95[ gςςsqlobject/sqlbuilder.pyPKa95ecssqlobject/index.pyPKa951||sqlobject/constraints.pyPKa95misqlobject/col.pyPKa95o·6sqlobject/styles.pyPKa95N}c}**Hsqlobject/joins.pyPKa95TX[nnssqlobject/declarative.pyPKa953CI9%sqlobject/main.pyPKa95i9"9"sqlobject/sresults.pyPKa95ȿ5:~sqlobject/conftest.pyPKb95Hllsqlobject/boundattributes.pycPKb95^T'%'%6sqlobject/converters.pycPKb95K,sqlobject/classregistry.pycPKb95ֽ6sqlobject/__init__.pycPKb95/9u0u0sqlobject/cache.pycPKb95x~Esqlobject/dbconnection.pycPKb95h#wIIgsqlobject/sqlbuilder.pycPKb95;sqlobject/index.pycPKb95 sqlobject/constraints.pycPKb95 @  .sqlobject/col.pycPKb95(e&&9sqlobject/styles.pycPKb95^AA`sqlobject/joins.pycPKb95/))sqlobject/declarative.pycPKb95&Lsqlobject/main.pycPKb953))fsqlobject/sresults.pycPKb95O#I I ssqlobject/conftest.pycPKa95q!XOOsqlobject/firebird/__init__.pyPKa95}yiuu({sqlobject/firebird/firebirdconnection.pyPKb95O__6sqlobject/firebird/__init__.pycPKb95**)sqlobject/firebird/firebirdconnection.pycPKa95  "!( sqlobject/inheritance/iteration.pyPKa95++!|4 sqlobject/inheritance/__init__.pyPKb95#` sqlobject/inheritance/iteration.pycPKb95 "#]~*~*"o sqlobject/inheritance/__init__.pycPKa95<:EEy sqlobject/mysql/__init__.pyPKa95#I" sqlobject/mysql/mysqlconnection.pyPKb95 M11Ѻ sqlobject/mysql/__init__.pycPKb95'+fR&R&#< sqlobject/mysql/mysqlconnection.pycPKa95ŋ11" sqlobject/postgres/pgconnection.pyPKa95~e sqlobject/postgres/__init__.pyPKb95 99# sqlobject/postgres/pgconnection.pycPKb95UའxR sqlobject/postgres/__init__.pycPKa951v55UV sqlobject/sqlite/__init__.pyPKa95y$W sqlobject/sqlite/sqliteconnection.pyPKb95{x66w sqlobject/sqlite/__init__.pycPKb951]A((%z sqlobject/sqlite/sqliteconnection.pycPKa95u88 sqlobject/sybase/__init__.pyPKa95\"s$W sqlobject/sybase/sybaseconnection.pyPKb95@6 >>S sqlobject/sybase/__init__.pycPKb956I"I"%̾ sqlobject/sybase/sybaseconnection.pycPKa95(̰2*2*"X sqlobject/maxdb/maxdbconnection.pyPKa95177 sqlobject/maxdb/__init__.pyPKb95x8Pm:m:#: sqlobject/maxdb/maxdbconnection.pycPKb95=::G sqlobject/maxdb/__init__.pycPKa95Vvv\K sqlobject/util/moduleloader.pyPKa95LS,@Q sqlobject/util/backports.pyPKa95R sqlobject/util/__init__.pyPKa95 S sqlobject/util/threadinglocal.pyPKb95ooW sqlobject/util/moduleloader.pycPKb9502_ sqlobject/util/backports.pycPKb95A݅c sqlobject/util/__init__.pycPKb95A]66!Bd sqlobject/util/threadinglocal.pycPKa95il sqlobject/manager/command.pyPKa95 sqlobject/manager/__init__.pyPKb95  sqlobject/manager/command.pycPKb95`% sqlobject/manager/__init__.pycPKa95"=~~ sqlobject/mssql/__init__.pyPKa95_%%" sqlobject/mssql/mssqlconnection.pyPKb95W||k sqlobject/mssql/__init__.pycPKb95..#! sqlobject/mssql/mssqlconnection.pycPKb95~&4 EGG-INFO/PKG-INFOPKb95ֳkddt: EGG-INFO/SOURCES.txtPKb952 K EGG-INFO/dependency_links.txtPKb95Zt3FK EGG-INFO/requires.txtPKb95ǘ L EGG-INFO/top_level.txtPKb952LL EGG-INFO/not-zip-safePKb95 L EGG-INFO/scripts/sqlobject-adminPKSSP