--- sqlobject/col.py.orig	2014-05-04 12:48:24 UTC
+++ sqlobject/col.py
@@ -22,17 +22,17 @@ from array import array
 from itertools import count
 import re, time
 try:
-    import cPickle as pickle
+    import pickle as pickle
 except ImportError:
     import pickle
 import weakref
 from formencode import compound, validators
-from classregistry import findClass
+from .classregistry import findClass
 # Sadly the name "constraints" conflicts with many of the function
 # arguments in this module, so we rename it:
-import constraints as constrs
-import sqlbuilder
-from styles import capword
+from . import constraints as constrs
+from . import sqlbuilder
+from .styles import capword
 
 NoDefault = sqlbuilder.NoDefault
 
@@ -218,7 +218,7 @@ class SOCol(object):
         self.dbEncoding = dbEncoding
 
         if extra_vars:
-            for name, value in extra_vars.items():
+            for name, value in list(extra_vars.items()):
                 setattr(self, name, value)
 
     def _set_validator(self, value):
@@ -286,7 +286,7 @@ class SOCol(object):
 
     def _sqlType(self):
         if self.customSQLType is None:
-            raise ValueError, ("Col %s (%s) cannot be used for automatic "
+            raise ValueError("Col %s (%s) cannot be used for automatic "
                                "schema creation (too abstract)" %
                                (self.name, self.__class__))
         else:
@@ -399,7 +399,7 @@ class Col(object):
         super(Col, self).__init__()
         self.__dict__['_name'] = name
         self.__dict__['_kw'] = kw
-        self.__dict__['creationOrder'] = creationOrder.next()
+        self.__dict__['creationOrder'] = next(creationOrder)
         self.__dict__['_extra_vars'] = {}
 
     def _set_name(self, value):
@@ -473,7 +473,7 @@ class SOStringLikeCol(SOCol):
 
     def _check_case_sensitive(self, db):
         if self.char_binary:
-            raise ValueError, "%s does not support binary character columns" % db
+            raise ValueError("%s does not support binary character columns" % db)
 
     def _mysqlType(self):
         type = self._sqlType()
@@ -538,14 +538,14 @@ class StringValidator(SOValidator):
         except AttributeError:
             binaryType = type(None) # Just a simple workaround
         dbEncoding = self.getDbEncoding(state, default='ascii')
-        if isinstance(value, unicode):
+        if isinstance(value, str):
             return value.encode(dbEncoding)
         if self.dataType and isinstance(value, self.dataType):
             return value
         if isinstance(value, (str, buffer, binaryType, sqlbuilder.SQLExpression)):
             return value
         if hasattr(value, '__unicode__'):
-            return unicode(value).encode(dbEncoding)
+            return str(value).encode(dbEncoding)
         raise validators.Invalid("expected a str in the StringCol '%s', got %s %r instead" % \
             (self.name, type(value), value), value, state)
 
@@ -563,7 +563,7 @@ class StringCol(Col):
 
 class NQuoted(sqlbuilder.SQLExpression):
     def __init__(self, value):
-        assert isinstance(value, unicode)
+        assert isinstance(value, str)
         self.value = value
     def __hash__(self):
         return hash(self.value)
@@ -576,14 +576,14 @@ class UnicodeStringValidator(SOValidator):
     def to_python(self, value, state):
         if value is None:
             return None
-        if isinstance(value, (unicode, sqlbuilder.SQLExpression)):
+        if isinstance(value, (str, sqlbuilder.SQLExpression)):
             return value
         if isinstance(value, str):
-            return unicode(value, self.getDbEncoding(state))
+            return str(value, self.getDbEncoding(state))
         if isinstance(value, array): # MySQL
-            return unicode(value.tostring(), self.getDbEncoding(state))
+            return str(value.tostring(), self.getDbEncoding(state))
         if hasattr(value, '__unicode__'):
-            return unicode(value)
+            return str(value)
         raise validators.Invalid("expected a str or a unicode in the UnicodeCol '%s', got %s %r instead" % \
             (self.name, type(value), value), value, state)
 
@@ -592,7 +592,7 @@ class UnicodeStringValidator(SOValidator):
             return None
         if isinstance(value, (str, sqlbuilder.SQLExpression)):
             return value
-        if isinstance(value, unicode):
+        if isinstance(value, str):
             try:
                 connection = state.connection or state.soObject._connection
             except AttributeError:
@@ -602,7 +602,7 @@ class UnicodeStringValidator(SOValidator):
                     return NQuoted(value)
             return value.encode(self.getDbEncoding(state))
         if hasattr(value, '__unicode__'):
-            return unicode(value).encode(self.getDbEncoding(state))
+            return str(value).encode(self.getDbEncoding(state))
         raise validators.Invalid("expected a str or a unicode in the UnicodeCol '%s', got %s %r instead" % \
             (self.name, type(value), value), value, state)
 
@@ -625,9 +625,9 @@ class IntValidator(SOValidator):
     def to_python(self, value, state):
         if value is None:
             return None
-        if isinstance(value, (int, long, sqlbuilder.SQLExpression)):
+        if isinstance(value, (int, sqlbuilder.SQLExpression)):
             return value
-        for converter, attr_name in (int, '__int__'), (long, '__long__'):
+        for converter, attr_name in (int, '__int__'), (int, '__long__'):
             if hasattr(value, attr_name):
                 try:
                     return converter(value)
@@ -708,7 +708,7 @@ class BoolValidator(SOValidator):
             return None
         if isinstance(value, (bool, sqlbuilder.SQLExpression)):
             return value
-        if isinstance(value, (int, long)) or hasattr(value, '__nonzero__'):
+        if isinstance(value, int) or hasattr(value, '__nonzero__'):
             return bool(value)
         raise validators.Invalid("expected a bool or an int in the BoolCol '%s', got %s %r instead" % \
             (self.name, type(value), value), value, state)
@@ -753,9 +753,9 @@ class FloatValidator(SOValidator):
     def to_python(self, value, state):
         if value is None:
             return None
-        if isinstance(value, (float, int, long, sqlbuilder.SQLExpression)):
+        if isinstance(value, (float, int, sqlbuilder.SQLExpression)):
             return value
-        for converter, attr_name in  (float, '__float__'), (int, '__int__'), (long, '__long__'):
+        for converter, attr_name in  (float, '__float__'), (int, '__int__'), (int, '__long__'):
             if hasattr(value, attr_name):
                 try:
                     return converter(value)
@@ -964,7 +964,7 @@ class EnumValidator(SOValidator):
 
     def to_python(self, value, state):
         if value in self.enumValues:
-            if isinstance(value, unicode):
+            if isinstance(value, str):
                 dbEncoding = self.getDbEncoding(state)
                 value = value.encode(dbEncoding)
             return value
@@ -1000,7 +1000,7 @@ class SOEnumCol(SOCol):
             return "ENUM(%s) NOT NULL" % ', '.join([sqlbuilder.sqlrepr(v, 'mysql') for v in self.enumValues])
 
     def _postgresType(self):
-        length = max(map(self._getlength, self.enumValues))
+        length = max(list(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)
@@ -1014,7 +1014,7 @@ class SOEnumCol(SOCol):
         return self._postgresType()
 
     def _firebirdType(self):
-        length = max(map(self._getlength, self.enumValues))
+        length = max(list(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
@@ -1048,7 +1048,7 @@ class SetValidator(SOValidator):
             (self.name, type(value), value), value, state)
 
     def from_python(self, value, state):
-        if isinstance(value, basestring):
+        if isinstance(value, str):
             value = (value,)
         try:
             return ",".join(value)
@@ -1358,7 +1358,7 @@ class DecimalValidator(SOValidator):
     def to_python(self, value, state):
         if value is None:
             return None
-        if isinstance(value, (int, long, Decimal, sqlbuilder.SQLExpression)):
+        if isinstance(value, (int, Decimal, sqlbuilder.SQLExpression)):
             return value
         if isinstance(value, float):
             value = str(value)
@@ -1380,7 +1380,7 @@ class DecimalValidator(SOValidator):
             return None
         if isinstance(value, float):
             value = str(value)
-        if isinstance(value, basestring):
+        if isinstance(value, str):
             try:
                 connection = state.connection or state.soObject._connection
             except AttributeError:
@@ -1393,7 +1393,7 @@ class DecimalValidator(SOValidator):
             except:
                 raise validators.Invalid("can not parse Decimal value '%s' in the DecimalCol from '%s'" %
                     (value, getattr(state, 'soObject', '(unknown)')), value, state)
-        if isinstance(value, (int, long, Decimal, sqlbuilder.SQLExpression)):
+        if isinstance(value, (int, Decimal, sqlbuilder.SQLExpression)):
             return value
         raise validators.Invalid("expected a Decimal in the DecimalCol '%s', got %s %r instead" % \
             (self.name, type(value), value), value, state)
@@ -1447,7 +1447,7 @@ class DecimalStringValidator(DecimalValidator):
                         "Value must be less than %s" % int(self.max)
                 value = value.quantize(self.precision)
             value = value.to_eng_string()
-        elif isinstance(value, (int, long)):
+        elif isinstance(value, int):
             value = str(value)
         return value
 
@@ -1569,7 +1569,7 @@ class PickleValidator(BinaryValidator):
     def to_python(self, value, state):
         if value is None:
             return None
-        if isinstance(value, unicode):
+        if isinstance(value, str):
             dbEncoding = self.getDbEncoding(state, default='ascii')
             value = value.encode(dbEncoding)
         if isinstance(value, str):
@@ -1610,7 +1610,7 @@ def pushKey(kw, name, value):
         kw[name] = value
 
 all = []
-for key, value in globals().items():
+for key, value in list(globals().items()):
     if isinstance(value, type) and (issubclass(value, (Col, SOCol))):
         all.append(key)
 __all__.extend(all)
--- sqlobject/converters.py.orig	2014-05-04 12:48:24 UTC
+++ sqlobject/converters.py
@@ -95,7 +95,7 @@ def StringLikeConverter(value, db):
     return "'%s'" % value
 
 registerConverter(str, StringLikeConverter)
-registerConverter(unicode, StringLikeConverter)
+registerConverter(str, StringLikeConverter)
 registerConverter(array, StringLikeConverter)
 registerConverter(buffer, StringLikeConverter)
 
@@ -107,7 +107,7 @@ registerConverter(int, IntConverter)
 def LongConverter(value, db):
     return str(value)
 
-registerConverter(long, LongConverter)
+registerConverter(int, LongConverter)
 
 if NumericType:
     registerConverter(NumericType, IntConverter)
@@ -203,8 +203,8 @@ def sqlrepr(obj, db=None):
     except AttributeError:
         converter = lookupConverter(obj)
         if converter is None:
-            raise ValueError, "Unknown SQL builtin type: %s for %s" % \
-                  (type(obj), repr(obj))
+            raise ValueError("Unknown SQL builtin type: %s for %s" % \
+                  (type(obj), repr(obj)))
         return converter(obj, db)
     else:
         return reprFunc(db)
--- sqlobject/dbconnection.py.orig	2013-07-07 18:43:26 UTC
+++ sqlobject/dbconnection.py
@@ -6,17 +6,17 @@ import os
 import sys
 import threading
 import types
-import urllib
+import urllib.request, urllib.parse, urllib.error
 import warnings
 import weakref
 
-from cache import CacheSet
-import classregistry
-import col
-from converters import sqlrepr
-import main
-import sqlbuilder
-from util.threadinglocal import local as threading_local
+from .cache import CacheSet
+from . import classregistry
+from . import col
+from .converters import sqlrepr
+from . import main
+from . import sqlbuilder
+from .util.threadinglocal import local as threading_local
 
 warnings.filterwarnings("ignore", "DB-API extension cursor.lastrowid used")
 
@@ -34,7 +34,7 @@ class ConsoleWriter:
         self.dbEncoding = getattr(connection, "dbEncoding", None) or "ascii"
     def write(self, text):
         logfile = getattr(sys, self.loglevel)
-        if isinstance(text, unicode):
+        if isinstance(text, str):
             try:
                 text = text.encode(self.dbEncoding)
             except UnicodeEncodeError:
@@ -111,9 +111,9 @@ class DBConnection:
     def uri(self):
         auth = getattr(self, 'user', '') or ''
         if auth:
-            auth = urllib.quote(auth)
+            auth = urllib.parse.quote(auth)
             if self.password:
-                auth = auth + ':' + urllib.quote(self.password)
+                auth = auth + ':' + urllib.parse.quote(self.password)
             auth = auth + '@'
         else:
             assert not getattr(self, 'password', None), (
@@ -127,7 +127,7 @@ class DBConnection:
         db = self.db
         if db.startswith('/'):
             db = db[1:]
-        return uri + urllib.quote(db)
+        return uri + urllib.parse.quote(db)
 
     @classmethod
     def connectionFromOldURI(cls, uri):
@@ -167,9 +167,9 @@ class DBConnection:
             try:
                 port = int(port)
             except ValueError:
-                raise ValueError, "port must be integer, got '%s' instead" % port
+                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
+                raise ValueError("port must be integer in the range 1-65535, got '%d' instead" % port)
             host = _host
         else:
             port = None
@@ -183,15 +183,15 @@ class DBConnection:
             arglist = arglist.split('&')
             for single in arglist:
                 argname, argvalue = single.split('=', 1)
-                argvalue = urllib.unquote(argvalue)
+                argvalue = urllib.parse.unquote(argvalue)
                 args[argname] = argvalue
         return user, password, host, port, path, args
 
     @staticmethod
     def _parseURI(uri):
-        protocol, request = urllib.splittype(uri)
+        protocol, request = urllib.parse.splittype(uri)
         user, password, port = None, None, None
-        host, path = urllib.splithost(request)
+        host, path = urllib.parse.splithost(request)
 
         if host:
             # Python < 2.7 have a problem - splituser() calls unquote() too early
@@ -199,17 +199,17 @@ class DBConnection:
             if '@' in host:
                 user, host = host.split('@', 1)
             if user:
-                user, password = [x and urllib.unquote(x) or None for x in urllib.splitpasswd(user)]
-            host, port = urllib.splitport(host)
+                user, password = [x and urllib.parse.unquote(x) or None for x in urllib.parse.splitpasswd(user)]
+            host, port = urllib.parse.splitport(host)
             if port: port = int(port)
         elif host == '':
             host = None
 
         # hash-tag is splitted but ignored
-        path, tag = urllib.splittag(path)
-        path, query = urllib.splitquery(path)
+        path, tag = urllib.parse.splittag(path)
+        path, query = urllib.parse.splitquery(path)
 
-        path = urllib.unquote(path)
+        path = urllib.parse.unquote(path)
         if (os.name == 'nt') and (len(path) > 2):
             # Preserve backward compatibility with URIs like /C|/path;
             # replace '|' by ':'
@@ -282,7 +282,7 @@ class ConnWrapper(object):
                 "because it takes **kw: %r"
                 % meth)
             takes_conn = 'connection' in args
-            meth.im_func.takes_connection = takes_conn
+            meth.__func__.takes_connection = takes_conn
         if not takes_conn:
             return meth
         return ConnMethodWrapper(meth, self._connection)
@@ -363,7 +363,7 @@ class DBAPI(DBConnection):
                 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'
+                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')
@@ -593,7 +593,7 @@ class DBAPI(DBConnection):
 
     def _SO_selectOneAlt(self, so, columnNames, condition):
         if columnNames:
-            columns = [isinstance(x, basestring) and sqlbuilder.SQLConstant(x) or x for x in columnNames]
+            columns = [isinstance(x, str) and sqlbuilder.SQLConstant(x) or x for x in columnNames]
         else:
             columns = None
         return self.queryOne(self.sqlrepr(sqlbuilder.Select(columns,
@@ -643,7 +643,7 @@ class DBAPI(DBConnection):
         data = {}
         if 'id' in kw:
             data[soClass.sqlmeta.idName] = kw.pop('id')
-        for key, col in soClass.sqlmeta.columns.items():
+        for key, col in list(soClass.sqlmeta.columns.items()):
             if key in kw:
                 value = kw.pop(key)
                 if col.from_python:
@@ -657,7 +657,7 @@ class DBAPI(DBConnection):
                     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()
+            raise TypeError("got an unexpected keyword argument(s): %r" % list(kw.keys()))
 
         if not data:
             return None
@@ -665,7 +665,7 @@ class DBAPI(DBConnection):
             ['%s %s %s' %
              (dbName, ops.get(value, "="), self.sqlrepr(value))
              for dbName, value
-             in data.items()])
+             in list(data.items())])
 
     def sqlrepr(self, v):
         return sqlrepr(v, self.dbName)
@@ -718,7 +718,7 @@ class Iteration(object):
     def __iter__(self):
         return self
 
-    def next(self):
+    def __next__(self):
         result = self.cursor.fetchone()
         if result is None:
             self._cleanup()
@@ -791,7 +791,7 @@ class Transaction(object):
         if not cls in self._deletedCache:
             self._deletedCache[cls] = []
         self._deletedCache[cls].append(inst.id)
-        meth = new.instancemethod(self._dbConnection._SO_delete.im_func, self, self.__class__)
+        meth = new.instancemethod(self._dbConnection._SO_delete.__func__, self, self.__class__)
         return meth(inst)
 
     def commit(self, close=False):
@@ -801,8 +801,8 @@ class Transaction(object):
         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()])
+        subCaches = [(sub[0], sub[1].allIDs()) for sub in list(self.cache.allSubCachesByClassNames().items())]
+        subCaches.extend([(x[0], x[1]) for x in list(self._deletedCache.items())])
         for cls, ids in subCaches:
             for id in ids:
                 inst = self._dbConnection.cache.tryGetByName(id, cls)
@@ -836,7 +836,7 @@ class Transaction(object):
         self.assertActive()
         attr = getattr(self._dbConnection, attr)
         try:
-            func = attr.im_func
+            func = attr.__func__
         except AttributeError:
             if isinstance(attr, ConnWrapper):
                 return ConnWrapper(attr._soClass, self)
@@ -996,9 +996,9 @@ class ConnectionURIOpener(object):
     def connectionForURI(self, uri, oldUri=False, **args):
         if args:
             if '?' not in uri:
-                uri += '?' + urllib.urlencode(args)
+                uri += '?' + urllib.parse.urlencode(args)
             else:
-                uri += '&' + urllib.urlencode(args)
+                uri += '&' + urllib.parse.urlencode(args)
         if uri in self.cachedURIs:
             return self.cachedURIs[uri]
         if uri.find(':') != -1:
@@ -1020,7 +1020,7 @@ class ConnectionURIOpener(object):
     def dbConnectionForScheme(self, scheme):
         assert scheme in self.schemeBuilders, (
                "No SQLObject driver exists for %s (only %s)"
-               % (scheme, ', '.join(self.schemeBuilders.keys())))
+               % (scheme, ', '.join(list(self.schemeBuilders.keys()))))
         return self.schemeBuilders[scheme]()
 
 TheURIOpener = ConnectionURIOpener()
