Quantcast
Channel: Mako: Ticket Query

#167: Apache/WSGI Integration

$
0
0

I modified the run_wsgi.py file to work directly in Apache to enable PHP-style pages written in Mako. I don't want to offend the purists :), but there are times when full app stacks like Pylons or Django are just too much. For simple web pages with a little code in them, Mako works great all by itself.

Any file named *.mako in the web root of Apache runs as a Mako template. They can be anywhere in the web root.

The script is a fork of run_wsgi.py. I tried to make one file do both (Apache and built-in web server), but they were different enough environments that it made sense to separate them.

I've attached the script to this trouble ticket. If the developers find it useful, they are welcome to add it to the examples/ directory for other users to have.


#150: Line ending handling broken on Win32 platform

$
0
0

Version 0.3.4

Line ending handling of templates is broken on Windows:

For each "CR-LF" sequence in the template file you get "CR-CR-LF" in the output.

This only happens when using the filename argument to Template.init(), not if the text argument is used to supply the template.

I think this is due to opening file with mode "rb" where mode "rU" should be used to automatically convert line endings to the correct internal format on all platforms.

#149: Add new filter "nbsp"

$
0
0

Hi,

What do you think about adding a filter for non-breaking spaces? I assume that it could be very help full for a lot of people.

Example:

diff -r 4dc291a1bc1c mako/filters.py
--- a/mako/filters.py   Tue Sep 14 10:54:22 2010 +0200
+++ b/mako/filters.py   Wed Sep 15 08:41:05 2010 +0200
@@ -39,6 +39,9 @@
 def trim(string):
     return string.strip()
+def nbsp(string):
+    return string.replace(' ', ' ')
+
 class Decode(object):
     def __getattr__(self, key):
@@ -161,6 +164,7 @@
     'h':'filters.html_escape',
     'u':'filters.url_escape',
     'trim':'filters.trim',
+    'nbsp':'filters.nbsp',
     'entity':'filters.html_entities_escape',
     'unicode':'unicode',
     'decode':'decode',

Regards, Carsten

#197: "Try" blocks don't support the "else" ternary keyword.

$
0
0

parsetree.py:96 needs to be:

'try':set(['except','else','finally']),

...but I don't know enough about Mako internally to know what else (hehe) is required to make this work.

#196: No way to import from __future__

$
0
0

<%! from __future__ import division %> on the first line of a file doesn't work, because the import doesn't end up as the first statement in the resulting Python module.

Hardly a show-stopper, but it bit me when I wanted to do a bit of inline math in a template.

#195: Control statements don't follow line-wrapping rules

$
0
0
% for item in [
        'some',
        'long',
        'list',
        'of',
        'items',
    ]:
    ${item}
% endfor

Produces:

CompileException: Fragment 'for item in [' is not a partial control statement in file...

Adding backslashes to the end of every line works, but normal Python wrapping ought to apply here.

#145: continue / break control statements?

$
0
0

Hi,

I was wondering how to use control/break within a loop. I didn't find anything in the docs, so I tried this:

% for i in range(10):

% if i == 3:

% continue

% endif ${i}

% endfor

That didn't work, so I ended up with this:

% for i in range(10):

<% if i == 3:

continue

%> ${i}

% endfor

I find the first version is more readable. Perhaps it would be nice to have 'continue' and 'break' statements to complement the flow control.

Alternatively, if there's another preferred method for issuing a continue or break, it would be great to have an example in the docs.

Thanks!

#140: inconsistent behavior of filter pulling from context based on name

$
0
0

this is related to #3 but seems different

frommako.templateimport Template
x = Template("""
X:
    ${"asdf" | h.foo}
""")
y = Template("""
Y:
    ${"asdf" | z.foo}
""")
z = Template("""
Z:
    ${h}
    ${"asdf" | h.foo}
""")classh(object):
    foo =strtry:print x.render(h=h)exceptNameError, e:print e
print y.render(z=h)print z.render(h=h)

#136: Suggestion: Custom Python message extractor in the Babel plugin

$
0
0

I use a gettext wrapper function with slightly modified semantics. I have written a Python message extractor for it, and now I would like to use the same extractor also in Mako. Would it be possible to specify the extract_python function to be should be used in mako.ext.babelplugin:extract_nodes ?

A simple solution would be along the lines of:

extractor = options.get('python_extract_function', extract_python)

and then calling extractor instead of extract_python directly.

Or, the babel.messages.extract:extract function could be called directly, for access to Babel's dispatching mechanism (with a slight backwards incompatibility):

from babel.messages.extract import extract as babel_extract
...
method = options.get('python_extractor', 'python')

