Changes between Version 8 and Version 9 of TracDev/PortingFromClearSilverToGenshi
- Timestamp:
- Feb 23, 2016, 8:34:36 PM (8 years ago)
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 5 This 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. 6 6 7 7 For migrating your own templates, a good way to start is to learn by example. … … 13 13 In Trac [milestone:0.13], this support has been dropped (r10405), effectively making the migration to Genshi templates mandatory. 14 14 15 == Changes in the template syntax ==15 == Changes in the template syntax 16 16 17 17 Most of the time, the porting is a straightforward operation. 18 === expand a variable === 18 19 === expand a variable 19 20 - Clearsilver [[xml(<b><?cs var:the_variable ?></b>)]] 20 21 - Genshi [[xml(<b>$the_variable</b>)]] 21 === expand a simple computation === 22 23 === expand a simple computation 22 24 - Clearsilver [[xml(<b><?cs var:the_variable+1 ?></b>)]] 23 25 - Genshi [[xml(<b>${the_variable+1}</b>)]] 24 === include another template === 26 27 === include another template 25 28 - Clearsilver [[xml(<?cs include:the_file.cs ?>)]] 26 29 - 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) 28 32 - Clearsilver [[xml(<?cs if:flag ?><b>OK</b><?cs /if ?>)]] 29 33 - 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 31 36 - Clearsilver 32 {{{ 33 #!xml 37 {{{#!xml 34 38 <?cs if:flag ?> 35 39 <b>OK</b> … … 39 43 }}} 40 44 - Genshi 41 {{{ 42 #!xml 45 {{{#!xml 43 46 <py:choose test="flag"> 44 47 <py:when test="True"> … … 51 54 }}} 52 55 or simply: 53 {{{ 54 #!xml 56 {{{#!xml 55 57 <py:choose> 56 58 <b py:when="flag">OK</b> … … 60 62 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). 61 63 62 === iterate over a collection ===64 === iterate over a collection 63 65 - Clearsilver 64 {{{ 65 #!xml 66 {{{#!xml 66 67 <ul><?cs 67 68 each:element = list ?> … … 71 72 }}} 72 73 - Genshi 73 {{{ 74 #!xml 74 {{{#!xml 75 75 <ul> 76 76 <py:for each="element in list"> … … 80 80 }}} 81 81 or simply: 82 {{{ 83 #!xml 82 {{{#!xml 84 83 <ul> 85 84 <li py:for="element in list">$element</li> … … 87 86 }}} 88 87 89 === define a macro ===88 === define a macro 90 89 - Clearsilver 91 {{{ 92 #!xml 90 {{{#!xml 93 91 <?cs def:entry(key, val)?> 94 92 <dt><?cs var:key ?></dt><dd><?cs var:val ?></dd> … … 96 94 }}} 97 95 - Genshi 98 {{{ 99 #!xml 96 {{{#!xml 100 97 <py:def function="entry(key, val='--')"> 101 98 <dt>$key</dt><dd>$val</dd> … … 104 101 As you can see, with Genshi it's also easy to specify default values for the macro arguments. 105 102 106 === set a variable ===103 === set a variable 107 104 - Clearsilver 108 {{{ 109 #!xml 105 {{{#!xml 110 106 <?cs set:count = len(collection) ?> 111 107 We have <?cs if:count > 10 ?>too much<?cs else ?><?cs var:count ?><?cs /if ?> elements. 112 108 }}} 113 109 - Genshi 114 {{{ 115 #!xml 110 {{{#!xml 116 111 <py:with vars="count = len(collection)"> 117 112 We have ${count > 10 and 'too much' or count} elements. … … 120 115 Note that we had to use `>` in Genshi, instead of directly `>` as in Clearsilver. 121 116 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 119 Let's first take a simple full-contained example from the Trac source, the simple index.cs / index.html templates: 124 120 125 121 - Clearsilver [source:trunk/templates/index.cs@3725 index.cs]: 126 {{{ 127 #!xml 122 {{{#!xml 128 123 <!DOCTYPE html 129 124 PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" … … 145 140 }}} 146 141 - Genshi [source:sandbox/genshi/templates/index.html@3728 index.html]: 147 {{{ 148 #!xml 142 {{{#!xml 149 143 <!DOCTYPE html 150 144 PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" … … 173 167 174 168 Some 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. 183 172 184 173 Note that a Genshi template can usually be rendered directly to have a taste of how it will look like: 185 174 ---- 186 {{{ 187 #!html 175 {{{#!html 188 176 <h1>Available Projects</h1> 189 177 <ul> … … 201 189 This comes from an important property of Genshi templates: '''they must themselves be well-formed XML documents'''. 202 190 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 191 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. 192 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. 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. 206 193 207 194 Another 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: ?>` .195 This illustrates how to use `<py:def>` and `<py:with>`, to convert a Clearsilver macro using `<?cs def: ?>` and `<?cs set: ?>`: 209 196 210 197 - Clearsilver 211 {{{ 212 #!xml 198 {{{#!xml 213 199 def:browser_path_links(path, file) ?><?cs 214 200 <?cs set:first = #1 ?><?cs … … 224 210 }}} 225 211 - Genshi 226 {{{ 227 #!xml 212 {{{#!xml 228 213 <py:def function="browser_path_links(path_links)"> 229 214 <py:for each="idx, part in enumerate(path_links)"> … … 238 223 }}} 239 224 240 241 == Changes in the controllers == 242 243 === Implementing the `IRequestHandler` interface === 225 == Changes in the controllers 226 227 === Implementing the `IRequestHandler` interface 228 244 229 Previously, 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 === 230 With 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 249 234 When 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. 235 Check 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. 252 236 253 237 Usage examples: … … 255 239 - Sending [source:sandbox/genshi/trac/notification.py@3725#L99 notification] e-mails 256 240 257 == Debugging ==258 259 Genshi is very different from ClearSilver. For ClearSilver the possibilities w asessentially 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 243 Genshi 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? 260 244 261 245 Here 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. 262 246 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 267 250 <html xmlns="http://www.w3.org/1999/xhtml" 268 251 xmlns:py="http://genshi.edgewall.org/" … … 322 305 </html> 323 306 }}} 324