@@ -1031,11 +1031,11 @@ connectionForURI = TheURIOpener.connectionForURI
 dbConnectionForScheme = TheURIOpener.dbConnectionForScheme
 
 # Register DB URI schemas
-import firebird
-import maxdb
-import mssql
-import mysql
-import postgres
-import rdbhost
-import sqlite
-import sybase
+from . import firebird
+from . import maxdb
+from . import mssql
+from . import mysql
+from . import postgres
+from . import rdbhost
+from . import sqlite
+from . import sybase
--- sqlobject/events.py.orig	2010-11-13 17:42:40 UTC
+++ sqlobject/events.py
@@ -206,25 +206,25 @@ def summarize_events_by_sender(sender=None, output=Non
     if sender is None:
         send_list = [
             (deref(dispatcher.senders.get(sid)), listeners)
-            for sid, listeners in dispatcher.connections.items()
+            for sid, listeners in list(dispatcher.connections.items())
             if deref(dispatcher.senders.get(sid))]
         for sender, listeners in sorted_items(send_list):
             real_sender = deref(sender)
             if not real_sender:
                 continue
             header = 'Sender: %r' % real_sender
-            print >> output, (' '*indent) + header
-            print >> output, (' '*indent) + '='*len(header)
+            print((' '*indent) + header, file=output)
+            print((' '*indent) + '='*len(header), file=output)
             summarize_events_by_sender(real_sender, output=output, indent=indent+2)
     else:
         for signal, receivers in sorted_items(dispatcher.connections.get(id(sender), [])):
             receivers = [deref(r) for r in receivers if deref(r)]
             header = 'Signal: %s (%i receivers)' % (sort_name(signal),
                                                     len(receivers))
-            print >> output, (' '*indent) + header
-            print >> output, (' '*indent) + '-'*len(header)
+            print((' '*indent) + header, file=output)
+            print((' '*indent) + '-'*len(header), file=output)
             for receiver in sorted(receivers, key=sort_name):
-                print >> output, (' '*indent) + '  ' + nice_repr(receiver)
+                print((' '*indent) + '  ' + nice_repr(receiver), file=output)
 
 def deref(value):
     if isinstance(value, dispatcher.WEAKREF_TYPES):
@@ -234,14 +234,14 @@ def deref(value):
 
 def sorted_items(a_dict):
     if isinstance(a_dict, dict):
-        a_dict = a_dict.items()
+        a_dict = list(a_dict.items())
     return sorted(a_dict, key=lambda t: sort_name(t[0]))
 
 def sort_name(value):
     if isinstance(value, type):
         return value.__name__
     elif isinstance(value, types.FunctionType):
-        return value.func_name
+        return value.__name__
     else:
         return str(value)
 
@@ -262,26 +262,26 @@ def debug_events():
 
 def _debug_send(signal=dispatcher.Any, sender=dispatcher.Anonymous,
                 *arguments, **named):
-    print "send %s from %s: %s" % (
-        nice_repr(signal), nice_repr(sender), fmt_args(*arguments, **named))
+    print("send %s from %s: %s" % (
+        nice_repr(signal), nice_repr(sender), fmt_args(*arguments, **named)))
     return _real_dispatcher_send(signal, sender, *arguments, **named)
 
 def _debug_sendExact(signal=dispatcher.Any, sender=dispatcher.Anonymous,
                      *arguments, **named):
-    print "sendExact %s from %s: %s" % (
-        nice_repr(signal), nice_repr(sender), fmt_args(*arguments, **name))
+    print("sendExact %s from %s: %s" % (
+        nice_repr(signal), nice_repr(sender), fmt_args(*arguments, **name)))
     return _real_dispatcher_sendExact(signal, sender, *arguments, **named)
 
 def _debug_connect(receiver, signal=dispatcher.Any, sender=dispatcher.Any,
                    weak=True):
-    print "connect %s to %s signal %s" % (
-        nice_repr(receiver), nice_repr(signal), nice_repr(sender))
+    print("connect %s to %s signal %s" % (
+        nice_repr(receiver), nice_repr(signal), nice_repr(sender)))
     return _real_dispatcher_connect(receiver, signal, sender, weak)
 
 def _debug_disconnect(receiver, signal=dispatcher.Any, sender=dispatcher.Any,
                       weak=True):
-    print "disconnecting %s from %s signal %s" % (
-        nice_repr(receiver), nice_repr(signal), nice_repr(sender))
+    print("disconnecting %s from %s signal %s" % (
+        nice_repr(receiver), nice_repr(signal), nice_repr(sender)))
     return disconnect(receiver, signal, sender, weak)
 
 def fmt_args(*arguments, **name):
@@ -294,23 +294,23 @@ def nice_repr(v):
     """
     Like repr(), but nicer for debugging here.
     """
-    if isinstance(v, (types.ClassType, type)):
+    if isinstance(v, type):
         return v.__module__ + '.' + v.__name__
     elif isinstance(v, types.FunctionType):
-        if '__name__' in v.func_globals:
-            if getattr(sys.modules[v.func_globals['__name__']],
-                       v.func_name, None) is v:
-                return '%s.%s' % (v.func_globals['__name__'], v.func_name)
+        if '__name__' in v.__globals__:
+            if getattr(sys.modules[v.__globals__['__name__']],
+                       v.__name__, None) is v:
+                return '%s.%s' % (v.__globals__['__name__'], v.__name__)
         return repr(v)
     elif isinstance(v, types.MethodType):
         return '%s.%s of %s' % (
-            nice_repr(v.im_class), v.im_func.func_name,
-            nice_repr(v.im_self))
+            nice_repr(v.__self__.__class__), v.__func__.__name__,
+            nice_repr(v.__self__))
     else:
         return repr(v)
 
 
 __all__ = ['listen', 'send']
