diff --git a/.travis.yml b/.travis.yml index 1afe312..3139144 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,8 @@ language: python python: - "2.7" + - "3.3" + - "3.4" install: - pip install -e . --use-mirrors - pip install coveralls --use-mirrors diff --git a/ipydb/__init__.py b/ipydb/__init__.py index 71d8ece..5de8468 100644 --- a/ipydb/__init__.py +++ b/ipydb/__init__.py @@ -12,15 +12,17 @@ :copyright: (c) 2012 by Jay Sweeney. :license: see LICENSE for more details. """ +from __future__ import print_function + +import logging +import os + __title__ = 'ipydb' __version__ = '0.0.2' __author__ = 'Jay Sweeney' __license__ = 'Apache 2.0' __copyright__ = 'Copyright 2012 Jay Sweeney' -import logging -import os - PLUGIN_NAME = 'ipydb' _loaded = False _backup_prompt1 = '' @@ -29,7 +31,7 @@ def load_ipython_extension(ip): """Load the ipydb into the active ipython session""" - from plugin import SqlPlugin + from .plugin import SqlPlugin global _loaded if not _loaded: plugin = SqlPlugin(shell=ip, config=ip.config) @@ -60,34 +62,34 @@ def configure_prompt(ipydb): def ipydb_help(): - msg = "Welcome to ipydb %s!" % __version__ - print msg - print - msg2 = 'ipydb has added the following `magic` ' \ + msg = u"Welcome to ipydb %s!" % __version__ + print(msg) + print() + msg2 = u'ipydb has added the following `magic` ' \ 'commands to your ipython session:' - print msg2 + print(msg2) helps = get_brief_help() maxname = max(map(len, (r[0] for r in helps))) - print '-' * (maxname + 5) + print('-' * (maxname + 5)) for magic, doc in helps: - print (" %%%-" + str(maxname) + "s %s") % (magic, doc) - print '-' * (maxname + 5) - print - print "You can get detailed usage information " \ - "for any of the above commands " - print "by typing %magic_command_name? For example, " \ - "to get help on %connect, type" - print - print " %connect?" - print - print "Get started by connecting to a database " \ - "using %connect_url or %connect" + print((u" %%%-" + str(maxname) + "s %s") % (magic, doc)) + print('-' * (maxname + 5)) + print() + print("You can get detailed usage information " + "for any of the above commands ") + print("by typing %magic_command_name? For example, " + "to get help on %connect, type") + print() + print(" %connect?") + print() + print("Get started by connecting to a database " + "using %connect_url or %connect") def get_brief_help(): """return a list of (magic_name, first_line_of_docstring) for all the magic methods ipydb defines""" - from magic import SqlMagics + from .magic import SqlMagics docs = [] magics = {} magic_thing = SqlMagics.magics diff --git a/ipydb/asciitable.py b/ipydb/asciitable.py index ead411c..9e1add6 100644 --- a/ipydb/asciitable.py +++ b/ipydb/asciitable.py @@ -1,10 +1,14 @@ # -*- coding: utf-8 -*- +from future.standard_library import install_aliases +install_aliases() """Draw ascii tables.""" import itertools import sys -from utils import termsize +from past.builtins import basestring + +from .utils import termsize class FakedResult(object): @@ -39,7 +43,7 @@ def keys(self): def isublists(l, n): - return itertools.izip_longest(*[iter(l)] * n) + return itertools.zip_longest(*[iter(l)] * n) def draw(cursor, out=sys.stdout, paginate=True, max_fieldsize=100): @@ -58,15 +62,15 @@ def draw(cursor, out=sys.stdout, paginate=True, max_fieldsize=100): def heading_line(sizes): for size in sizes: - out.write('+' + '-' * (size + 2)) - out.write('+\n') + out.write(u'+' + '-' * (size + 2)) + out.write(u'+\n') def draw_headings(headings, sizes): heading_line(sizes) for idx, size in enumerate(sizes): - fmt = '| %%-%is ' % size + fmt = u'| %%-%is ' % size out.write((fmt % headings[idx])) - out.write('|\n') + out.write(u'|\n') heading_line(sizes) cols, lines = termsize() @@ -76,7 +80,7 @@ def draw_headings(headings, sizes): cursor = isublists(cursor, lines - 4) # else we assume cursor arrive here pre-paginated for screenrows in cursor: - sizes = heading_sizes[:] + sizes = list(heading_sizes) for row in screenrows: if row is None: break @@ -90,7 +94,7 @@ def draw_headings(headings, sizes): if rw is None: break # from isublists impl for idx, size in enumerate(sizes): - fmt = '| %%-%is ' % size + fmt = u'| %%-%is ' % size value = rw[idx] if not isinstance(value, basestring): value = str(value) @@ -99,12 +103,8 @@ def draw_headings(headings, sizes): value = value.replace('\n', '^') value = value.replace('\r', '^').replace('\t', ' ') value = fmt % value - try: - value = value.encode('utf-8', 'replace') - except UnicodeDecodeError: - value = fmt % '?' out.write(value) - out.write('|\n') + out.write(u'|\n') if not paginate: heading_line(sizes) - out.write('\n') + out.write(u'\n') diff --git a/ipydb/completion.py b/ipydb/completion.py index d4803ad..ce4a0e4 100644 --- a/ipydb/completion.py +++ b/ipydb/completion.py @@ -4,6 +4,7 @@ This module provides functionality for readline-style tab-completion of SQL statements and other ipydb commands. """ +from __future__ import print_function import itertools import logging import re @@ -38,14 +39,14 @@ def ipydb_complete(self, event): try: if sqlplugin: if sqlplugin.debug: - print 'complete: sym=[%s] line=[%s] tuc=[%s]' % ( - event.symbol, event.line, event.text_until_cursor) + print('complete: sym=[%s] line=[%s] tuc=[%s]' % ( + event.symbol, event.line, event.text_until_cursor)) completions = sqlplugin.completer.complete(event) if sqlplugin.debug: - print 'completions:', completions + print('completions:', completions) return completions - except Exception, e: - print repr(e) + except Exception as e: + print(repr(e)) if sqlplugin and sqlplugin.debug: import traceback traceback.print_exc() @@ -215,7 +216,7 @@ def expand_join_expression(self, expr): for tbl in reversed(tables): joins = self.db.get_joins(tbl, tail) if joins: - join = iter(joins).next() # XXX: take a punt + join = next(iter(joins)) # XXX: take a punt joinstr = 'inner join %s on ' % (tail) sep = '' for idx, col in enumerate(join.columns): diff --git a/ipydb/engine.py b/ipydb/engine.py index 8291469..9cac5e8 100644 --- a/ipydb/engine.py +++ b/ipydb/engine.py @@ -2,8 +2,11 @@ """Functions to help create an SQLalchemy connection based upon a 'connection configuration file'""" -import urlparse -from ConfigParser import ConfigParser, DuplicateSectionError +from future.standard_library import install_aliases +install_aliases() + +from urllib import parse +from configparser import ConfigParser, DuplicateSectionError import sqlalchemy as sa @@ -101,7 +104,7 @@ def make_connection_url(config): password=config.get('password'), host=config.get('host'), port=config.get('port') or None, database=config.get('database'), - query=dict(urlparse.parse_qsl(config.get('query', '')))) + query=dict(parse.parse_qsl(config.get('query', '')))) def save_connection(name, engine, overwrite=False): diff --git a/ipydb/magic.py b/ipydb/magic.py index 1d8d370..36585a6 100644 --- a/ipydb/magic.py +++ b/ipydb/magic.py @@ -6,6 +6,7 @@ :copyright: (c) 2012 by Jay Sweeney. :license: see LICENSE for more details. """ +from __future__ import print_function import logging from IPython.core.magic import Magics, magics_class, \ @@ -78,8 +79,8 @@ def set_reflection(self, arg): self.ipydb.do_reflection = False else: self.ipydb.do_reflection = True - print 'Schema reflection: %s' % ( - 'on' if self.ipydb.do_reflection else 'off') + print('Schema reflection: %s' % ( + 'on' if self.ipydb.do_reflection else 'off')) @line_magic def engine(self, arg): @@ -97,7 +98,7 @@ def debug(self, arg): self.ipydb.debug = True root_logger = logging.getLogger() root_logger.setLevel(logging.DEBUG) - print "ipydb debugging is", 'on' if self.ipydb.debug else 'off' + print("ipydb debugging is", 'on' if self.ipydb.debug else 'off') @line_magic def begin(self, arg): @@ -178,7 +179,7 @@ def sql(self, args='', cell=None): if args.ret: return sqlstr else: - print "\n%s" % sqlstr + print("\n%s" % sqlstr) return if args.params: params = self.shell.user_ns.get(args.params, {}) @@ -198,7 +199,7 @@ def sql(self, args='', cell=None): elif result and not result.returns_rows: # XXX: do all drivers support this? s = 's' if result.rowcount != 1 else '' - print "%i row%s affected" % (result.rowcount, s) + print("%i row%s affected" % (result.rowcount, s)) sql.__description__ = 'Run an sql statement against ' \ 'the current ipydb connection.' @@ -272,7 +273,7 @@ def showsql(self, param=''): level = logging.INFO self.ipydb.show_sql = True logging.getLogger('sqlalchemy.engine').setLevel(level) - print 'SQL logging %s' % ('on' if self.ipydb.show_sql else 'off') + print('SQL logging %s' % ('on' if self.ipydb.show_sql else 'off')) @line_magic def references(self, param=""): @@ -288,7 +289,7 @@ def references(self, param=""): : shows all fields having a foreign key referencing person.id """ if not param.strip() or len(param.split()) != 1: - print "Usage: %references TABLE_NAME[.FIELD_NAME]" + print("Usage: %references TABLE_NAME[.FIELD_NAME]") return self.ipydb.what_references(param) @@ -304,7 +305,7 @@ def joins(self, param=""): Usage: %joins TABLE_NAME """ if not param.strip() or len(param.split()) != 1: - print "Usage: %show_joins TABLE_NAME" + print("Usage: %show_joins TABLE_NAME") return self.ipydb.show_joins(param) @@ -315,7 +316,7 @@ def fks(self, param=""): Usage: %fks TABLE_NAME """ if not param.strip() or len(param.split()) != 1: - print "Usage: %show_fks TABLE_NAME" + print("Usage: %show_fks TABLE_NAME") return self.ipydb.show_fks(param) @@ -324,10 +325,10 @@ def sqlformat(self, param=None): """Change the output format.""" from ipydb.plugin import SQLFORMATS if not param or param not in SQLFORMATS: - print self.sqlformat.__doc__ + print(self.sqlformat.__doc__) else: self.ipydb.sqlformat = param - print "output format: %s" % self.ipydb.sqlformat + print("output format: %s" % self.ipydb.sqlformat) @line_magic def connect(self, param): @@ -393,7 +394,7 @@ def flushmetadata(self, arg): def rereflect(self, arg): """Force re-loading of completion metadata.""" if not self.ipydb.connected: - print self.ipydb.not_connected_message + print(self.ipydb.not_connected_message) return self.ipydb.metadata_accessor.get_metadata( self.ipydb.engine, force=True, noisy=True) @@ -411,10 +412,10 @@ def saveconnection(self, arg): with the current engine's connection parameters. """ if not self.ipydb.connected: - print self.ipydb.not_connected_message + print(self.ipydb.not_connected_message) return if not len(arg.strip()): - print "Usage: %saveconnection NICKNAME. \n\n" + \ - "Please supply a NICKNAME to store the connection against." + print("Usage: %saveconnection NICKNAME. \n\n" + "Please supply a NICKNAME to store the connection against.") return self.ipydb.save_connection(arg) diff --git a/ipydb/metadata/__init__.py b/ipydb/metadata/__init__.py index 1ed0d72..8b77c48 100644 --- a/ipydb/metadata/__init__.py +++ b/ipydb/metadata/__init__.py @@ -7,6 +7,7 @@ :copyright: (c) 2012 by Jay Sweeney. :license: see LICENSE for more details. """ +from __future__ import print_function import base64 from collections import defaultdict @@ -49,7 +50,7 @@ def get_metadata_engine(other_engine): if not os.path.exists(path): os.makedirs(path) dbfilename = get_db_filename(other_engine) - dburl = 'sqlite:////%s' % os.path.join(path, dbfilename) + dburl = u'sqlite:////%s' % os.path.join(path, dbfilename) return dbfilename, sa.create_engine(dburl) @@ -60,7 +61,7 @@ def get_db_filename(engine): url = engine.url url = str(URL(url.drivername, url.username, host=url.host, port=url.port, database=url.database)) - return base64.urlsafe_b64encode(url) + return str(base64.urlsafe_b64encode(url.encode('utf-8'))) @contextmanager @@ -126,7 +127,7 @@ def get_metadata(self, engine, noisy=False, force=False): db = self.read_expunge(ipydb_engine) self.databases[db_key] = db if noisy: - print "ipydb is fetching database metadata" + print("ipydb is fetching database metadata") self.spawn_reflection_thread(db_key, db, engine.url) return db if db.age > MAX_CACHE_AGE: @@ -140,7 +141,7 @@ def get_metadata(self, engine, noisy=False, force=False): # Spawn a thread to do the slow sqlalchemy reflection, # return whatever we have if noisy: - print "ipydb is fetching database metadata" + print("ipydb is fetching database metadata") self.spawn_reflection_thread(db_key, db, engine.url) return db diff --git a/ipydb/plugin.py b/ipydb/plugin.py index f3502c2..04569b1 100644 --- a/ipydb/plugin.py +++ b/ipydb/plugin.py @@ -6,7 +6,8 @@ :copyright: (c) 2012 by Jay Sweeney. :license: see LICENSE for more details. """ -from ConfigParser import DuplicateSectionError +from __future__ import print_function +from configparser import DuplicateSectionError import fnmatch import functools import logging @@ -38,7 +39,7 @@ def connected(f): @functools.wraps(f) def wrapper(plugin, *args, **kw): if not plugin.connected: - print plugin.not_connected_message + print(plugin.not_connected_message) return return f(plugin, *args, **kw) return wrapper @@ -184,9 +185,9 @@ def save_connection(self, configname): engine.save_connection( configname, self.engine, overwrite=True) else: - print "Save aborted" + print("Save aborted") return - print "`%s` saved to ~/.db-connections" % (configname,) + print("`%s` saved to ~/.db-connections" % (configname,)) def connect(self, configname=None): """Connect to a database based upon its `nickname`. @@ -197,13 +198,13 @@ def connect(self, configname=None): success = False def available(): - print self.connect.__doc__ - print "Available connection nicknames: %s" % ( - ' '.join(sorted(configs.keys()))) + print(self.connect.__doc__) + print("Available connection nicknames: %s" % ( + ' '.join(sorted(configs.keys())))) if not configname: available() elif configname not in configs: - print "Config `%s` not found. " % configname + print("Config `%s` not found. " % configname) available() else: config = configs[configname] @@ -225,27 +226,27 @@ def connect_url(self, url, connect_args={}): True if connection was successful. """ if self.trans_ctx and self.trans_ctx.transaction.is_active: - print "You have an active transaction, either %commit or " \ - "%rollback before connecting to a new database." + print("You have an active transaction, either %commit or " + "%rollback before connecting to a new database.") return False try: parsed_url = sa.engine.url.make_url(str(url)) except sa.exc.ArgumentError as e: - print e + print(e) return False safe_url = self.safe_url(parsed_url) if safe_url: - print "ipydb is connecting to: %s" % safe_url + print("ipydb is connecting to: %s" % safe_url) try: self.engine = engine.from_url(parsed_url, connect_args=connect_args) except ImportError: # pragma: nocover - print "It looks like you don't have a driver for %s.\n" \ - "See the following URL for supported " \ - "database drivers:\n\t%s" % ( + print("It looks like you don't have a driver for %s.\n" + "See the following URL for supported " + "database drivers:\n\t%s" % ( parsed_url.drivername, 'http://docs.sqlalchemy.org/en/latest/' - 'dialects/index.html#included-dialects') + 'dialects/index.html#included-dialects')) return False # force a connect so that we can fail early if the connection url won't # work @@ -253,7 +254,7 @@ def connect_url(self, url, connect_args={}): with self.engine.connect(): pass except sa.exc.OperationalError as e: # pragma: nocover - print e + print(e) return False self.connected = True @@ -265,7 +266,7 @@ def connect_url(self, url, connect_args={}): @connected def flush_metadata(self): """Delete cached schema information""" - print "Deleting metadata..." + print("Deleting metadata...") self.metadata_accessor.flush(self.engine) self.metadata_accessor.get_metadata(self.engine, noisy=True) @@ -305,10 +306,10 @@ def execute(self, query, params=None, multiparams=None): if rereflect: # schema changed self.metadata_accessor.get_metadata(self.engine, force=True, noisy=True) - except Exception, e: # pragma: nocover + except Exception as e: # pragma: nocover if self.debug: raise - print e.message + print(e.message) return result @connected @@ -328,7 +329,7 @@ def run_sql_script(self, script, interactive=False, delimiter='/'): line = fin.readline() if line.strip() == delimiter or (line == '' and current): if interactive: - print current + print(current) choice = multi_choice_prompt( 'Run this statement ' '([y]es, [n]o, [a]ll, [q]uit):', @@ -360,8 +361,8 @@ def begin(self): if not self.trans_ctx or not self.trans_ctx.transaction.is_active: self.trans_ctx = self.engine.begin() else: - print "You are already in a transaction" \ - " block and nesting is not supported" + print("You are already in a transaction" + " block and nesting is not supported") @connected def commit(self): @@ -371,7 +372,7 @@ def commit(self): pass self.trans_ctx = None else: - print "No active transaction" + print("No active transaction") @connected def rollback(self): @@ -380,7 +381,7 @@ def rollback(self): self.trans_ctx.transaction.rollback() self.trans_ctx = None else: - print "No active transaction" + print("No active transaction") @connected def show_tables(self, *globs): @@ -408,7 +409,7 @@ def show_tables(self, *globs): def describe(self, table): """Print information about a table.""" if table not in self.get_metadata().tables: - print "Table not found: %s" % table + print("Table not found: %s" % table) return tbl = self.get_metadata().tables[table] @@ -421,38 +422,38 @@ def namestr(c): with self.pager() as out: items = ((namestr(c), c.type, nullstr(c.nullable)) for c in tbl.columns) - out.write('Columns' + '\n') + out.write(u'Columns' + '\n') asciitable.draw( FakedResult(sorted(items), 'Name Type Nullable'.split()), out, paginate=True, max_fieldsize=5000) - out.write('\n') - out.write('Primary Key (*)\n') - out.write('---------------\n') - pk = ', '.join(c.name for c in tbl.columns if c.primary_key) - out.write(' ') + out.write(u'\n') + out.write(u'Primary Key (*)\n') + out.write(u'---------------\n') + pk = u', '.join(c.name for c in tbl.columns if c.primary_key) + out.write(u' ') if not pk: - out.write('(None Found!)') + out.write(u'(None Found!)') else: out.write(pk) - out.write('\n\n') - out.write('Foreign Keys\n') - out.write('------------\n') + out.write(u'\n\n') + out.write(u'Foreign Keys\n') + out.write(u'------------\n') fks = self.get_metadata().foreign_keys(table) fk = None for fk in fks: - out.write(' %s\n' % str(fk)) + out.write(u' %s\n' % str(fk)) if fk is None: - out.write(' (None Found)') - out.write('\n\nReferences to %s\n' % table) - out.write('--------------' + '-' * len(table) + '\n') + out.write(u' (None Found)') + out.write(u'\n\nReferences to %s\n' % table) + out.write(u'--------------' + '-' * len(table) + '\n') fks = self.get_metadata().fields_referencing(table) fk = None for fk in fks: - out.write(' ' + str(fk) + '\n') + out.write(u' ' + str(fk) + '\n') if fk is None: - out.write(' (None found)\n') - out.write('\n\nIndexes' + '\n') + out.write(u' (None found)\n') + out.write(u'\n\nIndexes' + '\n') def items(): for idx in self.get_metadata().indexes(table): @@ -494,16 +495,16 @@ def glob_columns(table): columns = table.columns columns = {starname(c): c for c in columns} if columns: - out.write(table.name + '\n') - out.write('-' * len(table.name) + '\n') + out.write(table.name + u'\n') + out.write(u'-' * len(table.name) + u'\n') for starcol in sorted(columns): col = columns[starcol] - out.write(" %-35s%s %s\n" % ( + out.write(u" %-35s%s %s\n" % ( starcol, col.type, 'NULL' if col.nullable else 'NOT NULL')) if columns: - out.write('\n') + out.write(u'\n') @connected def show_joins(self, table): @@ -513,9 +514,9 @@ def show_joins(self, table): """ with self.pager() as out: for fk in self.get_metadata().foreign_keys(table): - out.write('%s\n' % fk.as_join(reverse=True)) + out.write(u'%s\n' % fk.as_join(reverse=True)) for fk in self.get_metadata().fields_referencing(table): - out.write('%s\n' % fk.as_join()) + out.write(u'%s\n' % fk.as_join()) @connected def what_references(self, arg): @@ -534,7 +535,7 @@ def what_references(self, arg): fieldname = bits[1] if len(bits) > 1 else None fks = self.get_metadata().fields_referencing(tablename, fieldname) for fk in fks: - out.write(str(fk) + '\n') + out.write(str(fk) + u'\n') @connected def show_fks(self, table): @@ -545,7 +546,7 @@ def show_fks(self, table): with self.pager() as out: fks = self.get_metadata().foreign_keys(table) for fk in fks: - out.write(str(fk) + '\n') + out.write(str(fk) + u'\n') def pager(self): return Pager() diff --git a/ipydb/utils.py b/ipydb/utils.py index 5d79837..12d9cdb 100644 --- a/ipydb/utils.py +++ b/ipydb/utils.py @@ -2,9 +2,12 @@ import codecs import csv -import cStringIO +from io import StringIO import time +from builtins import input +from past.builtins import basestring + class UnicodeWriter: """ @@ -14,13 +17,14 @@ class UnicodeWriter: def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds): # Redirect output to a queue - self.queue = cStringIO.StringIO() + self.queue = StringIO() self.writer = csv.writer(self.queue, dialect=dialect, **kwds) self.stream = f self.encoder = codecs.getincrementalencoder(encoding)() def writerow(self, row): - self.writer.writerow([s.encode("utf-8") if isinstance(s, basestring) else s for s in row]) + self.writer.writerow([s.encode("utf-8") if isinstance(s, basestring) + else s for s in row]) # Fetch UTF-8 output from the queue ... data = self.queue.getvalue() data = data.decode("utf-8") @@ -40,7 +44,7 @@ def multi_choice_prompt(prompt, choices, default=None): ans = None while ans not in choices.keys(): try: - ans = raw_input(prompt + ' ').lower() + ans = input(prompt + ' ').lower() if not ans: # response was an empty string ans = default except KeyboardInterrupt: diff --git a/setup.py b/setup.py index 569c30e..81bfb09 100755 --- a/setup.py +++ b/setup.py @@ -4,7 +4,8 @@ from setuptools import setup import ipydb -requires = ['SQLAlchemy', 'ipython>=1.0', 'python-dateutil', 'sqlparse'] +requires = ['SQLAlchemy', 'ipython>=1.0', 'python-dateutil', 'sqlparse', + 'future'] tests_require = ['nose', 'mock'] extras_require = ['Sphinx==1.2.3', 'sphinx-rtd-theme==0.1.6'] description = "An IPython extension to help you write and run SQL statements" diff --git a/tests/test_completion.py b/tests/test_completion.py index 96e747b..d1a408d 100644 --- a/tests/test_completion.py +++ b/tests/test_completion.py @@ -59,7 +59,7 @@ def mock_fieldnames(self, table=None, dotted=False): if not dotted: return itertools.chain(*self.data.values()) else: - return ['%s.%s' % (t, c) for t, cols in self.data.iteritems() + return ['%s.%s' % (t, c) for t, cols in self.data.items() for c in cols] if dotted: return ['%s.%s' % (table, col) for col in self.data[table]] @@ -135,7 +135,7 @@ def test_expand_join_expression(self): 'not**real': 'not**real', 'lur**foo': 'lur inner join foo on lur.foo_id = foo.first ', } - for k, v in expansions.iteritems(): + for k, v in expansions.items(): nt.assert_equal(self.completer.expand_join_expression(k), v) def test_join_shortcut(self): @@ -149,7 +149,7 @@ def test_join_shortcut(self): 'lur**bar': ['lur inner join bar on lur.bar_id = bar.thing '], } - for symbol, expected in expectations.iteritems(): + for symbol, expected in expectations.items(): actual = self.completer.join_shortcut(Event(symbol=symbol)) nt.assert_equal(expected, actual) @@ -159,7 +159,7 @@ def test_sql_format(self): 'cs': ['csv'], 'ta': ['table'] } - for symbol, expected in expectations.iteritems(): + for symbol, expected in expectations.items(): actual = self.completer.sql_format(Event(symbol=symbol)) nt.assert_equal(expected, actual) @@ -178,7 +178,7 @@ def test_connection_nickname(self, mock_getconfigs): 'emp': ['employees'], 'no': ['northwind'] } - for symbol, expected in expectations.iteritems(): + for symbol, expected in expectations.items(): actual = self.completer.connection_nickname(Event(symbol=symbol)) nt.assert_equal(expected, actual) @@ -189,7 +189,7 @@ def test_sql_statement(self): ('select foo**lu', 'foo**lu'): ['foo**lur'], ('select foo.first foo.se', 'foo.se'): ['foo.second'], } - for (line, symbol), expected in expectations.iteritems(): + for (line, symbol), expected in expectations.items(): actual = self.completer.sql_statement( Event(line=line, symbol=symbol)) nt.assert_equal(expected, actual) @@ -214,7 +214,7 @@ def test_complete(self, mock_getconfigs): ('foo = %select -r foo.fi', 'select', 'foo.fi'): ['foo.first'], ('zzzz', 'zzzz', 'zzzz'): None, } - for (line, command, symbol), expected in expectations.iteritems(): + for (line, command, symbol), expected in expectations.items(): actual = self.completer.complete( Event(line=line, symbol=symbol, command=command)) nt.assert_equal(expected, actual) diff --git a/tests/test_integration.py b/tests/test_integration.py index a2b2a93..0a07cc1 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -1,11 +1,12 @@ """Some integration tests using the chinook example db.""" +from __future__ import print_function import shutil from IPython.terminal.interactiveshell import TerminalInteractiveShell import nose.tools as nt import mock -from StringIO import StringIO +from io import StringIO import ipydb from ipydb import plugin, engine @@ -43,7 +44,7 @@ def test_it(self): self.ipydb.get_reflecting_ps1() self.m.flushmetadata('') self.m.describe('Album') - print self.out.getvalue() + print(self.out.getvalue()) def test_help(self): ipydb.ipydb_help() # XXX: assert somthing... @@ -56,7 +57,7 @@ def test_other(self): self.m.sqlformat('vsc') self.m.sqlformat('csv') self.m.rereflect('') - print self.out.getvalue() + print(self.out.getvalue()) def teardown(self): self.pgetconfigs.stop() diff --git a/tests/test_metadata.py b/tests/test_metadata.py index 879e45f..c358406 100644 --- a/tests/test_metadata.py +++ b/tests/test_metadata.py @@ -28,7 +28,7 @@ def setup_ipydb_schema(): def teardown_ipydb_schema(): try: ipsession.commit() - except Exception, e: + except Exception as e: ipsession.rollback() raise e finally: diff --git a/tests/test_persist.py b/tests/test_persist.py index f8bf085..3000a5a 100644 --- a/tests/test_persist.py +++ b/tests/test_persist.py @@ -28,7 +28,7 @@ def setup_ipydb_schema(): def teardown_ipydb_schema(): try: ipsession.commit() - except Exception, e: + except Exception as e: ipsession.rollback() raise e finally: diff --git a/tests/test_plugin.py b/tests/test_plugin.py index d2845f4..eb33e42 100644 --- a/tests/test_plugin.py +++ b/tests/test_plugin.py @@ -1,6 +1,6 @@ -from ConfigParser import DuplicateSectionError +from configparser import DuplicateSectionError import re -from StringIO import StringIO +from io import StringIO from IPython.terminal.interactiveshell import TerminalInteractiveShell import nose.tools as nt @@ -49,9 +49,9 @@ def setup_run_sql(self, runsetup=False): self.ip.engine.begin.return_value = self.ip.engine self.ip.trans_ctx = self.ip.engine self.ip.trans_ctx.conn = self.ip.engine - s1 = "update table foo set bar = 1 where baz = 2\n" - s2 = 'delete from spam where eggs = 1\n' - statements = "{s1}/\n{s2}/\n".format(s1=s1, s2=s2) + s1 = u"update table foo set bar = 1 where baz = 2\n" + s2 = u'delete from spam where eggs = 1\n' + statements = u"{s1}/\n{s2}/\n".format(s1=s1, s2=s2) sio = StringIO(statements) mo = mock.mock_open(read_data=statements) handle = mo.return_value