]> git.ipfire.org Git - thirdparty/sqlalchemy/alembic.git/commitdiff
Fixes to Py3k in-place compatibity regarding output encoding and related;
authorMike Bayer <mike_mp@zzzcomputing.com>
Thu, 21 Nov 2013 23:46:35 +0000 (18:46 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Thu, 21 Nov 2013 23:46:35 +0000 (18:46 -0500)
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.

alembic/compat.py
alembic/migration.py
docs/build/changelog.rst
tests/test_offline_environment.py

index fc88933a1b0f505a59a68c6d1300727ce9a7c651..5cfdaccdc8a5292bf11737263aaf19bf55b66006 100644 (file)
@@ -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)
+
+
index 657e60d83e2d6fa26d4ac447cccf0d0abdc85d8a..9a01b0161db05e8cfd83366c9434916d5f075754 100644 (file)
@@ -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(
index 364bc8408628e44a8a2e7f6dbc4f58480552bbf4..9f7b7153f4814db9bdff6abe18eecd28c2d34783 100644 (file)
@@ -7,6 +7,16 @@ Changelog
     :version: 0.6.1
     :released: no release date
 
+    .. 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
index da2589c587cf824a55f720c821587ed275376f60..7026e8c689266270bb44b9cdd0aabcfafb3f5790 100644 (file)
@@ -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):