-for name, value in globals().items():
+for name, value in list(globals().items()):
     if isinstance(value, type) and issubclass(value, Signal):
         __all__.append(name)
--- sqlobject/include/pydispatch/dispatcher.py.orig	2011-05-15 15:48:27 UTC
+++ sqlobject/include/pydispatch/dispatcher.py
@@ -25,20 +25,14 @@ Internal attributes:
 		deletion, (considerably speeds up the cleanup process
 		vs. the original code.)
 """
-from __future__ import generators
+
 import types, weakref
-import saferef, robustapply, errors
+from . import saferef, robustapply, errors
 
 __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
 __cvsid__ = "$Id: dispatcher.py,v 1.9 2005/09/17 04:55:57 mcfletch Exp $"
 __version__ = "$Revision: 1.9 $"[11:-2]
 
-try:
-	True
-except NameError:
-	True = 1==1
-	False = 1==0
-
 class _Parameter:
 	"""Used to represent default parameter values."""
 	def __repr__(self):
@@ -379,8 +373,8 @@ def _removeReceiver(receiver):
 	backKey = id(receiver)
 	for senderkey in sendersBack.get(backKey,()):
 		try:
-			signals = connections[senderkey].keys()
-		except KeyError,err:
+			signals = list(connections[senderkey].keys())
+		except KeyError as err:
 			pass
 		else:
 			for signal in signals:
@@ -391,7 +385,7 @@ def _removeReceiver(receiver):
 				else:
 					try:
 						receivers.remove( receiver )
-					except Exception, err:
+					except Exception as err:
 						pass
 				_cleanupConnections(senderkey, signal)
 	try:
@@ -440,7 +434,7 @@ def _removeBackrefs( senderkey):
 	except KeyError:
 		signals = None
 	else:
-		items = signals.items()
+		items = list(signals.items())
 		def allReceivers( ):
 			for signal,set in items:
 				for item in set:
@@ -468,7 +462,7 @@ def _removeOldBackRefs(senderkey, signal, receiver, re
 		found = 0
 		signals = connections.get(signal)
 		if signals is not None:
-			for sig,recs in connections.get(signal,{}).iteritems():
+			for sig,recs in connections.get(signal,{}).items():
 				if sig != signal:
 					for rec in recs:
 						if rec is oldReceiver:
--- sqlobject/include/pydispatch/robust.py.orig	2006-02-09 16:14:04 UTC
+++ sqlobject/include/pydispatch/robust.py
@@ -1,6 +1,6 @@
 """Module implementing error-catching version of send (sendRobust)"""
-from dispatcher import Any, Anonymous, liveReceivers, getAllReceivers
-from robustapply import robustApply
+from .dispatcher import Any, Anonymous, liveReceivers, getAllReceivers
+from .robustapply import robustApply
 
 def sendRobust(
 	signal=Any, 
@@ -50,7 +50,7 @@ def sendRobust(
 				*arguments,
 				**named
 			)
-		except Exception, err:
+		except Exception as err:
 			responses.append((receiver, err))
 		else:
 			responses.append((receiver, response))
--- sqlobject/include/pydispatch/saferef.py.orig	2006-02-09 16:14:04 UTC
+++ sqlobject/include/pydispatch/saferef.py
@@ -13,7 +13,7 @@ def safeRef(target, onDelete = None):
 		weakref or a BoundMethodWeakref) as argument.
 	"""
 	if hasattr(target, 'im_self'):
-		if target.im_self is not None:
+		if target.__self__ is not None:
 			# Turn a bound method into a BoundMethodWeakref instance.
 			# Keep track of these instances for lookup by disconnect().
 			assert hasattr(target, 'im_func'), """safeRef target %r has im_self, but no im_func, don't know how to create reference"""%( target,)
@@ -109,26 +109,26 @@ class BoundMethodWeakref(object):
 				try:
 					if callable( function ):
 						function( self )
-				except Exception, e:
+				except Exception as e:
 					try:
 						traceback.print_exc()
-					except AttributeError, err:
-						print '''Exception during saferef %s cleanup function %s: %s'''%(
+					except AttributeError as err:
+						print('''Exception during saferef %s cleanup function %s: %s'''%(
 							self, function, e
-						)
+						))
 		self.deletionMethods = [onDelete]
 		self.key = self.calculateKey( target )
-		self.weakSelf = weakref.ref(target.im_self, remove)
-		self.weakFunc = weakref.ref(target.im_func, remove)
-		self.selfName = str(target.im_self)
-		self.funcName = str(target.im_func.__name__)
+		self.weakSelf = weakref.ref(target.__self__, remove)
+		self.weakFunc = weakref.ref(target.__func__, remove)
+		self.selfName = str(target.__self__)
+		self.funcName = str(target.__func__.__name__)
 	def calculateKey( cls, target ):
 		"""Calculate the reference key for this reference
 
 		Currently this is a two-tuple of the id()'s of the
 		target object and the target function respectively.
 		"""
-		return (id(target.im_self),id(target.im_func))
+		return (id(target.__self__),id(target.__func__))
 	calculateKey = classmethod( calculateKey )
 	def __str__(self):
 		"""Give a friendly representation of the object"""
@@ -138,7 +138,7 @@ class BoundMethodWeakref(object):
 			self.funcName,
 		)
 	__repr__ = __str__
-	def __nonzero__( self ):
+	def __bool__( self ):
 		"""Whether we are still a valid reference"""
 		return self() is not None
 	def __cmp__( self, other ):
--- sqlobject/index.py.orig	2011-05-15 15:48:27 UTC
+++ sqlobject/index.py
@@ -1,6 +1,6 @@
 from itertools import count
 from types import *
-from converters import sqlrepr
+from .converters import sqlrepr
 
 creationOrder = count()
 
@@ -20,15 +20,15 @@ class SODatabaseIndex(object):
 
     def get(self, *args, **kw):
         if not self.unique:
