Edgewall Software

Changes between Version 8 and Version 9 of TracDev/PortingFromClearSilverToGenshi


Ignore:
Timestamp:
Feb 23, 2016, 8:34:36 PM (4 years ago)
Author:
figaro
Comment:

Cosmetic changes

Legend:

Unmodified
Added
Removed
Modified
  • TracDev/PortingFromClearSilverToGenshi

    v8 v9  
    1 [[PageOutline(2-3)]]
    2 = Porting Templates from ClearSilver to Genshi =
    3 
    4 The following documentation is by no means a replacement for the excellent documentation you'll find in the [http://genshi.edgewall.org/ Genshi] site.
    5 You should go there for a more in-depth understanding of how Genshi actually works and should be used. Here we'll focus on the differences with Clearsilver.
     1[[PageOutline(2-3,Contents)]]
     2
     3= Porting Templates from ClearSilver to Genshi
     4
     5This page describes some of the differences between Genshi and Clearsilver. It is not a replacement for the [http://genshi.edgewall.org/ Genshi documentation] and you should go there for a more in-depth understanding of how Genshi actually works and should be used.
    66
    77For migrating your own templates, a good way to start is to learn by example.
     
    1313In Trac [milestone:0.13], this support has been dropped (r10405), effectively making the migration to Genshi templates mandatory.
    1414
    15 == Changes in the template syntax ==
     15== Changes in the template syntax
    1616
    1717Most of the time, the porting is a straightforward operation.
    18 === expand a variable ===
     18
     19=== expand a variable
    1920 - Clearsilver [[xml(<b><?cs var:the_variable ?></b>)]]
    2021 - Genshi [[xml(<b>$the_variable</b>)]]
    21 === expand a simple computation ===
     22
     23=== expand a simple computation
    2224 - Clearsilver [[xml(<b><?cs var:the_variable+1 ?></b>)]]
    2325 - Genshi [[xml(<b>${the_variable+1}</b>)]]
    24 === include another template ===
     26
     27=== include another template
    2528 - Clearsilver [[xml(<?cs include:the_file.cs ?>)]]
    2629 - Genshi [[xml(<xi:include href="the_file.html"><xi:fallback/></xi:include>)]]
    27 === simple if...then (no else) ===
     30
     31=== simple if...then (no else)
    2832 - Clearsilver [[xml(<?cs if:flag ?><b>OK</b><?cs /if ?>)]]
    2933 - Genshi [[xml(<py:if test="flag"><b>OK</b></py:if>)]] or simply [[xml(<b py:if="flag">OK</b>)]]
    30 === if...then...else ===
     34
     35=== if...then...else
    3136 - Clearsilver
    32    {{{
    33 #!xml
     37   {{{#!xml
    3438<?cs if:flag ?>
    3539 <b>OK</b>
     
    3943   }}}
    4044 - Genshi
    41    {{{
    42 #!xml
     45   {{{#!xml
    4346<py:choose test="flag">
    4447  <py:when test="True">
     
    5154   }}}
    5255   or simply:
    53    {{{
    54 #!xml
     56   {{{#!xml
    5557<py:choose>
    5658 <b py:when="flag">OK</b>
     
    6062   The <py:choose>/<py:when>/<py:otherwise> is a bit heavy-weight for a simple if/else, but on the other hand, the construct is more general (think switch/case, or the equivalent choose/when/otherwise in XSLT).
    6163
    62 === iterate over a collection ===
     64=== iterate over a collection
    6365 - Clearsilver
    64    {{{
    65 #!xml
     66   {{{#!xml
    6667<ul><?cs
    6768 each:element = list ?>
     
    7172   }}}
    7273 - Genshi
    73    {{{
    74 #!xml
     74   {{{#!xml
    7575<ul>
    7676  <py:for each="element in list">
     
    8080   }}}
    8181   or simply:
    82    {{{
    83 #!xml
     82   {{{#!xml
    8483<ul>
    8584  <li py:for="element in list">$element</li>
     
    8786   }}}
    8887
    89 === define a macro ===
     88=== define a macro
    9089 - Clearsilver
    91    {{{
    92 #!xml
     90   {{{#!xml
    9391<?cs def:entry(key, val)?>
    9492 <dt><?cs var:key ?></dt><dd><?cs var:val ?></dd>
     
    9694   }}}
    9795 - Genshi
    98    {{{
    99 #!xml
     96   {{{#!xml
    10097<py:def function="entry(key, val='--')">
    10198 <dt>$key</dt><dd>$val</dd>
     
    104101   As you can see, with Genshi it's also easy to specify default values for the macro arguments.
    105102
    106 === set a variable ===
     103=== set a variable
    107104 - Clearsilver
    108    {{{
    109 #!xml
     105   {{{#!xml
    110106<?cs set:count = len(collection) ?>
    111107We have <?cs if:count > 10 ?>too much<?cs else ?><?cs var:count ?><?cs /if ?> elements.
    112108   }}}
    113109 - Genshi
    114    {{{
    115 #!xml
     110   {{{#!xml
    116111<py:with vars="count = len(collection)">
    117112We have ${count &gt; 10 and 'too much' or count} elements.
     
    120115   Note that we had to use `&gt;` in Genshi, instead of directly `>` as in Clearsilver.
    121116
    122 === Examples ===
    123 Let's first take a simple full-contained example from the Trac source, the simple index.cs / index.html templates.
     117=== Examples
     118
     119Let's first take a simple full-contained example from the Trac source, the simple index.cs / index.html templates:
    124120
    125121 - Clearsilver [source:trunk/templates/index.cs@3725 index.cs]:
    126    {{{
    127 #!xml
     122   {{{#!xml
    128123<!DOCTYPE html
    129124    PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
     
    145140   }}}
    146141 - Genshi [source:sandbox/genshi/templates/index.html@3728 index.html]:
    147    {{{
    148 #!xml
     142   {{{#!xml
    149143<!DOCTYPE html
    150144    PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
     
    173167
    174168Some remarks:
    175  - Note the possible use of multiple genshi attributes in the same element
    176    (in the above, the `<li>` element has a `py:for` and a `py:choose` attribute).
    177  - When there's only one element to output conditionally, one should use a genshi attribute
    178    (the `py:for="project in projets"` and the `py:when="project.href"` in the above).
    179    Otherwise, one should use a genshi element (here, the `<py:otherwise>`).
    180  - In this small example, there's no common Trac layout used (as the index is a bit special).
    181    For how a "normal" template looks like, see for example
    182    [source:sandbox/genshi/templates/diff_form.html@3831 diff_form.html], another small template.
     169 - Note the possible use of multiple Genshi attributes in the same element: in the above, the `<li>` element has a `py:for` and a `py:choose` attribute.
     170 - When there's only one element to output conditionally, use a Genshi attribute: the `py:for="project in projects"` and the `py:when="project.href"` in the above. Otherwise, use a Genshi element (here, the `<py:otherwise>`).
     171 - In this small example, there's no common Trac layout used (as the index is a bit special). For how a "normal" template looks like, see for example [source:sandbox/genshi/templates/diff_form.html@3831 diff_form.html], another small template.
    183172
    184173Note that a Genshi template can usually be rendered directly to have a taste of how it will look like:
    185174----
    186 {{{
    187 #!html
     175{{{#!html
    188176    <h1>Available Projects</h1>
    189177    <ul>
     
    201189This comes from an important property of Genshi templates: '''they must themselves be well-formed XML documents'''.
    202190
    203 That was not a constraint in Clearsilver, and sometimes the logic in those templates took "advantage" of that, e.g. by conditionally inserting end/start pairs of tags. Such templates are the hardest to port, because you actually have to think a bit... See for example the [source:sandbox/genshi/templates/query.html@3831 query.html] template.
    204 Of course, the great benefit of this constraint is that you'll end up quite naturally with well-formed content, which was far from being a trivial achievement using Clearsilver templates. Granted, you could still insert directly some non well-formed `Markup` data in your template, but again, if you use the [http://genshi.edgewall.org/wiki/Documentation/builder.html genshi.builder] ''tag'' facility for this, that's hardly a risk.
    205 
     191That was not a constraint in Clearsilver, and sometimes the logic in those templates took "advantage" of that, e.g. by conditionally inserting end/start pairs of tags. Such templates are the hardest to port, because you actually have to think a bit. See for example the [source:sandbox/genshi/templates/query.html@3831 query.html] template.
     192Of course, the great benefit of this constraint is that you'll end up quite naturally with well-formed content, which was far from being a trivial achievement using Clearsilver templates. You could still insert directly some non well-formed `Markup` data in your template, but if you use the [http://genshi.edgewall.org/wiki/Documentation/builder.html genshi.builder] ''tag'' facility for this, that's hardly a risk.
    206193
    207194Another example from Trac, a bit more complex.
    208 This illustrates how to use `<py:def>` and `<py:with>`, to convert a Clearsilver macro using `<?cs def: ?>` and `<?cs set: ?>`.
     195This illustrates how to use `<py:def>` and `<py:with>`, to convert a Clearsilver macro using `<?cs def: ?>` and `<?cs set: ?>`:
    209196
    210197 - Clearsilver
    211    {{{
    212 #!xml
     198   {{{#!xml
    213199def:browser_path_links(path, file) ?><?cs
    214200<?cs set:first = #1 ?><?cs
     
    224210   }}}
    225211 - Genshi
    226    {{{
    227 #!xml
     212   {{{#!xml
    228213  <py:def function="browser_path_links(path_links)">
    229214    <py:for each="idx, part in enumerate(path_links)">
     
    238223   }}}
    239224
    240 
    241 == Changes in the controllers ==
    242 
    243 === Implementing the `IRequestHandler` interface ===
     225== Changes in the controllers
     226
     227=== Implementing the `IRequestHandler` interface
     228
    244229Previously, all the data fed to a template had to be placed inside the `req.hdf` HDF wrapper object.
    245 With Genshi, the data for the template is basically a `dict`, which has to be returned by `process_request`
    246 at the same time as the template name. Check [source:sandbox/genshi/trac/wiki/web_ui.py@3831 trac.wiki.web_ui] for an example.
    247 
    248 === Generating content ===
     230With Genshi, the data for the template is basically a `dict`, which has to be returned by `process_request` at the same time as the template name. Check [source:sandbox/genshi/trac/wiki/web_ui.py@3831 trac.wiki.web_ui] for an example.
     231
     232=== Generating content
     233
    249234When one wants to directly render a template, the Chrome component facilities should be used.
    250 Check the [source:sandbox/genshi/trac/web/chrome.py@3730#L422 Chrome.load_template]
    251 and `render_method` methods. Note however that this API is still rapidly evolving.
     235Check the [source:sandbox/genshi/trac/web/chrome.py@3730#L422 Chrome.load_template] and `render_method` methods. Note however that this API is still rapidly evolving.
    252236
    253237Usage examples:
     
    255239 - Sending [source:sandbox/genshi/trac/notification.py@3725#L99 notification] e-mails
    256240
    257 == Debugging ==
    258 
    259 Genshi is very different from ClearSilver. For ClearSilver the possibilities was essentially defined by the syntax + the HDF dataset that was available. Genshi evaluates Python, and operates in a Python context that makes a large number of objects directly available for use. However, doing `?hdfdump=1` on a Genshi template will only show a fraction of this content - whatever is added to the dictionary returned from the request handler and post-processors. Where is the project name? Where is the chrome links? Permissions?
     241== Debugging
     242
     243Genshi is very different from ClearSilver. For ClearSilver the possibilities were essentially defined by the syntax + the HDF dataset that was available. Genshi evaluates Python, and operates in a Python context that makes a large number of objects directly available for use. However, doing `?hdfdump=1` on a Genshi template will only show a fraction of this content - whatever is added to the dictionary returned from the request handler and post-processors. Where is the project name? Where is the chrome links? Permissions?
    260244
    261245Here is a starting point for getting insight into the context, and help debugging your own templates. It is an example `site.html` file that can be added to global or project 'templates' folder, and which adds a debug output to all pages viewed. If you already have a `site.html`, just add the `<body py:match=...` element to the bottom of your own file. It contains massive amounts of information; use, trim, add to, and re-style to suit your particular needs.
    262246
    263 '''Note of warning:''' The debug prints out a lot of things. More often than not that works fine. However, in certain circumstances it could be that it tries to access something that cannot be represented as intended. The response is usually a somewhat cryptic error. When developing, the first instinct is often to re-check your own code (as you were developing when the error occured). Your first instinct should actually be: Comment out/disable the debug printing and try again - make sure it is not an error provoked by rummaging around in areas that was never meant for wrapping in `repr()`...
    264 
    265 {{{
    266 #!xml
     247'''Note of warning:''' The debug prints out a lot of things. More often than not that works fine. However, in certain circumstances it could be that it tries to access something that cannot be represented as intended. The response is usually a somewhat cryptic error. When developing, the first instinct is often to re-check your own code (as you were developing when the error occured). Your first instinct should actually be: Comment out/disable the debug printing and try again - make sure it is not an error provoked by rummaging around in areas that were never meant for wrapping in `repr()`.
     248
     249{{{#!xml
    267250<html xmlns="http://www.w3.org/1999/xhtml"
    268251       xmlns:py="http://genshi.edgewall.org/"
     
    322305</html>
    323306}}}
    324