and call babel_extract(method, ...) instead of extract_python(...)

(Sorry for filing this under the "runtime" component, it doesn't fit in any of the available ones.)

#199: steal/port jinja2's debug.py exception rewriting logic

$
0
0

The mako-render render script is useful for rendering templates in a non-html environment (eg I use it to generate c++ code ...)

It currently doesn't produce usable tracebacks when there is an error in the template. It should do something like

try:print render(data)except:frommakoimport exceptions
    fromsysimport stderr
    print>> sys.stderr, exceptions.text_error_template().render()

in main()

#184: Template.render_context(context) (re)sets context['self']

$
0
0

I'm not quite positive that this is a bug, but I’m pretty sure it is.

When Template.render_context() is called, it sets contextself?. So, if one renders another template like this:

subtemplate.render_context(context)

After the call to render_context(), contextself? no longer contains the correct namespace. This (at least) causes problems for any <%block>s in the calling template.

I've attached a short test script which demonstrates the problem.

#172: Clarify license in _ast_util.py

$
0
0

mako/_ast_util.py has the standard mako header at the top listing copyright holder as the mako authors and license terms as MIT. But the docstring that immediately follows says that the copyright holder is Armin Ronacher and license is the Python License.

These are compatible so it's not a big deal whatever permutation this turns out to be but it would be great to get clarification in the header of whether this file is actually under the Python or MIT license or both.

#171: default filters should be applied last

$
0
0

Maybe I am wrong here, but shouldn't default filters such as unicode() be applied last? The fact that it's done the exactly opposite way makes it a pain, as we are limited to deal with the string/unicode representation of whatever variable is passed to the filter.

Hence, I propose the following change:

  • mako/codegen.py

    diff -r 428b38caa618 mako/codegen.py
    a b  
    669669                if self.compiler.pagetag: 
    670670                    args = self.compiler.pagetag.filter_args.args + args 
    671671                if self.compiler.default_filters: 
    672                     args = self.compiler.default_filters + args 
     672                    args = args + self.compiler.default_filters 
    673673        for e in args: 
    674674            # if filter given as a function, get just the identifier portion 
    675675            if e == 'n': 

What do you think?

Cheers,

Pedro

#168: variables implicitly passed to block cause unexpected error for def

$
0
0

Try out the following 3-level inheritance setup, stripped down to show only the situation I want to point out:

Test setup:

#base.mako:
<%block name="foo"/>
#middle.mako:
<%inherit file="base.mako"/>
<%block name="foo">foo</%block>
#final.mako:
<%inherit file="middle.mako"/>
<%block name="foo">
${parent.foo()}
</%block>
# test script:
from mako.template import Template
from mako.lookup import TemplateLookup
mylookup = TemplateLookup(directories=['.'], module_directory='.')
if __name__ == '__main__':
    mytemplate = mylookup.get_template('final.mako')
    print mytemplate.render(**{'c': 'foo'})

OK, that works fine. Actually it's doing a really great job of helping me "normalize" and modularize the templating for my site, helps keep it all D.R.Y., etc.

Now let's say a coworker who's unaware of Mako 0.4.1 and its handy new "block"s, who was working on our project a few months back when it was built on defs instead, goes to add another template at the level of final.mako, and uses the old syntax we had for the project. We forgot to tell him that our template inheritance API changed and that he needs to use a block where he used to use a def in this case. So as far as he knows we use defs for inheritance as we used to. Let's say he's lazy and hasn't re-read the middle and base templates lately, he just wants to inherit from them as he always did before. He creates the following:

#problem.mako
<%inherit file="middle.mako">
<%def name="foo()">
${parent.foo()}
</%def>

Here's the point of this ticket. He gets this error:

TypeError: render_foo() got an unexpected keyword argument 'c'

That's not too far off; ideally he would reason that the source of the problem has something to do with something calling something with args when it doesn't expect them. But remember this guy has no idea he's on Mako 0.4.1 and that blocks exist or that middle.mako and base.mako have been converted to use blocks instead of defs. So he's not thinking about pageargs or lack thereof. Instead he goes on a wild goose chase asking the server guys why they're sending this variable 'c' in the context when they didn't used to. In fact they've always been sending in 'c', it just happens that 'c' is there for legacy reasons and has never been used in this project, so this guy never dealt with it before and he thinks its sudden appearance is the problem.

Ok, that's very made-up, but the point is, our hypothetical developer perhaps ought to get an error saying that a block is trying to call a def where a block is expected. Actually the current TypeError is accurate and appropriate, but maybe it should be augmented by a bit of suggestion text e.g. "make sure you're not unknowingly mixing defs and blocks."

#160: add source namespace to get_def() ?

$
0
0

When render() is called, runtime will pull out the requested namespace after _populate_self_namespace is called and effectively run whatever named def relative to that namespace, such as self.

The feature would look like:

classTemplate(object):# ...defget_def(self, name, via_namespace=None):# ...

Below is not the patch but this is the kind of tinkering we'd need

  • mako/runtime.py

    diff -r b03678de9faf mako/runtime.py
    a b  
    575575                            **_kwargs_for_callable(callable_, data)) 
    576576    return context._pop_buffer().getvalue() 
    577577 
     578def _get_self(tmpl, callable_, args, data, as_unicode=False): 
     579    buf = util.StringIO() 
     580    context = Context(buf, **data) 
     581    context._outputting_as_unicode = as_unicode 
     582    context._with_template = tmpl 
     583    (inherit, lclcontext) = _populate_self_namespace(context, tmpl) 
     584    return buf, context._data['self'] 
     585 
    578586def _kwargs_for_callable(callable_, data): 
    579587    argspec = inspect.getargspec(callable_) 
    580588    # for normal pages, **pageargs is usually present 
     
    609617        # otherwise, call the actual rendering method specified 
    610618        (inherit, lclcontext) = _populate_self_namespace(context, tmpl.parent) 
    611619        _exec_template(callable_, context, args=args, kwargs=kwargs) 
    612   
     620 
    613621def _exec_template(callable_, context, args=None, kwargs=None): 
    614622    """execute a rendering callable given the callable, a 
    615623    Context, and optional explicit arguments 
  • mako/template.py

    diff -r b03678de9faf mako/template.py
    a b  
    304304                                context,  
    305305                                *args,  
    306306                                **kwargs) 
    307   
     307 
     308    def get_self(self, *args, **data): 
     309        return runtime._get_self( 
     310            self,  
     311            self.callable_, 
     312            args,  
     313            data 
     314        ) 
     315 
    308316    def has_def(self, name): 
    309317        return hasattr(self.module, "render_%s" % name) 
    310318  

#111: mention defs can return data / better buffering explanation

$
0
0

Today I (finally) got how "buffering" works.

I think documentation could do better at explaining how this things work behind mako scenes.

First of all, all ${ call_some_function() } *should* be changed to <% call_some_function() %> for sake of understanding.

Secondly, it would be wise to mention that defs can return values. Example:

<%def name="hello_world()">
    hello world
    <% return True %>
<%/dev>
<%
   success = hello_world() ## also renders the body because of buffering
%>

that's my two cents:)

#85: need to not call imp.load_source to work with GAE

$
0
0

Per a comment here:  http://code.google.com/p/appengine-monkey/wiki/Pylons

I was briefly confused by the following error:

Error - <type 'exceptions.AttributeError'>: 'module' object has no attribute 'load_source'

I had pointed my development.ini to the default one created by Pylons - which has caching turned on. This makes Mako attemp to call imp.load_source, which isnt part of GAE. Turned off caching and it works like a charm.

#52: document dynamic inheritance

$
0
0

the template: <%inherit file="${layout}"/>

the problem: NameError?: global name 'layout' is not defined

when replacing the <%inherit %> with ${layout} the proper layout string is displayed

the solution (thanks to pjenvey): <%inherit file="${context.get('layout')}"/>

#17: More descriptive error message when missing required arguments for a template

$
0
0

When a template takes an argument like <%page args="x" /> and x is not provided, it yields the following error:

exceptions.TypeError?: render_body() takes exactly 2 arguments (1 given)

I think we should add some more explicit reason of what's missing. Like "page.html takes exactly 2 arguments (1 given). Missing required argument x."

#198: no mention whatsoever of **pageargs in the inheritance chapter

$
0
0

ideally all the body() calls should have it

#211: Enhancing documentation about filters

$
0
0

Mako provide cool filters, but I think documentation can be enhanced explaining, in HTML, where to use which filter. I mean, how to filter this :

   ${val1} <${val2} src="${val3}"/>

I was searching the right way to escape values of attributes, and got hard times to find it, Typically I'm a backend developper, not a front end, so I know that things has to be contextually escaped, but I don't exactly know which method escapes for which context.

So, presenting flags in  http://docs.makotemplates.org/en/latest/filtering.html as a table, with 'name', 'explanation', 'usage contexts', 'example' should be usefull.

#210: Missing documentation about parameters of render()

$
0
0

I'm searching if render can take an "object" like with properties, of a "dict" like with values, or only parameters, and I can't find it in the documentation, I think it's a cool thing to add.


#215: warn/raise when a def/block is named "body"

$
0
0

Hi,

I was trying out mako and found a peculiar issue. If I have the name of a block as "body" the inheritance won't work. I am attaching the output of before and after ... this is a very simple example.

## layout.html <title> Hello </title> <%block name="body">Parent body </%block>

## show_entries.html

<%inherit file="layout.html" />

<%block name="body" > Body of show entries </%block>

## Code for rendering

templ = temp_lookup.get_template('show_entries.html') print templ.render()

## Output :

In [64]: print templ.render() Parent body

In [65]: print templ.render() Parent body

In [66]: templ = temp_lookup.get_template('show_entries.html')

In [67]: print templ.render() Parent body

## After changing the name="body" to name="body_2" in both

In [68]: templ = temp_lookup.get_template('show_entries.html') In [69]: print templ.render()

<title> Hello </title>

Body of show entries

#218: Allow control statements (if, else, endif, etc.) to be closed so they can be inlined

$
0
0

In line with the discussion here:

http://groups.google.com/group/mako-discuss/browse_thread/thread/835ab6db0bb0cdb4

The pertinent parts quoted:

However, if the case is that Jinja2's (% if <expr> %}, because it has a
closing %} allows it to be inlined like {% if <expr> %} <html> {% else %}
<html> {% endif %}, then I'd want to think a bit bigger here.   I'd want to
go into match_control_line() as we did and just find some way to make the
newline optional:
% if <expr>:\n
    <html>\n
% else:\n
   <html>\n
% endif\n
we could perhaps just co-opt the { } verbosity:
{% if <expr>:}  <html> {% else:} <html> {% endif}
or just rip them off totally:
{% if <expr> %}  <html> {% else %} <html> {% endif %}
either of the above would require a rewritten (either in-place or additional
version of) match_control_line(), as we'd be doing the same kind of matching
which we do in match_expression(), which is that we need to make use of
parse_until_text() so that we properly skip over anything that might be
Python code.     I'd want the two formats to be completely interchangeable:
% if expr:
<html> {% else %} <html>
% endif
{% if <expr> %} <html>
% elif <expr>:
<html>
% else:
<html> {% endif %}
just some ideas but I'd need someone to be motivated to help patch out
lexer.py and add new tests as well.

I've frequently used Python's native 1 if 1 else 0 syntax, but it doesn't always seem ideal.

This is the only thing I can think of that other template languages can do that I wish Mako had.

Thank you for making Mako.

#217: Idea: local variable caching of filters/filter stacks

$
0
0

Analyzing the generated .py files from my current project, there's lots of this pattern, as my default_filters are ['h', 'unicode']:

        __M_writer(unicode(filters.html_escape(x)))
        __M_writer(u'some_constant_stuff')
        __M_writer(unicode(filters.html_escape(y)))
        __M_writer(u'more_constant_stuff')
        __M_writer(unicode(filters.html_escape(z)))
        __M_writer(u'even_more_constants')

so it would seem to make sense, to reduce name lookups (in favor of LOAD_FAST) to either

  • cache the filter callables as locals in the function (as is being done with __M_writer) to something like
    __M_f_unicode = unicode
    __M_f_filters__html_escape = filters.html_escape
    
  • and/or maybe better yet create a single cached callable for all of these filter "stacks":
    __M_f_unicode___filters__html_escape =
      lambda *args,**kwargs:
        __M_f_unicode(__M_f_filters__html_escape(*args,**kwargs))
    
    and have the codegen use those instead.

I haven't studied the codegen more deeply to find out what sort of magic this would require though :)

#222: Dict can not be passed to a function when using the “custom tag” format

$
0
0

A SyntaxError? (unexpected EOF) is raised when trying to pass a dict.

<%form:form id="service-form"
    action="${request.current_route_url(action='update')}"
    buttons="${False}"
    data_attrs="${ {'data-form-primary': ''} }">

I am using mako 0.8.1, python 2.7 on OSX 10.8.

A workaround is to use the dict constructor or to declare the dict before passing it

e.g.

<% data_attr={'data-form-primary':''}%><%form:form id="service-form"
    action="${request.current_route_url(action='update')}"
    buttons="${False}"
    data_attrs="${ data_attr }">

#223: TGPlugin.render method doesn't support unicode template names

$
0
0
Traceback (most recent call last):
  File "/Users/vm/ws/mako/test/test_tgplugin.py", line 48,in test_render
    assert result_lines(tl.render({}, template=u'/index.html'))==[
  File "/Users/vm/ws/mako/mako/ext/turbogears.py", line 57,in render
    return template.render(**info)AttributeError:'unicode'object has no attribute 'render'

Pull request: https://github.com/zzzeek/mako/pull/5