-            raise AttributeError, (
+            raise AttributeError(
                 "'%s' object has no attribute 'get' (index is not unique)" % self.name)
         connection = kw.pop('connection', None)
         if args and kw:
-            raise TypeError, "You cannot mix named and unnamed arguments"
+            raise TypeError("You cannot mix named and unnamed arguments")
         columns = [d['column'] for d in self.descriptions
             if 'column' in d]
         if kw and len(kw) != len(columns) or args and len(args) != len(columns):
-            raise TypeError, ("get() takes exactly %d argument and an optional "
+            raise TypeError("get() takes exactly %d argument and an optional "
                 "named argument 'connection' (%d given)" % (
                 len(columns), len(args)+len(kw)))
         if args:
@@ -65,13 +65,13 @@ class SODatabaseIndex(object):
                 columnName = columnName.name
             colDict = self.soClass.sqlmeta.columns
             if columnName not in colDict:
-                for possible in colDict.values():
+                for possible in list(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)
+                    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
@@ -153,7 +153,7 @@ class DatabaseIndex(object):
     def __init__(self, *columns, **kw):
         kw['columns'] = columns
         self.kw = kw
-        self.creationOrder = creationOrder.next()
+        self.creationOrder = next(creationOrder)
 
     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)
--- sqlobject/inheritance/__init__.py.orig	2011-05-15 15:48:27 UTC
+++ sqlobject/inheritance/__init__.py
@@ -5,7 +5,8 @@ from sqlobject import sqlbuilder
 from sqlobject.col import StringCol, ForeignKey
 from sqlobject.main import sqlmeta, SQLObject, SelectResults, \
    makeProperties, unmakeProperties, getterName, setterName
-import iteration
+from . import iteration
+from functools import reduce
 
 def tablesUsedSet(obj, db):
     if hasattr(obj, "tablesUsedSet"):
@@ -35,7 +36,7 @@ class InheritableSelectResults(SelectResults):
         if inheritedTables:
             for tableName in inheritedTables:
                 tablesSet.add(str(tableName))
-        if orderBy and not isinstance(orderBy, basestring):
+        if orderBy and not isinstance(orderBy, str):
             tablesSet.update(tablesUsedSet(orderBy, dbName))
         #DSM: if this class has a parent, we need to link it
         #DSM: and be sure the parent is in the table list.
@@ -69,7 +70,7 @@ class InheritableSelectResults(SelectResults):
             #DSM: Table registry contains only the last children
             #DSM: or standalone classes
             parentClause = []
-            for (currentClass, minParentClass) in tableRegistry.items():
+            for (currentClass, minParentClass) in list(tableRegistry.items()):
                 while (currentClass != minParentClass) \
                 and currentClass.sqlmeta.parentClass:
                     parentClass = currentClass.sqlmeta.parentClass
@@ -86,7 +87,7 @@ class InheritableSelectResults(SelectResults):
             return super(InheritableSelectResults, self).accumulateMany(*attributes)
         tables = []
         for func_name, attribute in attributes:
-           if not isinstance(attribute, basestring):
+           if not isinstance(attribute, str):
                 tables.append(attribute.tableName)
         clone = self.__class__(self.sourceClass, self.clause,
                           self.clauseTables, inheritedTables=tables, **self.ops)
@@ -130,7 +131,7 @@ class InheritableSQLMeta(sqlmeta):
             q = getattr(soClass.q, columnDef.name, None)
         else:
             q = None
-        for c in sqlmeta.childClasses.values():
+        for c in list(sqlmeta.childClasses.values()):
             c.sqlmeta.addColumn(columnDef, connection=connection, childUpdate=True)
             if q: setattr(c.q, columnDef.name, q)
 
@@ -153,7 +154,7 @@ class InheritableSQLMeta(sqlmeta):
 
         #DSM: Update each child class if needed
         #DSM: and delete properties for this column
-        for c in sqlmeta.childClasses.values():
+        for c in list(sqlmeta.childClasses.values()):
             c.sqlmeta.delColumn(column, changeSchema=changeSchema,
                 connection=connection, childUpdate=True)
 
@@ -184,7 +185,7 @@ class InheritableSQLMeta(sqlmeta):
 
         #DSM: Update each child class if needed and existing (only for new
         #DSM: dynamic join as no child classes exists at object creation)
-        for c in sqlmeta.childClasses.values():
+        for c in list(sqlmeta.childClasses.values()):
             c.sqlmeta.addJoin(joinDef, childUpdate=True)
 
     @classmethod
@@ -199,7 +200,7 @@ class InheritableSQLMeta(sqlmeta):
 
         #DSM: Update each child class if needed
         #DSM: and delete properties for this join
-        for c in sqlmeta.childClasses.values():
+        for c in list(sqlmeta.childClasses.values()):
             c.sqlmeta.delJoin(joinDef, childUpdate=True)
 
     @classmethod
@@ -236,7 +237,7 @@ class InheritableSQLObject(SQLObject):
         # if we are a child class, add sqlbuilder fields from parents
         currentClass = cls.sqlmeta.parentClass
         while currentClass:
-            for column in currentClass.sqlmeta.columnDefinitions.values():
+            for column in list(currentClass.sqlmeta.columnDefinitions.values()):
                 if column.name == 'childName':
                     continue
                 if isinstance(column, ForeignKey):
@@ -319,7 +320,7 @@ class InheritableSQLObject(SQLObject):
         # verify names of added columns
         if sqlmeta.parentClass:
             # FIXME: this does not check for grandparent column overrides
-            parentCols = sqlmeta.parentClass.sqlmeta.columns.keys()
+            parentCols = list(sqlmeta.parentClass.sqlmeta.columns.keys())
             for column in sqlmeta.columnList:
                 if column.name == 'childName':
                     raise AttributeError(
@@ -357,7 +358,7 @@ class InheritableSQLObject(SQLObject):
             parentClass = self.sqlmeta.parentClass
             new_kw = {}
             parent_kw = {}
-            for (name, value) in kw.items():
+            for (name, value) in list(kw.items()):
                 if (name != 'childName') and hasattr(parentClass, name):
                     parent_kw[name] = value
                 else:
@@ -370,7 +371,7 @@ class InheritableSQLObject(SQLObject):
             for col in self.sqlmeta.columnList:
                 if (col._default == sqlbuilder.NoDefault) and \
                         (col.name not in kw) and (col.foreignName not in kw):
-                    raise TypeError, "%s() did not get expected keyword argument %s" % (self.__class__.__name__, col.name)
+                    raise TypeError("%s() did not get expected keyword argument %s" % (self.__class__.__name__, col.name))
 
             parent_kw['childName'] = self.sqlmeta.childName
             self._parent = parentClass(kw=parent_kw,
@@ -426,7 +427,7 @@ class InheritableSQLObject(SQLObject):
                 addClause = parentClass.q.childName == cls.sqlmeta.childName
                 # if the clause was one of TRUE varians, replace it
                 if (clause is None) or (clause is sqlbuilder.SQLTrueClause) \
-                or (isinstance(clause, basestring) and (clause == 'all')):
+                or (isinstance(clause, str) and (clause == 'all')):
                     clause = addClause
                 else:
                     # patch WHERE condition:
@@ -471,11 +472,11 @@ class InheritableSQLObject(SQLObject):
         currentClass = cls
         while currentClass:
             foreignColumns.update(dict([(column.foreignName, name)
-                for (name, column) in currentClass.sqlmeta.columns.items()
+                for (name, column) in list(currentClass.sqlmeta.columns.items())
                     if column.foreignKey
             ]))
             currentClass = currentClass.sqlmeta.parentClass
-        for name, value in kw.items():
+        for name, value in list(kw.items()):
             if name in foreignColumns:
                 name = foreignColumns[name] # translate "key" to "keyID"
                 if isinstance(value, SQLObject):
@@ -485,7 +486,7 @@ class InheritableSQLObject(SQLObject):
                 try:
                     clause.append(getattr(currentClass.q, name) == value)
                     break
-                except AttributeError, err:
+                except AttributeError as err:
                     pass
                 currentClass = currentClass.sqlmeta.parentClass
             else:
--- sqlobject/main.py.orig	2013-10-14 16:07:00 UTC
+++ sqlobject/main.py
@@ -28,23 +28,23 @@ USA.
 
 import threading
 import weakref
-import sqlbuilder
-import dbconnection
-import col
-import styles
+from . import sqlbuilder
+from . import dbconnection
+from . import col
+from . import styles
 import types
 import warnings
-import joins
-import index
-import classregistry
-import declarative
-import events
-from sresults import SelectResults
-from util.threadinglocal import local
+from . import joins
+from . import index
+from . import classregistry
+from . import declarative
+from . import events
+from .sresults import SelectResults
+from .util.threadinglocal import local
 
 import sys
 if sys.version_info[:3] < (2, 5, 0):
-    raise ImportError, "SQLObject requires Python 2.5.0 or later"
+    raise ImportError("SQLObject requires Python 2.5.0 or later")
 
 """
 This thread-local storage is needed for RowCreatedSignals. It gathers
@@ -81,7 +81,7 @@ def makeProperties(obj):
         d = obj.__dict__
 
     props = {}
-    for var, value in d.items():
+    for var, value in list(d.items()):
         if var.startswith('_set_'):
             props.setdefault(var[5:], {})['set'] = value
         elif var.startswith('_get_'):
@@ -90,7 +90,7 @@ def makeProperties(obj):
             props.setdefault(var[5:], {})['del'] = value
         elif var.startswith('_doc_'):
             props.setdefault(var[5:], {})['doc'] = value
-    for var, setters in props.items():
+    for var, setters in list(props.items()):
         if len(setters) == 1 and 'doc' in setters:
             continue
         if var in d:
@@ -115,7 +115,7 @@ def unmakeProperties(obj):
         delFunc = delattr
         d = obj.__dict__
 
-    for var, value in d.items():
+    for var, value in list(d.items()):
         if isinstance(value, property):
             for prop in [value.fget, value.fset, value.fdel]:
                 if prop and not prop.__name__ in d:
@@ -148,7 +148,7 @@ def _collectAttributes(cls, new_attrs, look_for_class)
 
     """
     result = []
-    for attr, value in new_attrs.items():
+    for attr, value in list(new_attrs.items()):
         if isinstance(value, look_for_class):
             value.name = attr
             delattr(cls, attr)
@@ -162,7 +162,7 @@ class CreateNewSQLObject:
     """
     pass
 
-class sqlmeta(object):
+class sqlmeta(object, metaclass=declarative.DeclarativeMeta):
 
     """
     This object is the object we use to keep track of all sorts of
@@ -236,8 +236,6 @@ class sqlmeta(object):
     # Default encoding for UnicodeCol's
     dbEncoding = None
 
-    __metaclass__ = declarative.DeclarativeMeta
-
     def __classinit__(cls, new_attrs):
         for attr in cls._unshared_attributes:
             if attr not in new_attrs:
@@ -321,7 +319,7 @@ class sqlmeta(object):
         parent_columns = []
         for base in soClass.__bases__:
             if hasattr(base, "sqlmeta"):
-                parent_columns.extend(base.sqlmeta.columns.keys())
+                parent_columns.extend(list(base.sqlmeta.columns.keys()))
         if hasattr(soClass, name):
             assert  (name in parent_columns) or (name == "childName"), (
                 "The class %s.%s already has a variable or method %r, you cannot "
@@ -440,7 +438,7 @@ class sqlmeta(object):
         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):
+                if isinstance(columnDef.name, str):
                     columnDef.name = columnDef.name.encode('ascii')
                 sqlmeta.addColumn(columnDef)
 
@@ -456,7 +454,7 @@ class sqlmeta(object):
             else:
                 raise ValueError('Unknown column ' + column)
         if isinstance(column, col.Col):
-            for c in sqlmeta.columns.values():
+            for c in list(sqlmeta.columns.values()):
                 if column is c.columnDef:
                     column = c
                     break
@@ -704,10 +702,8 @@ _postponed_local = local()
 # here, though -- just automatic method generation (like
 # methods and properties for each column) is done in
 # MetaSQLObject.
-class SQLObject(object):
+class SQLObject(object, metaclass=declarative.DeclarativeMeta):
 
-    __metaclass__ = declarative.DeclarativeMeta
-
     _connection = sqlhub
 
     sqlmeta = sqlmeta
@@ -770,12 +766,12 @@ class SQLObject(object):
         # _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 sqlmeta.columnDefinitions.keys():
+        for key in list(sqlmeta.columnDefinitions.keys()):
             if (key in new_attrs
                 and new_attrs[key] is None):
                 del sqlmeta.columnDefinitions[key]
 
-        for column in sqlmeta.columnDefinitions.values():
+        for column in list(sqlmeta.columnDefinitions.values()):
             sqlmeta.addColumn(column)
 
         for column in implicitColumns:
@@ -850,7 +846,7 @@ class SQLObject(object):
                     "(while fixing up sqlmeta %r inheritance)"
                     % cls.sqlmeta)
             values = dict(cls.sqlmeta.__dict__)
-            for key in values.keys():
+            for key in list(values.keys()):
                 if key.startswith('__') and key.endswith('__'):
                     # Magic values shouldn't be passed through:
                     del values[key]
@@ -931,7 +927,7 @@ class SQLObject(object):
             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)
+                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.sqlmeta.dirty = False
@@ -958,7 +954,7 @@ class SQLObject(object):
                 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)
