diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2013-11-21 18:46:35 -0500 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2013-11-21 18:46:35 -0500 |
commit | 308233abea250b173492de4b64d1ac7ac0d9d1eb (patch) | |
tree | f2a1877550861d65218ce1820e90d76d11a49a86 | |
parent | 227f1404a4012c52f75b270f237c6c6bc0579cc3 (diff) | |
download | alembic-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.py | 49 | ||||
-rw-r--r-- | alembic/migration.py | 12 | ||||
-rw-r--r-- | docs/build/changelog.rst | 10 | ||||
-rw-r--r-- | tests/test_offline_environment.py | 3 |
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): |