Allow restricting the use of template data as magical globals
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 459
- Forks
- 90
- PR merge metrics
- No merged PRs in 30d
Description
Migrated issue, originally created by eevee (@eevee)
For big projects with big collections of big templates, having a set of super-global variables that aren't documented and might vary by caller starts to get really thorny and confusing. There are a few features that partially help this problem:
strict_undefinedmakes sure you don't use anything you don't pass in, but it only applies when some function is actually called (and doesn't apply at all for Python-land functions that use the context). Slightly better than Python semantics, sure, but linters are easier to come by for Python than for Mako.<%page args>provides some documentation and enforces that some minimum set of arguments are provided, which is great. But any extra variables are still added to the context (even though they also go intopageargs), and I think (not sure?) that even the explicitly named arguments are still context globals.
I don't see how to fix this outside of Mako without doing something really gross, but on the other hand Mako tries really hard not to be too opinionated.
I think the least-intrusive, most-helpful thing would be to add an argument to <%page> (opaque, maybe?) that does two things: shadows the context data when a function declared in that template is called, and doesn't populate the context with extra kwargs when body is rendered directly. So this would fail:
mako.template.Template(filename='a.mako').render(request=...)
# a.mako
<%namespace name="lib" file="lib.mako" />
${lib.print_link("hello world")}
# lib.mako
<%page opaque />
<%def name="print_link(title)">
<a href="${request.route_url(...)}">${title}</a>
</%def>
...because request doesn't exist inside print_link.
Then you could opt in on a per-template basis; for example, keep the default behavior for templates that render entire pages (which is reasonable), but use opaque for shared code where the callers aren't all immediately obvious.
Doesn't cover the case of a Python module imported as a namespace, but at least in that case it's plainly obvious when you're relying on non-arguments.
I think I could implement this, if the idea is okay.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by tracing how <%%page> arguments, template context data, and <%%def> calls interact during Template.render(), using the a.mako and lib.mako examples in the issue. Define the behavior of an opt-in opaque page for called template functions and direct body rendering, including how extra kwargs are handled; done means the proposed cases behave as specified and existing default behavior remains unchanged.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- backend
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 30/100