+                    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
@@ -973,7 +969,7 @@ class SQLObject(object):
             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)
+                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:
@@ -986,7 +982,7 @@ class SQLObject(object):
         try:
             if self.sqlmeta.columns:
                 values = [(self.sqlmeta.columns[v[0]].dbName, v[1])
-                          for v in self._SO_createValues.items()]
+                          for v in list(self._SO_createValues.items())]
                 self._connection._SO_update(self, values)
             self.sqlmeta.dirty = False
             self._SO_createValues = {}
@@ -1067,13 +1063,13 @@ class SQLObject(object):
         is_column = lambda _c: _c in self.sqlmeta._plainSetters
         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))
+        items = list(kw.items())
+        extra = dict(list(filter(f_not_column, items)))
+        kw = dict(list(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():
+            for name, value in list(kw.items()):
                 from_python = getattr(self, '_SO_from_python_%s' % name, None)
                 if from_python:
                     kw[name] = dbValue = from_python(value, self._SO_validatorState)
@@ -1086,16 +1082,16 @@ class SQLObject(object):
 
             self._SO_createValues.update(kw)
 
-            for name, value in extra.items():
+            for name, value in list(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)
+                        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)
+                except AttributeError as e:
+                    raise AttributeError('%s (with attribute %r)' % (e, name))
 
             self.sqlmeta.dirty = True
             return
@@ -1112,7 +1108,7 @@ class SQLObject(object):
             # read the user's mind.  We'll combine everything
             # else into a single UPDATE, if necessary.
             toUpdate = {}
-            for name, value in kw.items():
+            for name, value in list(kw.items()):
                 from_python = getattr(self, '_SO_from_python_%s' % name, None)
                 if from_python:
                     dbValue = from_python(value, self._SO_validatorState)
@@ -1124,20 +1120,20 @@ class SQLObject(object):
                 if self.sqlmeta.cacheValues:
                     setattr(self, instanceName(name), value)
                 toUpdate[name] = dbValue
-            for name, value in extra.items():
+            for name, value in list(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)
+                        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)
+                except AttributeError as e:
+                    raise AttributeError('%s (with attribute %r)' % (e, name))
 
             if toUpdate:
                 args = [(self.sqlmeta.columns[name].dbName, value)
-                        for name, value in toUpdate.items()]
+                        for name, value in list(toUpdate.items())]
                 self._connection._SO_update(self, args)
         finally:
             self._SO_writeLock.release()
@@ -1257,7 +1253,7 @@ class SQLObject(object):
                 # If we specified an SQL DEFAULT, then we should use that
                 if default is NoDefault:
                     if column.defaultSQL is None:
-                        raise TypeError, "%s() did not get expected keyword argument '%s'" % (self.__class__.__name__, column.name)
+                        raise TypeError("%s() did not get expected keyword argument '%s'" % (self.__class__.__name__, column.name))
                     else:
                         # There is defaultSQL for the column - do not put
                         # the column to kw so that the backend creates the value
@@ -1277,7 +1273,7 @@ class SQLObject(object):
         # 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()
+        setters = list(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]
@@ -1316,7 +1312,7 @@ class SQLObject(object):
             name = (name,)
             value = (value,)
         if len(name) != len(value):
-            raise ValueError, "'column' and 'value' tuples must be of the same size"
+            raise ValueError("'column' and 'value' tuples must be of the same size")
         new_value = []
         for n, v in zip(name, value):
             from_python = getattr(cls, '_SO_from_python_' + n)
@@ -1335,13 +1331,13 @@ class SQLObject(object):
         result, obj = cls._findAlternateID(name, dbName, value, connection)
         if not result:
             if idxName is None:
-                raise SQLObjectNotFound, "The %s by alternateID %s = %s does not exist" % (cls.__name__, name, repr(value))
+                raise SQLObjectNotFound("The %s by alternateID %s = %s does not exist" % (cls.__name__, name, repr(value)))
             else:
                 names = []
-                for i in xrange(len(name)):
+                for i in range(len(name)):
                     names.append("%s = %s" % (name[i], repr(value[i])))
                 names = ', '.join(names)
-                raise SQLObjectNotFound, "The %s by unique index %s(%s) does not exist" % (cls.__name__, idxName, names)
+                raise SQLObjectNotFound("The %s by unique index %s(%s) does not exist" % (cls.__name__, idxName, names))
         if obj:
             return obj
         if connection:
@@ -1564,7 +1560,7 @@ class SQLObject(object):
                 if results.count():
                     # Restrictions only apply if there are
                     # matching records on the related table
-                    raise SQLObjectIntegrityError, (
+                    raise SQLObjectIntegrityError(
                         "Tried to delete %s::%s but "
                         "table %s has a restriction against it" %
                         (klass.__name__, self.id, k.__name__))
@@ -1638,7 +1634,7 @@ class SQLObject(object):
 
     @classmethod
     def setConnection(cls, value):
-        if isinstance(value, basestring):
+        if isinstance(value, str):
             value = dbconnection.connectionForURI(value)
         cls._connection = value
 
@@ -1720,7 +1716,7 @@ def getID(obj, refColumn=None):
         return getattr(obj, refColumn or 'id')
     elif isinstance(obj, int):
         return obj
-    elif isinstance(obj, long):
+    elif isinstance(obj, int):
         return int(obj)
     elif isinstance(obj, str):
         try:
@@ -1733,7 +1729,7 @@ def getID(obj, refColumn=None):
 def getObject(obj, klass):
     if isinstance(obj, int):
         return klass(obj)
-    elif isinstance(obj, long):
+    elif isinstance(obj, int):
         return klass(int(obj))
     elif isinstance(obj, str):
         return klass(int(obj))
--- sqlobject/manager/command.py.orig	2011-05-15 15:48:27 UTC
+++ sqlobject/manager/command.py
@@ -69,10 +69,10 @@ def db_differences(soClass, conn):
                     del existing[col.dbName]
                 else:
                     missing[col.dbName] = col
-            for col in existing.values():
+            for col in list(existing.values()):
                 diffs.append('Database has extra column: %s'
                              % col.dbName)
-            for col in missing.values():
+            for col in list(missing.values()):
                 diffs.append('Database missing column: %s' % col.dbName)
     return diffs
 
@@ -96,7 +96,7 @@ class CommandRunner(object):
             self.invalid('No COMMAND given (try "%s help")'
                          % os.path.basename(invoked_as))
         real_command = self.command_aliases.get(command, command)
-        if real_command not in self.commands.keys():
+        if real_command not in list(self.commands.keys()):
             self.invalid('COMMAND %s unknown' % command)
         runner = self.commands[real_command](
             invoked_as, command, args, self)
@@ -109,7 +109,7 @@ class CommandRunner(object):
             self.command_aliases[alias] = name
 
     def invalid(self, msg, code=2):
-        print msg
+        print(msg)
         sys.exit(code)
 
 the_runner = CommandRunner()
@@ -170,10 +170,8 @@ def standard_parser(connection=True, simulate=True,
                       default=[])
     return parser
 
-class Command(object):
+class Command(object, metaclass=DeclarativeMeta):
 
-    __metaclass__ = DeclarativeMeta
-
     min_args = 0
     min_args_error = 'You must provide at least %(min_args)s arguments'
     max_args = 0
@@ -225,7 +223,7 @@ class Command(object):
             # Check for circular references
             if cls in dependency_stack:
                 dependency_stack.append(cls)
-                raise SQLObjectCircularReferenceError, (
+                raise SQLObjectCircularReferenceError(
                         "Found a circular reference: %s " %
                         (' --> '.join([x.__name__
                                        for x in dependency_stack])))
@@ -248,14 +246,14 @@ class Command(object):
                 sorter.append((level, cls))
             sorter.sort()
             ordered_classes = [cls for level, cls in sorter]
-        except SQLObjectCircularReferenceError, msg:
+        except SQLObjectCircularReferenceError as msg:
             # Failsafe: return the classes as-is if a circular reference
             # prevented the dependency levels to be calculated.
-            print ("Warning: a circular reference was detected in the "
+            print(("Warning: a circular reference was detected in the "
                     "model. Unable to sort the classes by dependency: they "
                     "will be treated in alphabetic order. This may or may "
                     "not work depending on your database backend. "
-                    "The error was:\n%s" % msg)
+                    "The error was:\n%s" % msg))
             return classes
         return ordered_classes
 
@@ -347,21 +345,21 @@ class Command(object):
                     % '\n  * '.join([soClass.__name__
                                      for soClass in missing]))
         if require_some and not all:
-            print 'No classes found!'
+            print('No classes found!')
             if self.options.modules:
-                print 'Looked in modules: %s' % ', '.join(self.options.modules)
+                print('Looked in modules: %s' % ', '.join(self.options.modules))
             else:
-                print 'No modules specified'
+                print('No modules specified')
             if self.options.packages:
-                print 'Looked in packages: %s' % ', '.join(self.options.packages)
+                print('Looked in packages: %s' % ', '.join(self.options.packages))
             else:
-                print 'No packages specified'
+                print('No packages specified')
             if self.options.class_matchers:
-                print 'Matching class pattern: %s' % self.options.class_matches
+                print('Matching class pattern: %s' % self.options.class_matches)
             if self.options.eggs:
-                print 'Looked in eggs: %s' % ', '.join(self.options.eggs)
+                print('Looked in eggs: %s' % ', '.join(self.options.eggs))
             else:
-                print 'No eggs specified'
+                print('No eggs specified')
             sys.exit(1)
         return self.orderClassesByDependencyLevel(all)
 
@@ -411,7 +409,7 @@ class Command(object):
         if '#' in conf_fn:
             conf_fn, conf_section = conf_fn.split('#', 1)
 
-        from ConfigParser import ConfigParser
+        from configparser import ConfigParser
         p = ConfigParser()
         # Case-sensitive:
         p.optionxform = str
@@ -454,21 +452,20 @@ class Command(object):
         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)
+            filenames = [fname for fname in filenames if fname.endswith('.py') and fname != '__init__.py']
             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:
+                except ImportError as err:
                     if self.options.verbose:
