Mako shadows the built-in next() function

37 views
Skip to first unread message

Peter Slížik

unread,
Mar 5, 2020, 8:11:59 AM3/5/20
to Mako Templates for Python
I'm writing some coroutine-based text generator (think of the old yield-based coroutines described in PEP 342).

The next() function is a part of the generator API. In coroutine context, it is used to start the coroutine before sending it values using send().

Mako uses the top-level next identifier to refer to the next template in the inheritance hierarchy.

In Python 2, the next() function is used as an attribute of the coroutine object, like this:

coro = coroutine()
coro.next()
coro.send(...)

However, in Python 3 it has been renamed to __next__() and the typical way of calling it is using the built-in next() function.

coro = coroutine()
next(coro)
coro.send()

Clearly, Mako's next identifier shadows the built-in next() function. Does Mako support any way to resolving this clash?

Never shadow the built-ins! :)

Mike Bayer

unread,
Mar 5, 2020, 9:16:03 AM3/5/20
to mako-d...@googlegroups.com


On Thu, Mar 5, 2020, at 8:11 AM, Peter Slížik wrote:
I'm writing some coroutine-based text generator (think of the old yield-based coroutines described in PEP 342).

The next() function is a part of the generator API. In coroutine context, it is used to start the coroutine before sending it values using send().

Mako uses the top-level next identifier to refer to the next template in the inheritance hierarchy.

In Python 2, the next() function is used as an attribute of the coroutine object, like this:

coro = coroutine()
coro.next()
coro.send(...)

so fun fact, the next() standalone, which is not just for coroutines but also for iterables, was introduced in Python 2.6.  Mako was introduced in January 2007 almost two years before Python 2.6 was first released.     It's an old library and making syntax changes is not really simple.


However, in Python 3 it has been renamed to __next__() and the typical way of calling it is using the built-in next() function.

coro = coroutine()
next(coro)
coro.send()

Clearly, Mako's next identifier shadows the built-in next() function. Does Mako support any way to resolving this clash?

All of Python's built-in functions are available in it's own namespace called exactly that:  https://docs.python.org/3/library/builtins.html

so you can import this and make use of it:

from mako.lookup import TemplateLookup


l = TemplateLookup()

l.put_string("base", """
    <%!
        import builtins

    %>
    <%
        some_iterator = iter([1, 2, 3])
    %>

    I'm the base.

    ${next.body()}

    Here's some Python next:

    ${builtins.next(some_iterator)}
    ${builtins.next(some_iterator)}
    ${builtins.next(some_iterator)}

""")

l.put_string("tmpl", """
    <%inherit file="base"/>
    I'm the template.



""")

print(l.get_template("tmpl").render())





Never shadow the built-ins! :)

This is unavoidable if Python adds new builtin functions that Mako has had for many years prior.  Since the Python builtin functions are less commonly used in a Mako template vs. Mako's own builtins, using the Python builtin namespace has always been the simplest way of accessing both namespaces simultaneously.





--
You received this message because you are subscribed to the Google Groups "Mako Templates for Python" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mako-discuss...@googlegroups.com.

Peter Slížik

unread,
Mar 10, 2020, 5:15:43 AM3/10/20
to Mako Templates for Python

That explanations dotted the i's and crossed the t's. Thank you a lot!
Reply all
Reply to author
Forward
0 new messages