diff options
author | Po-Chuan Hsieh <sunpoet@FreeBSD.org> | 2022-03-25 21:32:07 +0800 |
---|---|---|
committer | Po-Chuan Hsieh <sunpoet@FreeBSD.org> | 2022-03-25 21:38:06 +0800 |
commit | b117f7f8f7723515ea1f847cd66293719ce324bf (patch) | |
tree | b5b1b84c349cbea1443e80ea11f5a2592ff62d30 /databases/py-sqlobject/files/patch-2to3 | |
parent | databases/py-motor: Fix build with setuptools 58.0.0+ (diff) |
databases/py-sqlobject: Fix build with setuptools 58.0.0+
With hat: python
Diffstat (limited to 'databases/py-sqlobject/files/patch-2to3')
-rw-r--r-- | databases/py-sqlobject/files/patch-2to3 | 2505 |
1 files changed, 2505 insertions, 0 deletions
diff --git a/databases/py-sqlobject/files/patch-2to3 b/databases/py-sqlobject/files/patch-2to3 new file mode 100644 index 000000000000..66193d081e4a --- /dev/null +++ b/databases/py-sqlobject/files/patch-2to3 @@ -0,0 +1,2505 @@ +--- 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)) |