-                        print 'Could not import module "%s". Error was : "%s"' % (module_name, err)
+                        print('Could not import module "%s". Error was : "%s"' % (module_name, err))
                     continue
-                except Exception, exc:
+                except Exception as exc:
                     if self.options.verbose:
-                        print 'Unknown exception while processing module "%s" : "%s"' % (module_name, exc)
+                        print('Unknown exception while processing module "%s" : "%s"' % (module_name, exc))
                     continue
                 classes = self.classes_from_module(module)
                 all.extend(classes)
@@ -484,7 +481,7 @@ class Command(object):
             if not mod:
                 continue
             if self.options.verbose:
-                print 'Looking in module %s' % mod
+                print('Looking in module %s' % mod)
             modules.extend(self.classes_from_module(
                 moduleloader.load_module(mod)))
         return modules
@@ -503,7 +500,7 @@ class Command(object):
         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
+                print('No sqlobject.txt in %s egg info' % egg_spec)
             return None, {}
         result = {}
         for line in dist.get_metadata_lines('sqlobject.txt'):
@@ -513,7 +510,7 @@ class Command(object):
             name, value = line.split('=', 1)
             name = name.strip().lower()
             if name in result:
-                print 'Warning: %s appears more than once in sqlobject.txt' % name
+                print('Warning: %s appears more than once in sqlobject.txt' % name)
             result[name.strip().lower()] = value.strip()
         return dist, result
 
@@ -532,12 +529,12 @@ class Command(object):
         else:
             prompt += ' [y/N]? '
         while 1:
