summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2013-11-21 18:46:35 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2013-11-21 18:46:35 -0500
commit308233abea250b173492de4b64d1ac7ac0d9d1eb (patch)
treef2a1877550861d65218ce1820e90d76d11a49a86
parent227f1404a4012c52f75b270f237c6c6bc0579cc3 (diff)
downloadalembic-308233abea250b173492de4b64d1ac7ac0d9d1eb.tar.gz
Fixes to Py3k in-place compatibity regarding output encoding and related;
the use of the new io.* package introduced some incompatibilities on Py2k. These should be resolved, due to the introduction of new adapter types for translating from io.* to Py2k file types, StringIO types. Thanks to Javier Santacruz for help with this.
-rw-r--r--alembic/compat.py49
-rw-r--r--alembic/migration.py12
-rw-r--r--docs/build/changelog.rst10
-rw-r--r--tests/test_offline_environment.py3
4 files changed, 60 insertions, 14 deletions
diff --git a/alembic/compat.py b/alembic/compat.py
index fc88933..5cfdacc 100644
--- a/alembic/compat.py
+++ b/alembic/compat.py
@@ -80,9 +80,48 @@ def with_metaclass(meta, base=object):
return meta("%sBase" % meta.__name__, (base,), {})
################################################
+
+# produce a wrapper that allows encoded text to stream
+# into a given buffer, but doesn't close it.
+# not sure of a more idiomatic approach to this.
+class EncodedIO(io.TextIOWrapper):
+ def close(self):
+ pass
+
if py2k:
- def writable_buffer(file):
- return io.FileIO(file.fileno(), 'w')
-else:
- def writable_buffer(file):
- return file
+ # in Py2K, the io.* package is awkward because it does not
+ # easily wrap the file type (e.g. sys.stdout) and I can't
+ # figure out at all how to wrap StringIO.StringIO (used by nosetests)
+ # and also might be user specified too. So create a full
+ # adapter.
+
+ class ActLikePy3kIO(object):
+ """Produce an object capable of wrapping either
+ sys.stdout (e.g. file) *or* StringIO.StringIO().
+
+ """
+ def _false(self):
+ return False
+
+ def _true(self):
+ return True
+
+ readable = seekable = _false
+ writable = _true
+ closed = False
+
+ def __init__(self, file_):
+ self.file_ = file_
+
+ def write(self, text):
+ return self.file_.write(text)
+
+ def flush(self):
+ return self.file_.flush()
+
+ class EncodedIO(EncodedIO):
+ def __init__(self, file_, encoding):
+ super(EncodedIO, self).__init__(
+ ActLikePy3kIO(file_), encoding=encoding)
+
+
diff --git a/alembic/migration.py b/alembic/migration.py
index 657e60d..9a01b01 100644
--- a/alembic/migration.py
+++ b/alembic/migration.py
@@ -6,7 +6,7 @@ from sqlalchemy import MetaData, Table, Column, String, literal_column
from sqlalchemy import create_engine
from sqlalchemy.engine import url as sqla_url
-from .compat import callable, writable_buffer
+from .compat import callable, EncodedIO
from . import ddl, util
log = logging.getLogger(__name__)
@@ -72,13 +72,13 @@ class MigrationContext(object):
self._migrations_fn = opts.get('fn')
self.as_sql = as_sql
- self.output_buffer = opts.get("output_buffer", sys.stdout)
-
if "output_encoding" in opts:
- self.output_buffer = io.TextIOWrapper(
- opts.get("output_buffer") or writable_buffer(sys.stdout),
- opts.get('output_encoding')
+ self.output_buffer = EncodedIO(
+ opts.get("output_buffer") or sys.stdout,
+ opts['output_encoding']
)
+ else:
+ self.output_buffer = opts.get("output_buffer", sys.stdout)
self._user_compare_type = opts.get('compare_type', False)
self._user_compare_server_default = opts.get(
diff --git a/docs/build/changelog.rst b/docs/build/changelog.rst
index 364bc84..9f7b715 100644
--- a/docs/build/changelog.rst
+++ b/docs/build/changelog.rst
@@ -9,6 +9,16 @@ Changelog
.. change::
:tags: bug
+ :pullreq: 9
+
+ Fixes to Py3k in-place compatibity regarding output encoding and related;
+ the use of the new io.* package introduced some incompatibilities on Py2k.
+ These should be resolved, due to the introduction of new adapter types
+ for translating from io.* to Py2k file types, StringIO types.
+ Thanks to Javier Santacruz for help with this.
+
+ .. change::
+ :tags: bug
:tickets: 145
Fixed py3k bug where the wrong form of ``next()`` was being called
diff --git a/tests/test_offline_environment.py b/tests/test_offline_environment.py
index da2589c..7026e8c 100644
--- a/tests/test_offline_environment.py
+++ b/tests/test_offline_environment.py
@@ -12,7 +12,6 @@ class OfflineEnvironmentTest(TestCase):
def setUp(self):
env = staging_env()
self.cfg = _no_sql_testing_config()
- self.cfg.output_buffer = io.StringIO()
global a, b, c
a, b, c = three_rev_fixture(self.cfg)
@@ -43,8 +42,6 @@ assert context.get_starting_revision_argument() == 'x'
command.upgrade(self.cfg, a, sql=True)
command.downgrade(self.cfg, "%s:%s" % (b, a), sql=True)
command.current(self.cfg)
- # current seems to close the buffer (?)
- self.cfg.output_buffer = io.StringIO()
command.stamp(self.cfg, a)
def test_starting_rev_pre_context(self):