diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2014-04-28 17:03:37 -0400 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2014-04-28 17:03:37 -0400 |
commit | 70981099103828afbe33eb4d1f668dc20894b399 (patch) | |
tree | 4b9c0a98829b4d409211a8d536ca4e94e7450c8d | |
parent | d1f6d7f3e7e698eff2c7774b63531f151d908209 (diff) | |
download | mako-70981099103828afbe33eb4d1f668dc20894b399.tar.gz |
- switch to argparse for cmdline template runner
- write a test suite for cmdline
- start using context manager helpers in tests. intrinsic here is that
we're going to go 1.0 and drop at least 2.4 and probably 2.5
- update .gitignore
-rwxr-xr-x | .gitignore | 2 | ||||
-rwxr-xr-x | mako/cmd.py | 82 | ||||
-rw-r--r-- | setup.py | 7 | ||||
-rw-r--r-- | test/__init__.py | 28 | ||||
-rw-r--r-- | test/templates/cmd_good.mako | 1 | ||||
-rw-r--r-- | test/templates/cmd_runtime.mako | 1 | ||||
-rw-r--r-- | test/templates/cmd_syntax.mako | 1 | ||||
-rw-r--r-- | test/test_cmd.py | 73 |
8 files changed, 140 insertions, 55 deletions
@@ -1,4 +1,6 @@ /build +/dist +/.coverage /doc/build/output *.pyc *.orig diff --git a/mako/cmd.py b/mako/cmd.py index 15c2737..acccbc3 100755 --- a/mako/cmd.py +++ b/mako/cmd.py @@ -3,64 +3,60 @@ # # This module is part of Mako and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php - -def render(data, kw, lookup_dirs): - from mako.template import Template - from mako.lookup import TemplateLookup - - lookup = TemplateLookup(lookup_dirs) - return Template(data, lookup=lookup).render(**kw) +from argparse import ArgumentParser +from os.path import isfile, dirname +import sys +from mako.template import Template +from mako.lookup import TemplateLookup +from mako import exceptions def varsplit(var): if "=" not in var: return (var, "") return var.split("=", 1) -def cmdline(argv=None): - import pdb; pdb.set_trace() - - from os.path import isfile, dirname - from sys import stdin - - if argv is None: - import sys - argv = sys.argv +def _exit(): + sys.stderr.write(exceptions.text_error_template().render()) + sys.exit(1) - from optparse import OptionParser +def cmdline(argv=None): - parser = OptionParser("usage: %prog [FILENAME]") - parser.add_option("--var", default=[], action="append", + parser = ArgumentParser("usage: %prog [FILENAME]") + parser.add_argument("--var", default=[], action="append", help="variable (can be used multiple times, use name=value)") - parser.add_option("--template-dir", default=[], action="append", + parser.add_argument("--template-dir", default=[], action="append", help="Directory to use for template lookup (multiple " - "directories may be provided). If not given then if the " - "template is read from stdin, the value defaults to be " - "the current directory, otherwise it defaults to be the " - "parent directory of the file provided.") - - opts, args = parser.parse_args(argv[1:]) - if len(args) not in (0, 1): - parser.error("wrong number of arguments") # Will exit - - if (len(args) == 0) or (args[0] == "-"): - fo = stdin - lookup_dirs = opts.template_dir or ["."] + "directories may be provided). If not given then if the " + "template is read from stdin, the value defaults to be " + "the current directory, otherwise it defaults to be the " + "parent directory of the file provided.") + parser.add_argument('input', nargs='?', default='-') + + options = parser.parse_args(argv) + if options.input == '-': + lookup_dirs = options.template_dir or ["."] + lookup = TemplateLookup(lookup_dirs) + try: + template = Template(sys.stdin.read(), lookup=lookup) + except: + _exit() else: - filename = args[0] + filename = options.input if not isfile(filename): raise SystemExit("error: can't find %s" % filename) - fo = open(filename) - lookup_dirs = opts.template_dir or [dirname(filename)] - - kw = dict([varsplit(var) for var in opts.var]) - data = fo.read() - + lookup_dirs = options.template_dir or [dirname(filename)] + lookup = TemplateLookup(lookup_dirs) + try: + template = Template(filename=filename, lookup=lookup) + except: + _exit() + + kw = dict([varsplit(var) for var in options.var]) try: - print(render(data, kw, lookup_dirs=lookup_dirs)) + print(template.render(**kw)) except: - from mako import exceptions - print(exceptions.text_error_template().render(), file=sys.stderr) - sys.exit(1) + _exit() + if __name__ == "__main__": cmdline() @@ -18,6 +18,11 @@ if markupsafe_installs: else: install_requires = [] +try: + import argparse +except ImportError: + install_requires.append('argparse') + setup(name='Mako', version=VERSION, description="A super-fast templating language that borrows the \ @@ -39,7 +44,7 @@ setup(name='Mako', url='http://www.makotemplates.org/', license='MIT', packages=find_packages('.', exclude=['examples*', 'test*']), - tests_require=['nose >= 0.11'], + tests_require=['nose >= 0.11', 'mock'], test_suite="nose.collector", zip_safe=False, install_requires=install_requires, diff --git a/test/__init__.py b/test/__init__.py index 64dde8e..91ff54e 100644 --- a/test/__init__.py +++ b/test/__init__.py @@ -2,11 +2,12 @@ from mako.template import Template import unittest import os from mako.compat import py3k, py26, py25 +from mako import compat from mako.util import update_wrapper import re from mako.cache import CacheImpl, register_plugin from nose import SkipTest -import sys +import contextlib template_base = os.path.join(os.path.dirname(__file__), 'templates') module_base = os.path.join(template_base, 'modules') @@ -61,24 +62,29 @@ def teardown(): import shutil shutil.rmtree(module_base, True) -def assert_raises(except_cls, callable_, *args, **kw): +@contextlib.contextmanager +def raises(except_cls, message=None): try: - callable_(*args, **kw) + yield success = False - except except_cls: + except except_cls as e: + if message: + assert re.search(message, compat.text_type(e), re.UNICODE), \ + "%r !~ %s" % (message, e) + print(compat.text_type(e).encode('utf-8')) success = True # assert outside the block so it works for AssertionError too ! assert success, "Callable did not raise an exception" + +def assert_raises(except_cls, callable_, *args, **kw): + with raises(except_cls): + return callable_(*args, **kw) + def assert_raises_message(except_cls, msg, callable_, *args, **kwargs): - try: - callable_(*args, **kwargs) - assert False, "Callable did not raise an exception" - except except_cls: - e = sys.exc_info()[1] - assert re.search(msg, str(e)), "%r !~ %s" % (msg, e) - print(str(e)) + with raises(except_cls, msg): + return callable_(*args, **kwargs) def skip_if(predicate, reason=None): """Skip a test if predicate is true.""" diff --git a/test/templates/cmd_good.mako b/test/templates/cmd_good.mako new file mode 100644 index 0000000..68ebec4 --- /dev/null +++ b/test/templates/cmd_good.mako @@ -0,0 +1 @@ +hello world ${x}
\ No newline at end of file diff --git a/test/templates/cmd_runtime.mako b/test/templates/cmd_runtime.mako new file mode 100644 index 0000000..6c2675b --- /dev/null +++ b/test/templates/cmd_runtime.mako @@ -0,0 +1 @@ +${q}
\ No newline at end of file diff --git a/test/templates/cmd_syntax.mako b/test/templates/cmd_syntax.mako new file mode 100644 index 0000000..d2117db --- /dev/null +++ b/test/templates/cmd_syntax.mako @@ -0,0 +1 @@ +${x
\ No newline at end of file diff --git a/test/test_cmd.py b/test/test_cmd.py new file mode 100644 index 0000000..d7e07ae --- /dev/null +++ b/test/test_cmd.py @@ -0,0 +1,73 @@ +from __future__ import with_statement +from contextlib import contextmanager +from test import TemplateTest, eq_, raises, template_base +import os +import mock +from mako.cmd import cmdline + +class CmdTest(TemplateTest): + @contextmanager + def _capture_output_fixture(self, stream="stdout"): + with mock.patch("sys.%s" % stream) as stdout: + yield stdout + + def test_stdin_success(self): + with self._capture_output_fixture() as stdout: + with mock.patch("sys.stdin", mock.Mock( + read=mock.Mock(return_value="hello world ${x}"))): + cmdline(["--var", "x=5", "-"]) + + eq_(stdout.write.mock_calls[0][1][0], "hello world 5") + + def test_stdin_syntax_err(self): + with mock.patch("sys.stdin", mock.Mock( + read=mock.Mock(return_value="${x"))): + with self._capture_output_fixture("stderr") as stderr: + with raises(SystemExit): + cmdline(["--var", "x=5", "-"]) + + assert "SyntaxException: Expected" in \ + stderr.write.mock_calls[0][1][0] + assert "Traceback" in stderr.write.mock_calls[0][1][0] + + + def test_stdin_rt_err(self): + with mock.patch("sys.stdin", mock.Mock( + read=mock.Mock(return_value="${q}"))): + with self._capture_output_fixture("stderr") as stderr: + with raises(SystemExit): + cmdline(["--var", "x=5", "-"]) + + assert "NameError: Undefined" in stderr.write.mock_calls[0][1][0] + assert "Traceback" in stderr.write.mock_calls[0][1][0] + + def test_file_success(self): + with self._capture_output_fixture() as stdout: + cmdline(["--var", "x=5", + os.path.join(template_base, "cmd_good.mako")]) + + eq_(stdout.write.mock_calls[0][1][0], "hello world 5") + + def test_file_syntax_err(self): + with self._capture_output_fixture("stderr") as stderr: + with raises(SystemExit): + cmdline(["--var", "x=5", + os.path.join(template_base, "cmd_syntax.mako")]) + + assert "SyntaxException: Expected" in stderr.write.mock_calls[0][1][0] + assert "Traceback" in stderr.write.mock_calls[0][1][0] + + def test_file_rt_err(self): + with self._capture_output_fixture("stderr") as stderr: + with raises(SystemExit): + cmdline(["--var", "x=5", + os.path.join(template_base, "cmd_runtime.mako")]) + + assert "NameError: Undefined" in stderr.write.mock_calls[0][1][0] + assert "Traceback" in stderr.write.mock_calls[0][1][0] + + + def test_file_notfound(self): + with raises(SystemExit, "error: can't find fake.lalala"): + cmdline(["--var", "x=5", "fake.lalala"]) + |