-            response = raw_input(prompt).strip()
+            response = 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'
+            print('Y or N please')
 
     def shorten_filename(self, fn):
         """
@@ -558,7 +555,7 @@ class Command(object):
         f = open(fn, 'w')
         f.write(pretext)
         f.close()
-        print '$EDITOR %s' % fn
+        print('$EDITOR %s' % fn)
         os.system('$EDITOR %s' % fn)
         f = open(fn, 'r')
         content = f.read()
@@ -582,16 +579,16 @@ class CommandSQL(Command):
         allConstraints = []
         for cls in classes:
             if self.options.verbose >= 1:
-                print '-- %s from %s' % (
-                    cls.__name__, cls.__module__)
+                print('-- %s from %s' % (
+                    cls.__name__, cls.__module__))
             createSql, constraints = cls.createTableSQL()
-            print createSql.strip() + ';\n'
+            print(createSql.strip() + ';\n')
             allConstraints.append(constraints)
         for constraints in allConstraints:
             if constraints:
                 for constraint in constraints:
                     if constraint:
-                        print constraint.strip() + ';\n'
+                        print(constraint.strip() + ';\n')
 
 
 class CommandList(Command):
@@ -603,12 +600,12 @@ class CommandList(Command):
 
     def command(self):
         if self.options.verbose >= 1:
-            print 'Classes found:'
+            print('Classes found:')
         classes = self.classes(require_connection=False)
         for soClass in classes:
-            print '%s.%s' % (soClass.__module__, soClass.__name__)
+            print('%s.%s' % (soClass.__module__, soClass.__name__))
             if self.options.verbose >= 1:
-                print '  Table: %s' % soClass.sqlmeta.table
+                print('  Table: %s' % soClass.sqlmeta.table)
 
 class CommandCreate(Command):
 
@@ -633,26 +630,26 @@ class CommandCreate(Command):
                 if not self.options.simulate:
                     try:
                         soClass._connection.createEmptyDatabase()
-                    except soClass._connection.module.ProgrammingError, e:
+                    except soClass._connection.module.ProgrammingError as e:
                         if str(e).find('already exists') != -1:
-                            print 'Database already exists'
+                            print('Database already exists')
                         else:
                             raise
                 else:
-                    print '(simulating; cannot create database)'
+                    print('(simulating; cannot create database)')
                 dbs_created.append(soClass._connection)
-            if soClass._connection not in constraints.keys():
+            if soClass._connection not in list(constraints.keys()):
                 constraints[soClass._connection] = []
             exists = soClass._connection.tableExists(soClass.sqlmeta.table)
             if v >= 1:
                 if exists:
                     existing += 1
-                    print '%s already exists.' % soClass.__name__
+                    print('%s already exists.' % soClass.__name__)
                 else:
-                    print 'Creating %s' % soClass.__name__
+                    print('Creating %s' % soClass.__name__)
             if v >= 2:
                 sql, extra = soClass.createTableSQL()
-                print sql
+                print(sql)
             if (not self.options.simulate
                 and not exists):
                 if self.options.interactive:
@@ -662,22 +659,22 @@ class CommandCreate(Command):
                         if tableConstraints:
                             constraints[soClass._connection].append(tableConstraints)
                     else:
-                        print 'Cancelled'
+                        print('Cancelled')
                 else:
                     created += 1
                     tableConstraints = soClass.createTable(applyConstraints=False)
                     if tableConstraints:
                         constraints[soClass._connection].append(tableConstraints)
-        for connection in constraints.keys():
+        for connection in list(constraints.keys()):
             if v >= 2:
-                print 'Creating constraints'
+                print('Creating constraints')
             for constraintList in constraints[connection]:
                 for constraint in constraintList:
                     if constraint:
                         connection.query(constraint)
         if v >= 1:
-            print '%i tables created (%i already exist)' % (
-                created, existing)
+            print('%i tables created (%i already exist)' % (
+                created, existing))
 
 
 class CommandDrop(Command):
@@ -695,10 +692,10 @@ class CommandDrop(Command):
             exists = soClass._connection.tableExists(soClass.sqlmeta.table)
             if v >= 1:
                 if exists:
-                    print 'Dropping %s' % soClass.__name__
+                    print('Dropping %s' % soClass.__name__)
                 else:
                     not_existing += 1
-                    print '%s does not exist.' % soClass.__name__
+                    print('%s does not exist.' % soClass.__name__)
             if (not self.options.simulate
                 and exists):
                 if self.options.interactive:
@@ -706,13 +703,13 @@ class CommandDrop(Command):
                         dropped += 1
                         soClass.dropTable()
                     else:
-                        print 'Cancelled'
+                        print('Cancelled')
                 else:
                     dropped += 1
                     soClass.dropTable()
         if v >= 1:
-            print '%i tables dropped (%i didn\'t exist)' % (
-                dropped, not_existing)
+            print('%i tables dropped (%i didn\'t exist)' % (
+                dropped, not_existing))
 
 class CommandStatus(Command):
 
@@ -730,7 +727,7 @@ class CommandStatus(Command):
         if self.printed:
             return
         self.printed = True
-        print 'Checking %s...' % soClass.__name__
+        print('Checking %s...' % soClass.__name__)
 
     def command(self):
         good = 0
@@ -744,7 +741,7 @@ class CommandStatus(Command):
                 self.print_class(soClass)
             if not conn.tableExists(soClass.sqlmeta.table):
                 self.print_class(soClass)
-                print '  Does not exist in database'
+                print('  Does not exist in database')
                 missing_tables += 1
                 continue
             try:
@@ -752,13 +749,13 @@ class CommandStatus(Command):
                                                  soClass)
             except AttributeError:
                 if not columnsFromSchema_warning:
-                    print 'Database does not support reading columns'
+                    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)
+            except AssertionError as e:
+                print('Cannot read db table %s: %s' % (
+                    soClass.sqlmeta.table, e))
                 continue
             existing = {}
             for col in columns:
@@ -772,19 +769,19 @@ class CommandStatus(Command):
                     missing[col.dbName] = col
             if existing:
                 self.print_class(soClass)
-                for col in existing.values():
-                    print '  Database has extra column: %s' % col.dbName
+                for col in list(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
+                for col in list(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)
+            print('%i in sync; %i out of sync; %i not in database' % (
+                good, bad, missing_tables))
 
 class CommandHelp(Command):
 
@@ -799,20 +796,20 @@ class CommandHelp(Command):
         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()
+            print('Available commands:')
+            print('  (use "%s help COMMAND" or "%s COMMAND -h" ' % (
+                self.prog_name, self.prog_name))
+            print('  for more information)')
+            items = list(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,
+                print('%s:%s %s' % (command_name,
                                     ' '*(max_len-len(command_name)),
-                                    command.summary)
+                                    command.summary))
                 if command.aliases:
-                    print '%s (Aliases: %s)' % (
-                        ' '*max_len, ', '.join(command.aliases))
+                    print('%s (Aliases: %s)' % (
+                        ' '*max_len, ', '.join(command.aliases)))
 
 class CommandExecute(Command):
 
@@ -834,7 +831,7 @@ class CommandExecute(Command):
         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)..."
+                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()
@@ -843,22 +840,22 @@ class CommandExecute(Command):
 
     def execute_sql(self, sql):
         if self.options.verbose:
-            print sql
+            print(sql)
         try:
             self.cursor.execute(sql)
-        except Exception, e:
+        except Exception as e:
             if not self.options.verbose:
-                print sql
-            print "****Error:"
-            print '    ', e
+                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"
+                print("No rows accessed")
             else:
-                print "%i rows accessed" % self.cursor.rowcount
+                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)
@@ -867,7 +864,7 @@ class CommandExecute(Command):
             for col in row:
                 sys.stdout.write("%r\t" % col)
             sys.stdout.write("\n")
-        print
+        print()
 
 class CommandRecord(Command):
 
@@ -928,12 +925,12 @@ class CommandRecord(Command):
         sim = self.options.simulate
         classes = self.classes()
         if not classes:
-            print "No classes found!"
+            print("No classes found!")
             return
 
         output_dir = self.find_output_dir()
         version = os.path.basename(output_dir)
-        print "Creating version %s" % version
+        print("Creating version %s" % version)
         conns = []
         files = {}
         for cls in self.classes():
@@ -963,14 +960,14 @@ class CommandRecord(Command):
         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
+                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 fn in files_copy:
                     if v > 1:
-                        print "Missing file %s" % fn
+                        print("Missing file %s" % fn)
                     break
                 f = open(os.path.join(last_version_dir, fn), 'r')
                 content = f.read()
@@ -978,32 +975,32 @@ class CommandRecord(Command):
                 if (self.strip_comments(files_copy[fn])
                     != self.strip_comments(content)):
                     if v > 1:
-                        print "Content does not match: %s" % fn
+                        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))
+                    print(("Current status matches version %s"
+                           % os.path.basename(last_version_dir)))
                     return
                 if v > 1:
-                    print "Extra files: %s" % ', '.join(files_copy.keys())
+                    print("Extra files: %s" % ', '.join(list(files_copy.keys())))
             if v:
-                print ("Current state does not match %s"
-                       % os.path.basename(last_version_dir))
+                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"
+            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()
+            print('Making directory %s' % self.shorten_filename(output_dir))
+        files = list(files.items())
         files.sort()
         for fn, content in files:
             if v:
-                print '  Writing %s' % self.shorten_filename(fn)
+                print('  Writing %s' % self.shorten_filename(fn))
             if not sim:
                 f = open(os.path.join(output_dir, fn), 'w')
                 f.write(content)
@@ -1021,8 +1018,8 @@ class CommandRecord(Command):
                             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)
+                print('Database does not match schema:')
+                print('\n'.join(all_diffs))
                 for conn in conns:
                     self.update_db(version, conn)
         else:
@@ -1044,17 +1041,17 @@ class CommandRecord(Command):
                     f = open(fn, 'w')
                     f.write(text)
                     f.close()
-                    print 'Wrote to %s' % fn
+                    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)
+                print(('Creating table %s'
+                       % SQLObjectVersionTable.sqlmeta.table))
             sql = SQLObjectVersionTable.createTableSQL(connection=conn)
             if v > 1:
-                print sql
+                print(sql)
             if not self.options.simulate:
                 SQLObjectVersionTable.createTable(connection=conn)
         if not self.options.simulate:
@@ -1073,7 +1070,7 @@ class CommandRecord(Command):
         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)
+            print('Creating history directory %s' % self.shorten_filename(base))
             if not self.options.simulate:
                 os.makedirs(base)
         return base
@@ -1084,8 +1081,8 @@ class CommandRecord(Command):
             dir = os.path.join(self.base_dir(), today + '-' +
                                self.options.version_name)
             if os.path.exists(dir):
-                print ("Error, directory already exists: %s"
-                       % dir)
+                print(("Error, directory already exists: %s"
+                       % dir))
                 sys.exit(1)
             return dir
         extra = ''
@@ -1114,18 +1111,18 @@ class CommandRecord(Command):
         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
+            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)
+                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))
+            print(('Directory %s exists'
+                   % self.shorten_filename(version_dir)))
         if self.options.db_record:
             self.update_db(version, self.connection())
 
@@ -1162,51 +1159,51 @@ class CommandUpgrade(CommandRecord):
         else:
             fname = self.find_last_version()
             if fname is None:
-                print "No version exists, use 'record' command to create one"
+                print("No version exists, use 'record' command to create one")
                 return
             version_to = os.path.basename(fname)
         current = self.current_version()
         if v:
-            print 'Current version: %s' % current
+            print('Current version: %s' % current)
         version_list = self.make_plan(current, version_to)
         if not version_list:
-            print 'Database up to date'
+            print('Database up to date')
             return
         if v:
-            print 'Plan:'
+            print('Plan:')
             for next_version, upgrader in version_list:
-                print '  Use %s to upgrade to %s' % (
-                    self.shorten_filename(upgrader), next_version)
+                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
+                print("Running:")
+                print(sql)
+                print('-'*60)
             if not sim:
                 try:
                     conn.query(sql)
                 except:
-                    print "Error in script: %s" % upgrader
+                    print("Error in script: %s" % upgrader)
                     raise
             self.update_db(next_version, conn)
-        print 'Done.'
+        print('Done.')
 
 
     def current_version(self):
         conn = self.connection()
         if not conn.tableExists(SQLObjectVersionTable.sqlmeta.table):
-            print 'No sqlobject_version table!'
+            print('No sqlobject_version table!')
             sys.exit(1)
         versions = list(SQLObjectVersionTable.select(connection=conn))
         if not versions:
-            print 'No rows in sqlobject_version!'
+            print('No rows in sqlobject_version!')
             sys.exit(1)
         if len(versions) > 1:
-            print 'Ambiguous sqlobject_version_table'
+            print('Ambiguous sqlobject_version_table')
             sys.exit(1)
         return versions[0].version
 
@@ -1216,9 +1213,9 @@ class CommandUpgrade(CommandRecord):
         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))
+            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:
@@ -1229,42 +1226,42 @@ class CommandUpgrade(CommandRecord):
     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))
+            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
+                    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)
+                    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)
+                    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
+                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, basestring):
+    if isinstance(paths, str):
         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
+                print('Adding %s to path' % path)
             sys.path.insert(0, path)
 
 if __name__ == '__main__':
--- sqlobject/maxdb/maxdbconnection.py.orig	2022-03-15 19:15:16 UTC
+++ sqlobject/maxdb/maxdbconnection.py
@@ -246,7 +246,7 @@ class MaxdbConnection(DBAPI):
                 pkmap[col_name]=True
 
         if len(pkmap) == 0:
-            raise PrimaryKeyNotFounded, tableName
+            raise PrimaryKeyNotFounded(tableName)
 
         for (field, nullAllowed, default, data_type, data_len,
              data_scale) in colData:
--- sqlobject/mysql/mysqlconnection.py.orig	2011-05-08 15:49:57 UTC
+++ sqlobject/mysql/mysqlconnection.py
@@ -69,7 +69,7 @@ class MySQLConnection(DBAPI):
                 db=self.db, user=self.user, passwd=self.password, **self.kw)
             if self.module.version_info[:3] >= (1, 2, 2):
                 conn.ping(True) # Attempt to reconnect. This setting is persistent.
-        except self.module.OperationalError, e:
+        except self.module.OperationalError as e:
             conninfo = "; used connection string: host=%(host)s, port=%(port)s, db=%(db)s, user=%(user)s" % self.__dict__
             raise OperationalError(ErrorMessage(e, conninfo))
 
@@ -90,9 +90,9 @@ class MySQLConnection(DBAPI):
             conn.autocommit(auto)
 
     def _executeRetry(self, conn, cursor, query):
-        if self.need_unicode and not isinstance(query, unicode):
+        if self.need_unicode and not isinstance(query, str):
             try:
-                query = unicode(query, self.dbEncoding)
+                query = str(query, self.dbEncoding)
             except UnicodeError:
                 pass
 
@@ -111,7 +111,7 @@ class MySQLConnection(DBAPI):
         for count in range(3):
             try:
                 return cursor.execute(query)
-            except self.module.OperationalError, e:
+            except self.module.OperationalError as e:
                 if e.args[0] in (self.module.constants.CR.SERVER_GONE_ERROR, self.module.constants.CR.SERVER_LOST):
                     if count == 2:
                         raise OperationalError(ErrorMessage(e))
@@ -119,27 +119,27 @@ class MySQLConnection(DBAPI):
                         self.printDebug(conn, str(e), 'ERROR')
                 else:
                     raise OperationalError(ErrorMessage(e))
-            except self.module.IntegrityError, e:
+            except self.module.IntegrityError as e:
                 msg = ErrorMessage(e)
                 if e.args[0] == self.module.constants.ER.DUP_ENTRY:
                     raise DuplicateEntryError(msg)
                 else:
                     raise IntegrityError(msg)
-            except self.module.InternalError, e:
+            except self.module.InternalError as e:
                 raise InternalError(ErrorMessage(e))
-            except self.module.ProgrammingError, e:
+            except self.module.ProgrammingError as e:
                 raise ProgrammingError(ErrorMessage(e))
-            except self.module.DataError, e:
+            except self.module.DataError as e:
                 raise DataError(ErrorMessage(e))
-            except self.module.NotSupportedError, e:
+            except self.module.NotSupportedError as e:
                 raise NotSupportedError(ErrorMessage(e))
-            except self.module.DatabaseError, e:
+            except self.module.DatabaseError as e:
                 raise DatabaseError(ErrorMessage(e))
-            except self.module.InterfaceError, e:
+            except self.module.InterfaceError as e:
                 raise InterfaceError(ErrorMessage(e))
-            except self.module.Warning, e:
+            except self.module.Warning as e:
                 raise Warning(ErrorMessage(e))
-            except self.module.Error, e:
+            except self.module.Error as e:
                 raise Error(ErrorMessage(e))
 
     def _queryInsertID(self, conn, soInstance, id, names, values):
@@ -194,7 +194,7 @@ class MySQLConnection(DBAPI):
             # which is not always True (for an embedded application, e.g.)
             self.query('DESCRIBE %s' % (tableName))
             return True
-        except ProgrammingError, e:
+        except ProgrammingError as e:
             if e[0].code == 1146: # ER_NO_SUCH_TABLE
                 return False
             raise
--- sqlobject/postgres/pgconnection.py.orig	2013-09-30 14:25:11 UTC
+++ sqlobject/postgres/pgconnection.py
@@ -142,7 +142,7 @@ class PostgresConnection(DBAPI):
                 conn = self.module.connect(self.dsn)
             else:
                 conn = self.module.connect(**self.dsn_dict)
-        except self.module.OperationalError, e:
+        except self.module.OperationalError as e:
             raise OperationalError(ErrorMessage(e, "used connection string %r" % self.dsn))
 
         # For printDebug in _executeRetry
@@ -162,29 +162,29 @@ class PostgresConnection(DBAPI):
             self.printDebug(conn, query, 'QueryR')
         try:
             return cursor.execute(query)
-        except self.module.OperationalError, e:
+        except self.module.OperationalError as e:
             raise OperationalError(ErrorMessage(e))
-        except self.module.IntegrityError, e:
+        except self.module.IntegrityError as e:
             msg = ErrorMessage(e)
             if e.pgcode == '23505':
                 raise DuplicateEntryError(msg)
             else:
                 raise IntegrityError(msg)
-        except self.module.InternalError, e:
+        except self.module.InternalError as e:
             raise InternalError(ErrorMessage(e))
-        except self.module.ProgrammingError, e:
+        except self.module.ProgrammingError as e:
             raise ProgrammingError(ErrorMessage(e))
-        except self.module.DataError, e:
+        except self.module.DataError as e:
             raise DataError(ErrorMessage(e))
-        except self.module.NotSupportedError, e:
+        except self.module.NotSupportedError as e:
             raise NotSupportedError(ErrorMessage(e))
-        except self.module.DatabaseError, e:
+        except self.module.DatabaseError as e:
             raise DatabaseError(ErrorMessage(e))
-        except self.module.InterfaceError, e:
+        except self.module.InterfaceError as e:
             raise InterfaceError(ErrorMessage(e))
-        except self.module.Warning, e:
+        except self.module.Warning as e:
             raise Warning(ErrorMessage(e))
-        except self.module.Error, e:
+        except self.module.Error as e:
             raise Error(ErrorMessage(e))
 
     def _queryInsertID(self, conn, soInstance, id, names, values):
--- sqlobject/sqlbuilder.py.orig	2013-10-05 12:02:45 UTC
+++ sqlobject/sqlbuilder.py
@@ -67,8 +67,8 @@ import threading
 import types
 import weakref
 
-import classregistry
-from converters import registerConverter, sqlrepr, quote_str, unquote_str
+from . import classregistry
+from .converters import registerConverter, sqlrepr, quote_str, unquote_str
 
 
 class VersionError(Exception):
@@ -86,7 +86,7 @@ class SQLObjectState(object):
 safeSQLRE = re.compile(r'^[a-zA-Z_][a-zA-Z0-9_\.]*$')
 def sqlIdentifier(obj):
     # some db drivers return unicode column names
-    return isinstance(obj, basestring) and bool(safeSQLRE.search(obj.strip()))
+    return isinstance(obj, str) and bool(safeSQLRE.search(obj.strip()))
 
 
 def execute(expr, executor):
@@ -97,7 +97,7 @@ def execute(expr, executor):
 
 
 def _str_or_sqlrepr(expr, db):
-    if isinstance(expr, basestring):
+    if isinstance(expr, str):
         return expr
     return sqlrepr(expr, db)
 
@@ -181,9 +181,9 @@ class SQLExpression:
         return repr(self)
 
     def __cmp__(self, other):
-        raise VersionError, "Python 2.1+ required"
+        raise VersionError("Python 2.1+ required")
     def __rcmp__(self, other):
-        raise VersionError, "Python 2.1+ required"
+        raise VersionError("Python 2.1+ required")
 
     def startswith(self, s):
         return STARTSWITH(self, s)
@@ -287,7 +287,7 @@ class SQLCall(SQLExpression):
     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"
+        raise ValueError("I don't yet know how to locally execute functions")
 
 registerConverter(SQLCall, SQLExprConverter)
 
@@ -316,7 +316,7 @@ class SQLConstant(SQLExpression):
     def __sqlrepr__(self, db):
         return self.const
     def execute(self, executor):
-        raise ValueError, "I don't yet know how to execute SQL constants"
+        raise ValueError("I don't yet know how to execute SQL constants")
 
 registerConverter(SQLConstant, SQLExprConverter)
 
@@ -391,7 +391,7 @@ class Table(SQLExpression):
     def __sqlrepr__(self, db):
         return _str_or_sqlrepr(self.tableName, db)
     def execute(self, executor):
-        raise ValueError, "Tables don't have values"
+        raise ValueError("Tables don't have values")
 
 class SQLObjectTable(Table):
     FieldClass = SQLObjectField
@@ -411,7 +411,7 @@ class SQLObjectTable(Table):
         elif attr in self.soClass.sqlmeta.columns:
             column = self.soClass.sqlmeta.columns[attr]
             return self._getattrFromColumn(column, attr)
-        elif attr+'ID' in [k for (k, v) in self.soClass.sqlmeta.columns.items() if v.foreignKey]:
+        elif attr+'ID' in [k for (k, v) in list(self.soClass.sqlmeta.columns.items()) if v.foreignKey]:
             attr += 'ID'
             column = self.soClass.sqlmeta.columns[attr]
             return self._getattrFromColumn(column, attr)
@@ -427,7 +427,7 @@ class SQLObjectTable(Table):
 class SQLObjectTableWithJoins(SQLObjectTable):
 
     def __getattr__(self, attr):
-        if attr+'ID' in [k for (k, v) in self.soClass.sqlmeta.columns.items() if v.foreignKey]:
+        if attr+'ID' in [k for (k, v) in list(self.soClass.sqlmeta.columns.items()) if v.foreignKey]:
             column = self.soClass.sqlmeta.columns[attr+'ID']
             return self._getattrFromForeignKey(column, attr)
         elif attr in [x.joinMethodName for x in self.soClass.sqlmeta.joins]:
@@ -616,7 +616,7 @@ class Select(SQLExpression):
             # None doesn't filter anything, it's just a no-op:
             return self
         clause = self.ops['clause']
-        if isinstance(clause, basestring):
+        if isinstance(clause, str):
             clause = SQLConstant('(%s)' % clause)
         return self.newClause(AND(clause, filter_clause))
 
@@ -697,7 +697,7 @@ class Select(SQLExpression):
         if self.ops['limit'] is not NoDefault:
             end = start + self.ops['limit']
         if start or end:
-            from dbconnection import dbConnectionForScheme
+            from .dbconnection import dbConnectionForScheme
             select = dbConnectionForScheme(db)._queryAddLimitOffset(select, start, end)
         if self.ops['forUpdate']:
             select += " FOR UPDATE"
@@ -711,7 +711,7 @@ class Insert(SQLExpression):
         self.table = table
         if valueList:
             if values:
-                raise TypeError, "You may only give valueList *or* values"
+                raise TypeError("You may only give valueList *or* values")
             self.valueList = valueList
         else:
             self.valueList = [values]
@@ -722,7 +722,7 @@ class Insert(SQLExpression):
         allowNonDict = True
         template = self.template
         if (template is NoDefault) and isinstance(self.valueList[0], dict):
-            template = self.valueList[0].keys()
+            template = list(self.valueList[0].keys())
             allowNonDict = False
         if template is not NoDefault:
             insert += " (%s)" % ", ".join(template)
@@ -732,10 +732,10 @@ class Insert(SQLExpression):
         for value in self.valueList:
             if isinstance(value, dict):
                 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)
+                    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)
+                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
@@ -746,8 +746,8 @@ 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))
+    if len(list(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):
@@ -768,7 +768,7 @@ class Update(SQLExpression):
                     update += ","
                 update += " %s=%s" % (self.template[i], sqlrepr(self.values[i], db))
         else:
-            for key, value in self.values.items():
+            for key, value in list(self.values.items()):
                 if first:
                     first = False
                 else:
@@ -788,7 +788,7 @@ class Delete(SQLExpression):
     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"
+            raise TypeError("You must give a where clause or pass in None to indicate no where clause")
         self.whereClause = where
     def __sqlrepr__(self, db):
         whereClause = self.whereClause
@@ -846,7 +846,7 @@ def _IN(item, list):
     return SQLOp("IN", item, list)
 
 def IN(item, list):
-    from sresults import SelectResults # Import here to avoid circular import
+    from .sresults import SelectResults # Import here to avoid circular import
     if isinstance(list, SelectResults):
         query = list.queryForSelect()
         query.ops['items'] = [list.sourceClass.q.id]
@@ -880,7 +880,7 @@ def ISNOTNULL(expr):
 class ColumnAS(SQLOp):
     ''' Just like SQLOp('AS', expr, name) except without the parentheses '''
     def __init__(self, expr, name):
-        if isinstance(name, basestring):
+        if isinstance(name, str):
             name = SQLConstant(name)
         SQLOp.__init__(self, 'AS', expr, name)
     def __sqlrepr__(self, db):
@@ -919,11 +919,11 @@ class _LikeQuoted:
                 return "CONCAT(%s)" % ", ".join(values)
             else:
                 return " || ".join(values)
-        elif isinstance(s, basestring):
+        elif isinstance(s, str):
             s = _quote_like_special(unquote_str(sqlrepr(s, db)), db)
             return quote_str("%s%s%s" % (self.prefix, s, self.postfix), db)
         else:
-           raise TypeError, "expected str, unicode or SQLExpression, got %s" % type(s)
+           raise TypeError("expected str, unicode or SQLExpression, got %s" % type(s))
 
 def _quote_like_special(s, db):
     if db in ('postgres', 'rdbhost'):
@@ -1021,9 +1021,9 @@ class SQLJoinConditional(SQLJoin):
                 (Table1.q.col1, Table2.q.col2)
         """
         if not on_condition and not using_columns:
