Repository: cookiecutter/cookiecutter

Issue:
Jinja breaks on syntax error without reporting where the error occured
I tried to create a project from [here](https://github.com/thedrow/cookiecutter-pypackage/) and I got the following traceback:

```
cookiecutter https://github.com/thedrow/cookiecutter-pypackage.git
You've cloned cookiecutter-pypackage before. Is it okay to delete and re-clone it? [Y/n] y
Cloning into 'cookiecutter-pypackage'...
remote: Counting objects: 249, done.
remote: Compressing objects: 100% (131/131), done.
remote: Total 249 (delta 108), reused 230 (delta 96)
Receiving objects: 100% (249/249), 39.41 KiB, done.
Resolving deltas: 100% (108/108), done.
full_name (default is "Omer Katz")? 
email (default is "omer.drow@gmail.com")? 
github_username (default is "thedrow")? testsuite
project_name (default is "Python Boilerplate")? testsuite
repo_name (default is "boilerplate")? testsuite
project_short_description (default is "Python Boilerplate contains all the boilerplate you need to create a Python package.")? Testsuite is a set of plugins & extensions to nose2 that aims to assist you to write better tests.
release_date (default is "2013-08-25")? 
year (default is "2013")? 
version (default is "0.1.0")? 
Traceback (most recent call last):
  File "/usr/local/bin/cookiecutter", line 9, in <module>
    load_entry_point('cookiecutter==0.6.4', 'console_scripts', 'cookiecutter')()
  File "/usr/local/lib/python3.3/dist-packages/cookiecutter/main.py", line 90, in main
    cookiecutter(args.input_dir)
  File "/usr/local/lib/python3.3/dist-packages/cookiecutter/main.py", line 61, in cookiecutter
    context=context
  File "/usr/local/lib/python3.3/dist-packages/cookiecutter/generate.py", line 135, in generate_files
    generate_file(infile, context, env)
  File "/usr/local/lib/python3.3/dist-packages/cookiecutter/generate.py", line 85, in generate_file
    tmpl = env.get_template(infile_fwd_slashes)
  File "/usr/local/lib/python3.3/dist-packages/jinja2/environment.py", line 791, in get_template
    return self._load_template(name, self.make_globals(globals))
  File "/usr/local/lib/python3.3/dist-packages/jinja2/environment.py", line 765, in _load_template
    template = self.loader.load(self, name, globals)
  File "/usr/local/lib/python3.3/dist-packages/jinja2/loaders.py", line 125, in load
    code = environment.compile(source, name, filename)
  File "/usr/local/lib/python3.3/dist-packages/jinja2/environment.py", line 554, in compile
    self.handle_exception(exc_info, source_hint=source)
  File "/usr/local/lib/python3.3/dist-packages/jinja2/environment.py", line 742, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/usr/local/lib/python3.3/dist-packages/jinja2/_compat.py", line 36, in reraise
    raise value.with_traceback(tb)
  File "./cookiecutter-pypackage/{{cookiecutter.repo_name}}/LICENSE", line 13, in <module>
    * Neither the name of {{ cookiecutter.project_name } nor the names of its contributors
  File "/usr/local/lib/python3.3/dist-packages/jinja2/environment.py", line 459, in _parse
    return Parser(self, source, name, encode_filename(filename)).parse()
  File "/usr/local/lib/python3.3/dist-packages/jinja2/parser.py", line 893, in parse
    result = nodes.Template(self.subparse(), lineno=1)
  File "/usr/local/lib/python3.3/dist-packages/jinja2/parser.py", line 867, in subparse
    add_data(self.parse_tuple(with_condexpr=True))
  File "/usr/local/lib/python3.3/dist-packages/jinja2/parser.py", line 612, in parse_tuple
    args.append(parse())
  File "/usr/local/lib/python3.3/dist-packages/jinja2/parser.py", line 386, in parse_expression
    return self.parse_condexpr()
  File "/usr/local/lib/python3.3/dist-packages/jinja2/parser.py", line 391, in parse_condexpr
    expr1 = self.parse_or()
  File "/usr/local/lib/python3.3/dist-packages/jinja2/parser.py", line 404, in parse_or
    left = self.parse_and()
  File "/usr/local/lib/python3.3/dist-packages/jinja2/parser.py", line 413, in parse_and
    left = self.parse_not()
  File "/usr/local/lib/python3.3/dist-packages/jinja2/parser.py", line 424, in parse_not
    return self.parse_compare()
  File "/usr/local/lib/python3.3/dist-packages/jinja2/parser.py", line 428, in parse_compare
    expr = self.parse_add()
  File "/usr/local/lib/python3.3/dist-packages/jinja2/parser.py", line 450, in parse_add
    left = self.parse_sub()
  File "/usr/local/lib/python3.3/dist-packages/jinja2/parser.py", line 460, in parse_sub
    left = self.parse_concat()
  File "/usr/local/lib/python3.3/dist-packages/jinja2/parser.py", line 470, in parse_concat
    args = [self.parse_mul()]
  File "/usr/local/lib/python3.3/dist-packages/jinja2/parser.py", line 480, in parse_mul
    left = self.parse_div()
  File "/usr/local/lib/python3.3/dist-packages/jinja2/parser.py", line 490, in parse_div
    left = self.parse_floordiv()
  File "/usr/local/lib/python3.3/dist-packages/jinja2/parser.py", line 500, in parse_floordiv
    left = self.parse_mod()
  File "/usr/local/lib/python3.3/dist-packages/jinja2/parser.py", line 510, in parse_mod
    left = self.parse_pow()
  File "/usr/local/lib/python3.3/dist-packages/jinja2/parser.py", line 520, in parse_pow
    left = self.parse_unary()
  File "/usr/local/lib/python3.3/dist-packages/jinja2/parser.py", line 539, in parse_unary
    node = self.parse_postfix(node)
  File "/usr/local/lib/python3.3/dist-packages/jinja2/parser.py", line 664, in parse_postfix
    node = self.parse_subscript(node)
  File "/usr/local/lib/python3.3/dist-packages/jinja2/parser.py", line 692, in parse_subscript
    next(self.stream)
  File "/usr/local/lib/python3.3/dist-packages/jinja2/lexer.py", line 349, in __next__
    self.current = next(self._iter)
  File "/usr/local/lib/python3.3/dist-packages/jinja2/lexer.py", line 552, in wrap
    for lineno, token, value in stream:
  File "/usr/local/lib/python3.3/dist-packages/jinja2/lexer.py", line 677, in tokeniter
    filename)
jinja2.exceptions.TemplateSyntaxError: unexpected '}'
```

I'm using Python 3.3 on Ubuntu 13.04.



Discussion:

Resolving patch:
diff --git a/cookiecutter/generate.py b/cookiecutter/generate.py
--- a/cookiecutter/generate.py
+++ b/cookiecutter/generate.py
@@ -15,6 +15,7 @@
 
 from jinja2 import FileSystemLoader, Template
 from jinja2.environment import Environment
+from jinja2.exceptions import TemplateSyntaxError
 from binaryornot.check import is_binary
 
 from .exceptions import NonTemplatedInputDirException
@@ -82,7 +83,13 @@ def generate_file(infile, context, env):
         infile_fwd_slashes = infile.replace(os.path.sep, '/')
 
         # Render the file
-        tmpl = env.get_template(infile_fwd_slashes)
+        try:
+            tmpl = env.get_template(infile_fwd_slashes)
+        except TemplateSyntaxError as exception:
+            # Disable translated so that printed exception contains verbose
+            # information about syntax error location
+            exception.translated = False
+            raise
         rendered_file = tmpl.render(**context)
 
         # Render the output filename before writing


Test patch:
diff --git a/tests/input{{syntax_error}}/simple.txt b/tests/input{{syntax_error}}/simple.txt
new file mode 100644
--- /dev/null
+++ b/tests/input{{syntax_error}}/simple.txt
@@ -0,0 +1 @@
+I eat {{ syntax_error }} {# this comment is not closed}
\ No newline at end of file
diff --git a/tests/test_generate.py b/tests/test_generate.py
--- a/tests/test_generate.py
+++ b/tests/test_generate.py
@@ -16,6 +16,7 @@
 
 from jinja2 import FileSystemLoader
 from jinja2.environment import Environment
+from jinja2.exceptions import TemplateSyntaxError
 
 from cookiecutter import generate
 from cookiecutter import exceptions
@@ -49,6 +50,24 @@ def test_generate_files_bad(self):
             template_dir='tests/input'
         )
 
+    def test_generate_files_verbose_template_syntax_error(self):
+        try:
+            generate.generate_files(
+                context={'syntax_error': 'syntax_error'},
+                template_dir='tests/input{{syntax_error}}'
+            )
+        except TemplateSyntaxError as exception:
+            self.assertEquals(
+                str(exception),
+                'Missing end of comment tag\n'
+                '  File "./tests/input{{syntax_error}}/simple.txt", line 1\n'
+                '    I eat {{ syntax_error }} {# this comment is not closed}'
+            )
+        except exception:
+            self.fail('Unexpected exception thrown:', exception)
+        else:
+            self.fail('TemplateSyntaxError not thrown')
+
     def test_generate_files(self):
         generate.generate_files(
             context={'food': 'pizzä'},