]> git.ipfire.org Git - thirdparty/sqlalchemy/alembic.git/commitdiff
- Errors which occur within the Mako render step are now intercepted
authorMike Bayer <mike_mp@zzzcomputing.com>
Sat, 9 Apr 2016 01:32:07 +0000 (21:32 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sat, 9 Apr 2016 01:32:07 +0000 (21:32 -0400)
and raised as CommandErrors like other failure cases; the Mako
exception itself is written using template-line formatting to
a temporary file which is named in the exception message.
fixes #367

alembic/util/__init__.py
alembic/util/exc.py [new file with mode: 0644]
alembic/util/pyfiles.py
docs/build/changelog.rst
tests/test_script_production.py

index e53199bf24dc17a4ae5d1bf15fdd4469bb046d33..22411110c8accb0a42ae753497a19c42ae22e7a9 100644 (file)
@@ -9,10 +9,7 @@ from .pyfiles import (  # noqa
 from .sqla_compat import (  # noqa
     sqla_07, sqla_079, sqla_08, sqla_083, sqla_084, sqla_09, sqla_092,
     sqla_094, sqla_099, sqla_100, sqla_105, sqla_110)
-
-
-class CommandError(Exception):
-    pass
+from .exc import CommandError
 
 
 if not sqla_07:
diff --git a/alembic/util/exc.py b/alembic/util/exc.py
new file mode 100644 (file)
index 0000000..f7ad021
--- /dev/null
@@ -0,0 +1,2 @@
+class CommandError(Exception):
+    pass
index c4de0710190dda279a85df52dd53b7a31cfeb47a..e651403589b9253e839f681e9e39dcb6582c9dbe 100644 (file)
@@ -3,14 +3,27 @@ import os
 import re
 from .compat import load_module_py, load_module_pyc
 from mako.template import Template
+from mako import exceptions
+import tempfile
+from .exc import CommandError
 
 
 def template_to_file(template_file, dest, output_encoding, **kw):
-    with open(dest, 'wb') as f:
-        template = Template(filename=template_file)
-        f.write(
-            template.render_unicode(**kw).encode(output_encoding)
-        )
+    template = Template(filename=template_file)
+    try:
+        output = template.render_unicode(**kw).encode(output_encoding)
+    except:
+        with tempfile.NamedTemporaryFile(suffix='.txt', delete=False) as ntf:
+            ntf.write(
+                exceptions.text_error_template().
+                render_unicode().encode(output_encoding))
+            fname = ntf.name
+        raise CommandError(
+            "Template rendering failed; see %s for a "
+            "template-oriented traceback." % fname)
+    else:
+        with open(dest, 'wb') as f:
+            f.write(output)
 
 
 def coerce_resource_to_filename(fname):
@@ -63,7 +76,6 @@ def edit(path):
     """Given a source path, run the EDITOR for it"""
 
     import editor
-    from . import CommandError
     try:
         editor.edit(path)
     except Exception as exc:
index 4ac5941458a6cd8669c8f150291591fe550010bc..f42f1b60de2dbe0ad7ff447dc382910917ededf3 100644 (file)
@@ -6,6 +6,15 @@ Changelog
 .. changelog::
     :version: 0.8.6
 
+    .. change::
+      :tags: bug, commands
+      :tickets: 367
+
+      Errors which occur within the Mako render step are now intercepted
+      and raised as CommandErrors like other failure cases; the Mako
+      exception itself is written using template-line formatting to
+      a temporary file which is named in the exception message.
+
     .. change::
       :tags: bug, postgresql
       :tickets: 365
index d2e397f1dca3ef59919e3cd2da974eca1eecf2a3..66e311d1745cd86d03cf27826985305151d9141f 100644 (file)
@@ -16,6 +16,8 @@ import os
 import datetime
 import sqlalchemy as sa
 from sqlalchemy.engine.reflection import Inspector
+from alembic.util import CommandError
+import re
 
 env, abc, def_ = None, None, None
 
@@ -220,6 +222,8 @@ class RevisionCommandTest(TestBase):
         )
 
 
+
+
 class CustomizeRevisionTest(TestBase):
     def setUp(self):
         self.env = staging_env()
@@ -812,3 +816,24 @@ down_revision = ${repr(down_revision)}
         with open(rev.path) as f:
             text = f.read()
         assert "somearg: somevalue" in text
+
+    def test_bad_render(self):
+        env_file_fixture("""
+context.configure(dialect_name='sqlite', template_args={"somearg":"somevalue"})
+""")
+        script_file_fixture("""
+    <% z = x + y %>
+""")
+
+        try:
+            command.revision(self.cfg, message="some rev")
+        except CommandError as ce:
+            m = re.match(
+                r"^Template rendering failed; see (.+?) "
+                "for a template-oriented",
+                str(ce)
+            )
+            assert m, "Command error did not produce a file"
+            contents = open(m.group(1)).read()
+            os.remove(m.group(1))
+            assert "<% z = x + y %>" in contents