-            raise TypeError, "You must give ON condition or 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"
+            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
@@ -1254,7 +1254,7 @@ class ImportProxy(SQLExpression):
         self.soClass = None
         classregistry.registry(registry).addClassCallback(clsName, lambda foreign, me: setattr(me, 'soClass', foreign), self)
 
-    def __nonzero__(self):
+    def __bool__(self):
         return True
 
     def __getattr__(self, attr):
--- sqlobject/sqlite/sqliteconnection.py.orig	2014-04-12 20:42:31 UTC
+++ sqlobject/sqlite/sqliteconnection.py
@@ -1,7 +1,7 @@
 import base64
 import os
-import thread
-import urllib
+import _thread
+import urllib.request, urllib.parse, urllib.error
 from sqlobject.dbconnection import DBAPI, Boolean
 from sqlobject import col, sqlbuilder
 from sqlobject.dberrors import *
@@ -121,7 +121,7 @@ class SQLiteConnection(DBAPI):
                 path = "//" + path
             else:
                 path = "///" + path
-            path = urllib.quote(path)
+            path = urllib.parse.quote(path)
         return 'sqlite:%s' % path
 
     def getConnection(self):
@@ -133,7 +133,7 @@ class SQLiteConnection(DBAPI):
             self._connectionNumbers[id(conn)] = self._connectionCount
             self._connectionCount += 1
             return conn
-        threadid = thread.get_ident()
+        threadid = _thread.get_ident()
         if (self._pool is not None
             and threadid in self._threadPool):
             conn = self._threadPool[threadid]
@@ -206,30 +206,30 @@ class SQLiteConnection(DBAPI):
             self.printDebug(conn, query, 'QueryR')
         try:
             return cursor.execute(query)
-        except self.module.OperationalError, e:
+        except self.module.OperationalError as e:
             raise OperationalError(ErrorMessage(e))
-        except self.module.IntegrityError, e:
+        except self.module.IntegrityError as e:
             msg = ErrorMessage(e)
             if msg.startswith('column') and msg.endswith('not unique') \
             or msg.startswith('UNIQUE constraint failed:'):
                 raise DuplicateEntryError(msg)
             else:
                 raise IntegrityError(msg)
-        except self.module.InternalError, e:
+        except self.module.InternalError as e:
             raise InternalError(ErrorMessage(e))
-        except self.module.ProgrammingError, e:
+        except self.module.ProgrammingError as e:
             raise ProgrammingError(ErrorMessage(e))
-        except self.module.DataError, e:
+        except self.module.DataError as e:
             raise DataError(ErrorMessage(e))
-        except self.module.NotSupportedError, e:
+        except self.module.NotSupportedError as e:
             raise NotSupportedError(ErrorMessage(e))
-        except self.module.DatabaseError, e:
+        except self.module.DatabaseError as e:
             raise DatabaseError(ErrorMessage(e))
-        except self.module.InterfaceError, e:
+        except self.module.InterfaceError as e:
             raise InterfaceError(ErrorMessage(e))
-        except self.module.Warning, e:
+        except self.module.Warning as e:
             raise Warning(ErrorMessage(e))
-        except self.module.Error, e:
+        except self.module.Error as e:
             raise Error(ErrorMessage(e))
 
     def _queryInsertID(self, conn, soInstance, id, names, values):
--- sqlobject/util/moduleloader.py.orig	2011-05-15 15:48:27 UTC
+++ sqlobject/util/moduleloader.py
@@ -15,7 +15,7 @@ def load_module_from_name(filename, module_name):
     if not os.path.exists(init_filename):
         try:
             f = open(init_filename, 'w')
-        except (OSError, IOError), e:
+        except (OSError, IOError) as e:
             raise IOError(
                 'Cannot write __init__.py file into directory %s (%s)\n'
                 % (os.path.dirname(filename), e))