diff --git a/doc/build/content/caching.txt b/doc/build/content/caching.txt index 7b0e178ae55a038b95bb3ca1190278a09376f5aa..fe6d1b2bf4491f6baf8b31401c7f841051dea3be 100644 --- a/doc/build/content/caching.txt +++ b/doc/build/content/caching.txt @@ -10,22 +10,28 @@ The above template, after being executed the first time, will store its content Caching requires that the `myghtyutils` package be installed on the system. -The cache flag can also be assigned to any `<%def>`: +The caching flag and all its options can be used with the `<%def>` tag. <%def name="mycomp" cache="true" cache_timeout="30" cache_type="memory"> other text </%def> -Above, we also illustrate a few more options which are also available on the `<%page>` tag. -Cache arguments: +### Cache arguments -- cache="false|true" - turn caching on -- cache_timeout - number of seconds in which to invalidate the cached data -- cache_type - type of caching. `memory`, `file`, `dbm`, or `memcached`. -- cache_key - the "key" used to uniquely identify this content in the cache. it defaults to the name of the function (TODO: support for multiple defs with the same name). It is an evaluable tag, so you can put a Python expression to calculate the value of the key on the fly. For example, heres a page that caches any page which inherits from it, based on the filename of the calling template: +The various cache arguments are cascaded from their default values, to the arguments specified programmatically to the `Template` or its originating `TemplateLookup`, then to those defined in the `<%page>` tag of an individual template, and finally to an individual `<%def>` tag within the template. This means you can define, for example, a cache type of `dbm` on your `TemplateLookup`, a cache timeout of 60 seconds in a particular template's `<%page>` tag, and within one of that template's `<%def>` tags `cache=True`, and that one particular def will then cache its data using a `dbm` cache and a data timeout of 60 seconds. + +The options available are: + +* cache="False|True" - turn caching on +* cache_timeout - number of seconds in which to invalidate the cached data. after this timeout, the content is re-generated on the next call. +* cache_type - type of caching. `memory`, `file`, `dbm`, or `memcached`. (TODO: describe extra arguments for memcached) +* cache_dir - In the case of the `file` and `dbm` cache types, this is the filesystem directory with which to store data files. If this option is not present, the value of `module_directory` is used (i.e. the directory where compiled template modules are stored). If neither option is available an exception is thrown. +* cache_key - the "key" used to uniquely identify this content in the cache. the total namespace of keys within the cache is local to the current template, and the default value of "key" is the name of the def which is storing its data. It is an evaluable tag, so you can put a Python expression to calculate the value of the key on the fly. For example, heres a page that caches any page which inherits from it, based on the filename of the calling template: <%page cache="true" cache_key="${self.filename}"/> ${next.body()} + + # rest of template diff --git a/doc/build/content/defs.txt b/doc/build/content/defs.txt index aa97480d21233e91bde7c45d7ea3eb7d1f5ba478..7c5c2f592f3c6be68713e5c78635c61d41ed9a4c 100644 --- a/doc/build/content/defs.txt +++ b/doc/build/content/defs.txt @@ -113,7 +113,7 @@ Assigning to a name inside of a def declares that name as local to the scope of ### Calling a def with embedded content and/or other defs {@name=defswithcontent} -A flip-side to def within def is a def call with content. This is where you call a def, and at the same time declare a block of content (or multiple blocks) that can be used by the def being called. To achieve this, the target def is invoked using the `<%call>` tag instead of the normal `${}` syntax. The target def then gets a variable `caller` placed in its context which contains references to the body of the `<%call>` tag. The default body of the tag is available via the name `body`: +A flip-side to def within def is a def call with content. This is where you call a def, and at the same time declare a block of content (or multiple blocks) that can be used by the def being called. To achieve this, the target def is invoked using the `<%call>` tag instead of the normal `${}` syntax. The target def then gets a variable `caller` placed in its context which contains a **namespace** containing the body and other defs defined within the `<%call>` tag. The body itself is referenced by the method `body()`: <%def name="buildtable()"> <table> @@ -136,7 +136,7 @@ This produces the output: </td></tr> </table> -The `body` name is executed each time its referenced. This means you can use def-call-with-content to build iterators, conditionals, etc: +The `body()` can be executed multiple times or not at all. This means you can use def-call-with-content to build iterators, conditionals, etc: <%def name="lister(count)"> % for x in range(1,count): diff --git a/doc/build/content/inheritance.txt b/doc/build/content/inheritance.txt new file mode 100644 index 0000000000000000000000000000000000000000..0e92ab01a9698aeebc0ca6d810c66b2a59ccad09 --- /dev/null +++ b/doc/build/content/inheritance.txt @@ -0,0 +1,187 @@ +Inheritance +=================== + +Using template inheritance, two or more templates can organize themselves into an **inheritance chain**, where content and functions from all involved templates can be intermixed. The general paradigm of template inheritance is this: if a template `A` inherits from template `B`, then template `A` agrees to send the executional control to template `B` at runtime (`A` is called the **inheriting** template). Template `B`, the **inherited** template, then makes decisions as to what resources from `A` shall be executed. + +In practice, it looks like this. Heres a hypothetical inheriting template, `index.html`: + + # index.html + <%inherit file="base.html"/> + + <%def name="header()"> + this is some header content + </%def> + + this is the body content. + +And `base.html`, the inherited template: + + # base.html + <html> + <body> + <div class="header"> + ${self.header()} + </div> + + ${self.body()} + + <div class="footer"> + ${self.footer()} + </div> + </body> + </html> + + <%def name="footer()"> + this is the footer + </%def> + +Here is a breakdown of the execution: + +* When `index.html` is rendered, control immediately passes to `base.html`. +* `base.html` then renders the top part of an HTML document, then calls the method `header()` off of a built in namespace called `self` (this namespace was first introduced in the Namespaces chapter in [namespaces_builtin_self](rel:namespaces_builtin_self)). Since `index.html` is the topmost template and also defines a def called `header()`, its this `header()` def that gets executed. +* Control comes back to `base.html`. Some more HTML is rendered. +* `base.html` executes `self.body()`. The `body()` function on all template-based namespaces refers to the main body of the template, therefore the main body of `index.html` is rendered. +* Control comes back to `base.html`. More HTML is rendered, then the `self.footer()` expression is invoked. +* The `footer` def is only defined in `base.html`, so being the topmost definition of `footer`, its the one that executes. If `index.html` also specified `footer`, then its version would **override** that of the base. +* `base.html` finishes up rendering its HTML and the template is complete, producing: + + <html> + <body> + <div class="header"> + this is some header content + </div> + + this is the body content. + + <div class="footer"> + this is the footer + </div> + </body> + </html> + +...and that is template inheritance in a nutshell. The main idea is that the methods that you call upon `self` always correspond to the topmost definition of that method. Very much the way `self` works in a Python class, even though Mako is not actually using Python class inheritance to implement this functionality. (Mako doesn't take the "inheritance" metaphor too seriously; while useful to setup some commonly recognized semantics, a textual template is not very much like an object-oriented class construct in practice). + +### Using the "next" namespace to produce content wrapping {@name=next} + +Sometimes you have an inheritance chain that spans more than two templates. Or maybe you don't, but youd like to build your system such that extra inherited templates can be inserted in the middle of a chain where they would be smoothly integrated. If each template wants to define its layout just within its main body, you can't just call `self.body()` to get at the inheriting template's body, since that is only the topmost body. To get at the body of the *next* template, you call upon the namespace `next`, which is the namespace of the template **immediately following** the current template. + +Lets change the line in `base.html` which calls upon `self.body()` to instead call upon `next.body()`: + + # base.html + <html> + <body> + <div class="header"> + ${self.header()} + </div> + + ${next.body()} + + <div class="footer"> + ${self.footer()} + </div> + </body> + </html> + + <%def name="footer()"> + this is the footer + </%def> + +Lets also add an intermediate template called `layout.html`, which inherits from `base.html`: + + # layout.html + <%inherit file="base.html"/> + <ul> + ${self.toolbar()} + </ul> + <div class="mainlayout"> + ${next.body()} + </div> + + <%def name="toolbar"> + <li>selection 1</li> + <li>selection 2</li> + <li>selection 3</li> + </%def> + +And finally change `index.html` to inherit from `layout.html` instead: + + # index.html + <%inherit file="layout.html"/> + + # .. rest of template + +In this setup, each call to `next.body()` will render the body of the next template in the inheritance chain (which can be written as `base.html -> layout.html -> index.html`). Control is still first passed to the bottommost template `base.html`, and `self` still references the topmost definition of any particular def. + +The output we get would be: + + <html> + <body> + <div class="header"> + this is some header content + </div> + + <ul> + <li>selection 1</li> + <li>selection 2</li> + <li>selection 3</li> + </ul> + + <div class="mainlayout"> + this is the body content. + </div> + + <div class="footer"> + this is the footer + </div> + </body> + </html> + +So above, we have the `<html>`, `<body>` and `header`/`footer` layout of `base.html`, we have the `<ul>` and `mainlayout` section of `layout.html`, and the main body of `index.html` as well as its overridden `header` def. The `layout.html` template is inserted into the middle of the chain without `base.html` having to change anything. Without the `next` namespace, only the main body of `index.html` could be used; there would be no way to call `layout.html`'s body content. + +### Using the "parent" namespace to augment defs {@name=parent} + +Lets now look at the other inheritance-specific namespace, the opposite of `next` called `parent`. `parent` is the namespace of the template **immediately preceding** the current template. What is most useful about this namespace is the methods within it which can be accessed within overridden versions of those methods. This is not as hard as it sounds and is very much like using the `super` keyword in Python. Lets modify `index.html` to augment the list of selections provided by the `toolbar` function in `layout.html`: + + # index.html + <%inherit file="layout.html"/> + + <%def name="header()"> + this is some header content + </%def> + + <%def name="toolbar()"> + # call the parent's toolbar first + ${parent.toolbar()} + <li>selection 4</li> + <li>selection 5</li> + </%def> + + this is the body content. + +Above, we implemented a `toolbar()` function, which is meant to override the definition of `toolbar` within the inherited template `layout.html`. However, since we want the content from that of `layout.html` as well, we call it via the `parent` namespace whenever we want it's content, in this case before we add our own selections. So the output for the whole thing is now: + + <html> + <body> + <div class="header"> + this is some header content + </div> + + <ul> + <li>selection 1</li> + <li>selection 2</li> + <li>selection 3</li> + <li>selection 4</li> + <li>selection 5</li> + </ul> + + <div class="mainlayout"> + this is the body content. + </div> + + <div class="footer"> + this is the footer + </div> + </body> + </html> + +and you're now a template inheritance ninja ! diff --git a/doc/build/content/namespaces.txt b/doc/build/content/namespaces.txt index c26969ea5159452c97fe64f6342dd38ecb04cf07..a1e571bf3907f2c83162186ee701787f11874e3b 100644 --- a/doc/build/content/namespaces.txt +++ b/doc/build/content/namespaces.txt @@ -71,3 +71,46 @@ The `<%namespace>` tag supports the definition of `<%defs>` directly inside the # then call it ${stuff:comp1()} +### The "body()" method {@name=body} + +Every namespace that is generated from a template contains a method called `body()`. This method corresponds to the main body of the template, and plays its most important roles when using inheritance relationships as well as def-calls-with-content. + +Since the `body()` method is available from a namespace just like all the other defs defined in a template, what happens if you send arguments to it ? By default, the `body()` method accepts no positional arguments, and for usefulness in inheritance scenarios will by default dump all keyword arguments into a dictionary called `pageargs`. But if you actually want to get at the keyword arguments, Mako recommends you define your own argument signature explicitly. You do this via using the `<%page>` tag: + + <%page args="x, y, someval=8, scope='foo', **kwargs"/> + +A template which defines the above signature requires that the variables `x` and `y` are defined, defines default values for `someval` and `scope`, and sets up `**kwargs` to receive all other keyword arguments. If `**kwargs` or similar is not present, the argument `**pageargs` gets tacked on by Mako. When the template is called as a top-level template (i.e. via `template.render()`) or via the `<%include>` tag, the values for these arguments will be pulled from the `Context`. In all other cases, i.e. via calling the `body()` method, the arguments are taken as ordinary arguments from the method call. So above, the body might be called as: + + ${self.body(5, y=10, someval=15, delta=7)} + +The `Context` object also supplies a `kwargs` accessor, for cases when youd like to pass along whatever is in the context to a `body()` callable: + + ${next.body(**context.kwargs)} + +The usefulness of calls like the above become more apparent when one works with inheriting templates. For more information on this, as well as the meanings of the names `self` and `next`, see [inheritance](rel:inheritance). + +### Namespace methods and properties {@name=properties} + +The `Namespace` class includes helpful accessors and methods: + +* `module` - the Python module referenced by this Namespace. If the namespace references a `Template`, then this module is the equivalent of `template.module`, i.e. the generated module for the template. +* `filename` - the path of the filesystem file used for this Namespace's module or template. If this is a pure module-based Namespace, this evaluates to `module.__file__`. If a template-based namespace, it evaluates to the original template file location. +* `template` - the `Template` object referenced by this Namespace, if any. +* `uri` - the uri for this Namespace's template (i.e. whatever was sent to `lookup.get_template()`). This is the equivalent of `template.uri`. +* `context` - the `Context` object for this namespace. Namespaces are often created with copies of contexts that contain slightly different data, particularly in inheritance scenarios. Using the `Context` off of a `Namespace` one can traverse an entire chain of templates that inherit from one-another. +* `get_namespace(uri)` - this method returns a `Namespace` at the given `uri`. If the given uri is a relative uri (i.e. it does not contain ia leading slash `/`), the uri is adjusted to be relative to the uri **of the namespace itself**. This method is therefore mostly useful off of the built-in `local` namespace, described in the next section. In most cases, a template wouldn't need this function, and should instead use the `<%namespace>` tag to load namespaces. However, since all `<%namespace>` tags are evaulated before the body of the template ever runs, this method can be used to locate namespaces using expressions that were generated within the body code of the template, or to conditionally use a particular namespace. + +### Built-in Namespaces {@name=builtin} + +The namespace is so great that Mako gives your template one (or two) for free. The names of these namespaces are `local` and `self`. Other built-in namespaces include `parent` and `next`, which are optional and are described in [inheritance](rel:inheritance). + +#### local + +The `local` namespace is basically the namespace for the currently executing template. This means that all of the top level defs defined in your template, as well as your template's `body()` function, are also available off of the `local` namespace. + +The `local` namespace is also where properties like `uri`, `filename`, and `module` and the `get_namespace` method can be particularly useful. + +#### self + +The `self` namespace, in the case of a template that does not use inheritance, is synonomous with `local`. If inheritance is used, then `self` references the topmost template in the inheritance chain, where it is most useful for providing the ultimate form of various "method" calls which may have been overridden at various points in an inheritance chain. See [inheritance](rel:inheritance). + diff --git a/doc/build/content/runtime.txt b/doc/build/content/runtime.txt new file mode 100644 index 0000000000000000000000000000000000000000..626dd32296a230765dd1d8ca00d5988cb03079db --- /dev/null +++ b/doc/build/content/runtime.txt @@ -0,0 +1,76 @@ +The Mako Runtime Environment {@name=runtime} +============================== + +This section describes a little bit about the objects and built-in functions that are available in templates. + +### Context {@name=context} + +The `Context` is the central object that is created when a template is first executed, and is responsible for handling all communication with the outside world. This includes two major components, one of which is the output buffer, which is a file-like object such as Python's `StringIO` or similar, and the other a dictionary of variables that can be freely referenced within a template; this dictionary is a combination of the arguments sent to the `template.render()` function and some built-in variables provided by Mako's runtime environment. + +#### The Buffer {@name=buffer} + +The buffer is stored within the `Context`, and writing to it is achieved by calling `context.write()`. You usually don't need to care about this as all text within a template, as well as all expressions provided by `${}`, automatically send everything to this method. The cases you might want to be aware of its existence are if you are dealing with various filtering/buffering scenarios, which are described in [filtering](rel:filtering), or if you want to programmatically send content to the output stream, such as within a `<% %>` block. + + <% + context.write("some programmatic text") + %> + +The actual buffer may or may not be the original buffer sent to the `Context` object, as various filtering/caching scenarios may "push" a new buffer onto the context's underlying buffer stack. For this reason, just stick with `context.write()` and content will always go to the topmost buffer. + +#### Context Variables {@name=variables} + +When your template is compiled into a Python module, the body content is enclosed within a Python function called `render_body`. Other top-level defs defined in the template are defined within their own function bodies which are named after the def's name with the prefix `render_` (i.e. `render_mydef`). One of the first things that happens within these functions is that all variable names that are referenced within the function which are not defined in some other way (i.e. such as via assignment, module level imports, etc.) are pulled from the `Context` object's dictionary of variables. This is how you're able to freely reference variable names in a template which automatically correspond to what was passed into the current `Context`. + +* **What happens if I reference a variable name that is not in the current context?** - the value you get back is a special value called `UNDEFINED`. This is just a simple global variable with the class `mako.runtime.Undefined`. The `UNDEFINED` object throws an error when you call `str()` on it, which is what happens if you try to use it in an expression. +* **Why not just return None?** Using `UNDEFINED` is more explicit and allows differentiation between a value of `None` that was explicitly passed to the `Context` and a value that wasn't present at all. +* **Why raise an exception when you call str() on it ? Why not just return a blank string?** - Mako tries to stick to the Python philosophy of "explicit is better than implicit". In this case, its decided that the template author should be made to specifically handle a missing value rather than experiencing what may be a silent failure. Since `UNDEFINED` is a singleton object just like Python's `True` or `False`, you can use the `is` operator to check for it: + + % if someval is UNDEFINED: + someval is: no value + % else: + someval is: ${someval} + % endif + +Another facet of the `Context` is that its dictionary of variables is **immutable**. Whatever is set when `template.render()` is called is what stays. Of course, since its Python, you can hack around this and change values in the context's internal dictionary, but this will probably will not work as well as you'd think. The reason for this is that Mako in many cases creates copies of the `Context` object, which get sent to various elements of the template and inheriting templates used in an execution. So changing the value in your local `Context` will not necessarily make that value available in other parts of the template's execution. Examples of where Mako creates copies of the `Context` include within top-level def calls from the main body of the template (the context is used to propigate locally assigned variables into the scope of defs; since in the template's body they appear as inlined functions, Mako tries to make them act that way), and within an inheritance chain (each template in an inheritance chain has a different notion of `parent` and `next`, which are all stored in unique `Context` instances). + +* **So what if I want to set values that are global to everyone within a template request?** - All you have to do is provide a dictionary to your `Context` when the template first runs, and everyone can just get/set variables from that. Lets say its called `attributes`. + +Running the template looks like: + + {python} + output = template.render(attributes={}) + +Within a template, just reference the dictionary: + + <% + attributes['foo'] = 'bar' + %> + 'foo' attribute is: ${attributes['foo']} + +* **Why can't "attributes" be a built-in feature of the Context?** - This is an area where Mako is trying to make as few decisions about your application as it possibly can. Perhaps you don't want your templates to use this technique of assigning and sharing data, or perhaps you have a different notion of the names and kinds of data structures that should be passed around. Once again Mako would rather ask the user to be explicit. + +#### Context Methods and Accessors {@name=accessors} + +Significant members off of `Context` include: + +* `context[key]` / `context.get(key, default=None)` - dictionary-like accessors for the context. Normally, any variable you use in your template is automatically pulled from the context if it isnt defined somewhere already. Use the dictionary accessor and/or `get` method when you want a variable that *is* already defined somewhere else, such as in the local arguments sent to a %def call. If a key is not present, like a dictionary it raises `KeyError`. +* `keys()` - all the names defined within this context. +* `kwargs` - this returns a **copy** of the context's dictionary of variables. This is useful when you want to propigate the variables in the current context to a function as keyword arguments, i.e.: + + ${next.body(**context.kwargs)} + +* `write(text)` - write some text to the current output stream. +* `lookup` - returns the `TemplateLookup` instance that is used for all file-lookups within the current execution (even though individual `Template` instances can conceivably have different instances of a `TemplateLookup`, only the `TemplateLookup` of the originally-called `Template` gets used in a particular execution). + +### All the built-in names {@name=builtins} + +A one-stop shop for all the names Mako defines. Most of these names are instances of `Namespace`, which are described in the next section, [namespaces](rel:namespaces). Also, most of these names other than `context` and `UNDEFINED` are also present *within* the `Context` itself. + +* `local` - the namespace of the current template, described in [namespaces_builtin](rel:namespaces_builtin) +* `self` - the namespace of the topmost template in an inheritance chain (if any, otherwise the same as `local`), mostly described in [inheritance](rel:inheritance) +* `parent` - the namespace of the parent template in an inheritance chain (otherwise undefined); see [inheritance](rel:inheritance) +* `next` - the namespace of the next template in an inheritance chain (otherwise undefined); see [inheritance](rel:inheritance) +* `caller` - a "mini" namespace created when using the `<%call>` tag to define a "def call with content"; described in [defs_defswithcontent](rel:defs_defswithcontent) +* `capture` - a function that calls a given def and captures its resulting content into a string, which is returned. Usage is described in [filtering_buffering](rel:filtering_buffering) +* `UNDEFINED` - a global singleton that is applied to all otherwise uninitialized template variables that were not located within the `Context` when rendering began. Is an instance of `mako.runtime.Undefined`, and raises an exception when its `__str__()` method is called. +* `pageargs` - this is a dictionary which is present in a template which does not define any **kwargs section in its `<%page>` tag. All keyword arguments sent to the `body()` function of a template (when used via namespaces) go here by default unless otherwise defined as a page argument. If this makes no sense, it shouldn't; read the section [namespaces_body](rel:namespaces_body). diff --git a/doc/build/content/syntax.txt b/doc/build/content/syntax.txt index 56aa69151a5425a7518a8d65549702cc4e545236..f47757ce9cf7d85087b1b5eedd8da33b10b2db61 100644 --- a/doc/build/content/syntax.txt +++ b/doc/build/content/syntax.txt @@ -1,7 +1,7 @@ Syntax {@name=syntax} ============================== -A Mako template is parsed from a text stream containing any kind of content, XML, HTML, email text, etc. The template can further contain Mako-specific directives which represent variable and/or expression substitutions, control structures (i.e. conditionals and loops), server-side comments, full blocks of Python code, as well as various tags that offer additional functionality. Note that all of these constructs compile into real Python code. This means that you can leverage the full power of Python in almost every aspect of a Mako template. +A Mako template is parsed from a text stream containing any kind of content, XML, HTML, email text, etc. The template can further contain Mako-specific directives which represent variable and/or expression substitutions, control structures (i.e. conditionals and loops), server-side comments, full blocks of Python code, as well as various tags that offer additional functionality. All of these constructs compile into real Python code. This means that you can leverage the full power of Python in almost every aspect of a Mako template. ### Expression Substiution @@ -121,6 +121,8 @@ This tag defines general characteristics of the template, including caching argu Or a page tag that defines caching characteristics: <%page cached="True" cache_type="memory"/> + +Currently, only one `<%page>` tag gets used per template, the rest get ignored. While this will be improved in a future release, for now make sure you have only one `<%page>` tag defined in your template, else you may not get the results you want. The details of what `<%page>` is used for are described further in [namespaces_body](rel:namespaces_body) as well as [caching](rel:caching). #### <%include> diff --git a/doc/build/content/usage.txt b/doc/build/content/usage.txt index 062ae2d572e5ffdbe16075f1dbddc097f3d59205..24815116f8127233ebcbb6f0668e1ebc5a4ef2f7 100644 --- a/doc/build/content/usage.txt +++ b/doc/build/content/usage.txt @@ -21,7 +21,7 @@ The code inside the `render_body()` function has access to a namespace of variab mytemplate = Template("hello, ${name}!") print mytemplate.render(name="jack") -The `template.render()` method calls upon Mako to create a `Context` object, which stores all the variable names accessible to the template and also defines a buffer used to capture output. You can create this `Context` yourself and have the template render with it, using the `render_context` method: +The `template.render()` method calls upon Mako to create a `Context` object, which stores all the variable names accessible to the template and also stores a buffer used to capture output. You can create this `Context` yourself and have the template render with it, using the `render_context` method: {python} from mako.template import Template diff --git a/doc/build/genhtml.py b/doc/build/genhtml.py index bb05d8bdb7ef951adc3cf64fc51a33cd59f1770d..5296bc056746002848ec5e61fdf17ab8e47c5e38 100644 --- a/doc/build/genhtml.py +++ b/doc/build/genhtml.py @@ -15,7 +15,9 @@ files = [ 'usage', 'syntax', 'defs', + 'runtime', 'namespaces', + 'inheritance', 'filtering', 'caching', ] diff --git a/doc/build/read_markdown.py b/doc/build/read_markdown.py index 097e071b904a0c762215c3ab26e7e46e643c5983..d889ab992e21f6940db998d929a28d83b949c74f 100644 --- a/doc/build/read_markdown.py +++ b/doc/build/read_markdown.py @@ -157,7 +157,8 @@ def safety_code(tree): parents = get_parent_map(tree) for code in tree.findall('.//code'): tag = et.Element('%text') - #tag.attrib["filter"] = "h" +# if parents[code].tag != 'pre': +# tag.attrib["filter"] = "h" tag.text = code.text code.append(tag) code.text = "" diff --git a/lib/mako/codegen.py b/lib/mako/codegen.py index 9ec78084d7a698f2b394b1baf4a60ecab64b6570..ea86ea1101974f68a1038a72820d21d19ea6054d 100644 --- a/lib/mako/codegen.py +++ b/lib/mako/codegen.py @@ -45,7 +45,8 @@ class _GenerateRenderMethod(object): defs = None pagetag = None else: - (pagetag, defs) = self.write_toplevel() + defs = self.write_toplevel() + pagetag = self.compiler.pagetag name = "render_body" if pagetag is not None: args = pagetag.body_decl.get_argument_expressions() @@ -56,7 +57,6 @@ class _GenerateRenderMethod(object): args = ['**pageargs'] cached = False buffered = filtered = False - self.compiler.pagetag = pagetag if args is None: args = ['context'] else: @@ -76,17 +76,18 @@ class _GenerateRenderMethod(object): inherit = [] namespaces = {} module_code = [] - pagetag = [None] encoding =[None] + self.compiler.pagetag = None + class FindTopLevel(object): def visitInheritTag(s, node): inherit.append(node) - def visitNamespaceTag(self, node): + def visitNamespaceTag(s, node): namespaces[node.name] = node - def visitPageTag(self, node): - pagetag[0] = node - def visitCode(self, node): + def visitPageTag(s, node): + self.compiler.pagetag = node + def visitCode(s, node): if node.ismodule: module_code.append(node) @@ -128,7 +129,7 @@ class _GenerateRenderMethod(object): elif len(namespaces): self.write_namespaces(namespaces) - return (pagetag[0], main_identifiers.topleveldefs) + return main_identifiers.topleveldefs def write_render_callable(self, node, name, args, buffered, filtered, cached): """write a top-level render callable. diff --git a/lib/mako/runtime.py b/lib/mako/runtime.py index 22851df8b9dd54ed877da6d9391151a609688b2b..727eb3cb3816fe28c4d14381590a2d6ed76b7915 100644 --- a/lib/mako/runtime.py +++ b/lib/mako/runtime.py @@ -110,7 +110,7 @@ class Namespace(object): if a relative uri, it is adjusted to that of the template of this namespace""" key = (self, uri) if self.context.namespaces.has_key(key): - return context.namespaces[key] + return self.context.namespaces[key] else: ns = Namespace(uri, self.context, templateuri=uri, calling_uri=self._templateuri) self.context.namespaces[key] = ns @@ -191,7 +191,7 @@ def _include_file(context, uri, calling_uri): """locate the template from the given uri and include it in the current output.""" template = _lookup_template(context, uri, calling_uri) (callable_, ctx) = _populate_self_namespace(context._clean_inheritance_tokens(), template) - callable_(ctx) + callable_(ctx, **_kwargs_for_callable(callable_, context._data)) def _inherit_from(context, uri, calling_uri): """called by the _inherit method in template modules to set up the inheritance chain at the start @@ -245,15 +245,18 @@ def _render(template, callable_, args, data, as_unicode=False): buf = util.StringIO() context = Context(buf, **data) context._with_template = template + _render_context(template, callable_, context, *args, **_kwargs_for_callable(callable_, data)) + return context.pop_buffer().getvalue() + +def _kwargs_for_callable(callable_, data): kwargs = {} argspec = inspect.getargspec(callable_) namedargs = argspec[0] + [v for v in argspec[1:3] if v is not None] for arg in namedargs: if arg != 'context' and arg in data: kwargs[arg] = data[arg] - _render_context(template, callable_, context, *args, **kwargs) - return context.pop_buffer().getvalue() - + return kwargs + def _render_context(tmpl, callable_, context, *args, **kwargs): import mako.template as template # create polymorphic 'self' namespace for this template with possibly updated context