root/livinglogic.python.www/site/Python_xmlns.py @ 527:f42bbf03cd12

Revision 527:f42bbf03cd12, 41.9 KB (checked in by Walter Doerwald <walter@…>, 12 years ago)

Make the header lower.

Line 
1# -*- coding: iso-8859-1 -*-
2
3
4from __future__ import with_statement
5
6import sys, types, inspect
7
8from ll import misc, url
9from ll.xist import xsc, sims, parsers
10from ll.xist.ns import html, chars, htmlspecials, specials, abbr, meta, doc, code, xml
11
12
13xmlns = "http://xmlns.livinglogic.de/Python"
14
15
16class Page(object):
17    """
18    A webpage in the sitemap tree.
19    This is an abstract class, that provides common
20    functionality for derived classes.
21    """
22
23    class keywords(misc.propclass):
24        def __get__(self):
25            keywords = list(self.localkeywords)
26            page = self
27            while page is not None:
28                for keyword in page.inheritablekeywords:
29                    if keyword not in keywords:
30                        keywords.append(keyword)
31                page = page.parent
32            return keywords
33
34    @misc.notimplemented
35    def getChildByIndex(self, index):
36        pass
37
38    @misc.notimplemented
39    def getChildByName(self, index):
40        pass
41
42    def getFirstSibling(self):
43        parent = self.parent
44        if parent is None:
45            return None
46        else:
47            return parent.getChildByIndex(0)
48
49    def getPrevSibling(self):
50        parent = self.parent
51        if parent is None:
52            return None
53        else:
54            sibling = None
55            for child in parent.getChildren():
56                if child is self:
57                    break
58                sibling = child
59            return sibling
60
61    def getNextSibling(self):
62        parent = self.parent
63        if parent is None:
64            return None
65        else:
66            sibling = None
67            for child in parent.getChildren():
68                if child is self:
69                    sibling = self
70                elif sibling is not None:
71                    return child
72                else:
73                    sibling = None
74            return None
75
76    def getLastSibling(self):
77        parent = self.parent
78        if parent is None:
79            return None
80        else:
81            return parent.getChildByIndex(-1)
82
83    @misc.notimplemented
84    def __len__(self):
85        pass
86
87    def getChildren(self):
88        children = []
89        index = 0
90        while True:
91            try:
92                children.append(self.getChildByIndex(index))
93            except IndexError:
94                break
95            index + 1
96        return children
97
98    def walk(self):
99        yield self
100        for child in self.getChildren():
101            for page in child.walk():
102                yield page
103
104    def __getitem__(self, index):
105        if isinstance(index, (int, long)):
106            return self.getChildByIndex(index)
107        elif isinstance(index, basestring):
108            if index=="":
109                index = []
110            else:
111                index = index.split("/")
112        if isinstance(index, (list, tuple)):
113            result = self
114            for i in index:
115                if isinstance(i, (int, long)):
116                    result = result.getChildByIndex(i)
117                elif isinstance(i, basestring):
118                    result = result.getChildByName(i)
119                else:
120                    raise TypeError("illegal index type %r" % type(i))
121            return result
122        else:
123            raise TypeError("wrong type %s for index (must be int, long, string, unicode or tuple)" % type(index))
124
125    def getPath(self):
126        path = []
127        page = self
128        while page is not None:
129            path.insert(0, page)
130            page = page.parent
131        return path
132
133    def getPathString(self):
134        return "/".join([ page.name for page in self.getPath() if page.parent])
135
136    def getRoot(self):
137        """
138        return the root page (i.e. the one without a parent)
139        """
140        parent = self
141        while 1:
142            testparent = parent.parent
143            if testparent is None:
144                return parent
145            parent = testparent
146
147    def __repr__(self):
148        return '<%s object path="%s" at 0x%x>' % (self.__class__.__name__, self.getPathString(), id(self))
149
150    def alternates(self):
151        return []
152
153
154class StaticPage(Page):
155    """
156    A webpage in the sitemap tree
157    """
158    def __init__(self, name, *children, **attrs):
159        self.parent = None
160        self.name = name
161        self.title = None
162        self.crumb = None
163        self.url = None
164        self.header = None
165        self.subheader = None
166        self.localkeywords = []
167        self.inheritablekeywords = []
168        self.linktitle = None
169        self.description = None
170        for (k, v) in attrs.items():
171            if k=="crumb":
172                self.crumb = v
173            elif k=="url":
174                self.url = v
175            elif k=="title":
176                self.title = v
177            elif k=="header":
178                self.header = v
179            elif k=="subheader":
180                self.subheader = v
181            elif k=="localkeywords":
182                self.localkeywords = v
183            elif k=="inheritablekeywords":
184                self.inheritablekeywords = v
185            elif k=="linktitle":
186                self.linktitle = v
187            elif k=="description":
188                self.description = u" ".join(v.strip().split())
189            else:
190                raise ValueError("unknown keyword %s" % k)
191        for child in children:
192            child.parent = self # this creates a cycle
193        self.__children = list(children)
194
195    def getChildByIndex(self, index):
196        return self.__children[index]
197
198    def getChildByName(self, index):
199        for child in self.__children:
200            if child.name == index:
201                return child
202        raise KeyError("unknown child %r in page %r" % (index, self.getPathString()))
203
204    def getChildren(self):
205        return self.__children
206
207    def __len__(self):
208        return len(self.__children)
209
210
211class XISTPage(StaticPage):
212    def alternates(self):
213        alternates = super(XISTPage, self).alternates()
214
215        url = self.url
216        pos = url.rfind(".")
217        if pos>=0:
218            txturl = url[:pos+1] + "txt"
219            xmlurl = url[:pos+1] + "htmlxsc"
220        else:
221            txturl = url + ".txt"
222            xmlurl = url + ".htmlxsc"
223
224        return [
225            html.a("Text", href=txturl, rel="alternate", type="text/plain", title="A plain text version of this page"),
226            html.a("XIST", href=xmlurl, rel="alternate", type="text/xml", title=("The ", abbr.xist(), " source of this page"))
227        ] + alternates
228
229
230class PythonSourcePage(XISTPage):
231    def alternates(self):
232        alternates = super(PythonSourcePage, self).alternates()
233        url = self.url
234        if url.endswith(".html"):
235            url = url[:-5] + "_module.py"
236        else:
237            url = url + "_module.py"
238        return alternates + [html.a("Python", href=url, rel="alternate", type="text/x-python", title="The Python module described in this page")]
239
240
241pages = XISTPage(u"python",
242    PythonSourcePage(u"xist",
243        XISTPage(u"examples",
244            crumb=u"Examples",
245            title=(abbr.xist(), u" examples · Python software · LivingLogic AG"),
246            header=(abbr.xist(), u" examples"),
247            subheader=(u"An introduction to ", abbr.xist(), u" by examples"),
248            url=u"root:xist/Examples.html",
249            localkeywords=[],
250            linktitle=u"XIST examples: Parsing/creating/modifying XML; Traversing XML trees"
251        ),
252        XISTPage(u"howto",
253            crumb=u"Howto",
254            title=(abbr.xist(), u" howto · Python software · LivingLogic AG"),
255            header=(abbr.xist(), u" howto"),
256            subheader=(u"A quick tour of ", abbr.xist()),
257            url=u"root:xist/Howto.html",
258            localkeywords=[],
259            linktitle=u"""
260            A quick tour of XIST: Explains parsing/generating XML files,
261            XML transformations via XIST classes and other basic concepts.
262            """
263        ),
264        XISTPage(u"searching",
265            crumb=u"Searching",
266            title=(u"Searching ", abbr.xist(), u" trees · Python software · LivingLogic AG"),
267            header=("Searching ", abbr.xist(), u" trees"),
268            subheader=("Searching, tree traversal, xfind and ", abbr.css(), " selectors"),
269            url=u"root:xist/Searching.html",
270            localkeywords=["searching", "traversal", "xfind", "css"],
271            linktitle=u"""
272            How to iterate through XIST trees
273            """
274        ),
275        XISTPage(u"transformation",
276            crumb=u"Transformation",
277            title=("Transforming ", abbr.xist(), u" trees · Python software · LivingLogic AG"),
278            header=("Transforming ", abbr.xist(), u" trees"),
279            subheader=("The ", doc.func("mapped"), " function, sorting, etc."),
280            url=u"root:xist/Transformation.html",
281            localkeywords=[],
282            linktitle=u"""
283            How to transform XIST trees
284            """
285        ),
286        XISTPage(u"advanced",
287            crumb=u"Advanced topics",
288            title=("Advanced ", abbr.xist(), u" · Python software · LivingLogic AG"),
289            header=("Advanced ", abbr.xist()),
290            subheader="Converter contexts, pool chaining, namespace extensions, conversion targets, validation",
291            url=u"root:xist/Advanced.html",
292            localkeywords=[],
293            linktitle=u"""
294            Advanced XIST features: pool chaining, converter contexts, validation
295            """
296        ),
297        XISTPage(u"misc",
298            crumb=u"Miscellaneous",
299            title=(abbr.xist(), u" miscellaneous · Python software · LivingLogic AG"),
300            header=(abbr.xist(), u" miscellaneous"),
301            subheader=(abbr.url(), u"s, pretty printing, image sizes, embedding Python code"),
302            url=u"root:xist/Misc.html",
303            localkeywords=[],
304            linktitle=u"""
305            Explains various odds and ends of XIST
306            """
307        ),
308        PythonSourcePage(u"xsc",
309            crumb=u"xsc",
310            title=(abbr.xist(), u".xsc · Python software · LivingLogic AG"),
311            header=(abbr.xist(), u".xsc"),
312            subheader=(abbr.xist(), u" core classes"),
313            url=u"root:xist/xsc/index.html",
314            linktitle=u"Module ll.xist.xsc: XIST core classes"
315        ),
316        PythonSourcePage(u"ns",
317            PythonSourcePage(u"html",
318                crumb=u"html",
319                title=(abbr.xist(), u".ns.html · Python software · LivingLogic AG"),
320                header=(abbr.xist(), u".ns.html"),
321                subheader=(u"Module implementing ", abbr.html(), u" 4.01 (with additions)"),
322                url=u"root:xist/ns/html/index.html",
323                linktitle=u"Module ll.xist.ns.html: HTML namespace",
324            ),
325            PythonSourcePage(u"xml",
326                crumb=u"xml",
327                title=(abbr.xist(), u".ns.xml · Python software · LivingLogic AG"),
328                header=(abbr.xist(), u".ns.xml"),
329                subheader=(u"Module for global attributes from the ", abbr.xml(), u" namespace"),
330                url=u"root:xist/ns/xml/index.html",
331                linktitle=u"Module ll.xist.ns.xml: Namespace implementing global XML attributes",
332            ),
333            PythonSourcePage(u"wml",
334                crumb=u"wml",
335                title=(abbr.xist(), u".ns.wml · Python software · LivingLogic AG"),
336                header=(abbr.xist(), u".ns.wml"),
337                subheader=(u"Module implementing ", abbr.wml(), u" 1.3"),
338                url=u"root:xist/ns/wml/index.html",
339                linktitle=u"Module ll.xist.ns.wml: WML 1.3 namespace",
340            ),
341            PythonSourcePage(u"ihtml",
342                crumb=u"ihtml",
343                title=(abbr.xist(), u".ns.ihtml · Python software · LivingLogic AG"),
344                header=(abbr.xist(), u".ns.ihtml"),
345                subheader=(u"Module module implementing i-mode compatible ", abbr.html()),
346                url=u"root:xist/ns/ihtml/index.html",
347                linktitle=u"Module ll.xist.ns.ihtml: Namespace implementing i-mode compatible HTML",
348            ),
349            PythonSourcePage(u"docbook",
350                crumb=u"docbook",
351                title=(abbr.xist(), u".ns.docbook · Python software · LivingLogic AG"),
352                header=(abbr.xist(), u".ns.docbook"),
353                subheader=u"Namespace module implementing DocBook 4.3",
354                url=u"root:xist/ns/docbook/index.html",
355                linktitle=u"Module ll.xist.ns.docbook: Namespace implementing DocBook 4.3",
356            ),
357            PythonSourcePage(u"svg",
358                crumb=u"svg",
359                title=(abbr.xist(), u".ns.svg · Python software · LivingLogic AG"),
360                header=(abbr.xist(), u".ns.svg"),
361                subheader=(u"Namespace module implementing ", abbr.svg(), u" 1.0"),
362                url=u"root:xist/ns/svg/index.html",
363                linktitle=u"Module ll.xist.ns.svg: Namespace implementing SVG 1.0",
364            ),
365            PythonSourcePage(u"abbr",
366                crumb=u"abbr",
367                title=(abbr.xist(), u".ns.abbr · Python software · LivingLogic AG"),
368                header=(abbr.xist(), u".ns.abbr"),
369                subheader=u"Namespace module containing many abbreviation entities",
370                url=u"root:xist/ns/abbr/index.html",
371                linktitle=u"Module ll.xist.ns.abbr: Namespace containing abbreviation entities",
372            ),
373            PythonSourcePage(u"code",
374                crumb=u"code",
375                title=(abbr.xist(), u".ns.code · Python software · LivingLogic AG"),
376                header=(abbr.xist(), u".ns.code"),
377                subheader=(u"Namespace module for embedding Python code in ", abbr.xml()),
378                url=u"root:xist/ns/code/index.html",
379                linktitle=u"Module ll.xist.ns.code: Namespace for embedding Python code in XML",
380            ),
381            PythonSourcePage(u"form",
382                crumb=u"form",
383                title=(abbr.xist(), u".ns.form · Python software · LivingLogic AG"),
384                header=(abbr.xist(), u".ns.form"),
385                subheader=u"Namespace module implementing form related elements",
386                url=u"root:xist/ns/form/index.html",
387                linktitle=u"Module ll.xist.ns.form: Namespace implementing form related elements",
388            ),
389            PythonSourcePage(u"php",
390                crumb=u"php",
391                title=(abbr.xist(), u".ns.php · Python software · LivingLogic AG"),
392                header=(abbr.xist(), u".ns.php"),
393                subheader=(u"Namespace module for PHP processing instructions"),
394                url=u"root:xist/ns/php/index.html",
395                linktitle=u"Module ll.xist.ns.php: Namespace for PHP processing instructions",
396            ),
397            PythonSourcePage(u"jsp",
398                crumb=u"jsp",
399                title=(abbr.xist(), u".ns.jsp · Python software · LivingLogic AG"),
400                header=(abbr.xist(), u".ns.jsp"),
401                subheader=(u"Namespace module for embedding ", abbr.jsp(), u" code as processing instructions"),
402                url=u"root:xist/ns/jsp/index.html",
403                linktitle=u"Module ll.xist.ns.jsp: Namespace for JSP code as processing instructions",
404            ),
405            PythonSourcePage(u"meta",
406                crumb=u"meta",
407                title=(abbr.xist(), u".ns.meta · Python software · LivingLogic AG"),
408                header=(abbr.xist(), u".ns.meta"),
409                subheader=u"Namespace module containing meta information elements",
410                url=u"root:xist/ns/meta/index.html",
411                linktitle=u"Module ll.xist.ns.meta: Namespace containing meta information elements",
412            ),
413            PythonSourcePage(u"ruby",
414                crumb=u"ruby",
415                title=(abbr.xist(), u".ns.ruby · Python software · LivingLogic AG"),
416                header=(abbr.xist(), u".ns.ruby"),
417                subheader=u"Namespace implementing the W3C ruby draft",
418                url=u"root:xist/ns/ruby/index.html",
419                linktitle=u"Module ll.xist.ns.ruby: Namespace implementing the W3C ruby draft",
420            ),
421            PythonSourcePage(u"specials",
422                crumb=u"specials",
423                title=(abbr.xist(), u".ns.specials · Python software · LivingLogic AG"),
424                header=(abbr.xist(), u".ns.specials"),
425                subheader=u"Common useful elements",
426                url=u"root:xist/ns/specials/index.html",
427                linktitle=u"Module ll.xist.ns.specials: Common useful elements",
428            ),
429            PythonSourcePage(u"htmlspecials",
430                crumb=u"htmlspecials",
431                title=(abbr.xist(), u".ns.htmlspecials · Python software · LivingLogic AG"),
432                header=(abbr.xist(), u".ns.htmlspecials"),
433                subheader=(u"Common useful elements for ", abbr.html(), u" generation"),
434                url=u"root:xist/ns/htmlspecials/index.html",
435                linktitle=u"Module ll.xist.ns.htmlspecials: Common useful elements for HTML generation",
436            ),
437            PythonSourcePage(u"doc",
438                crumb=u"doc",
439                title=(abbr.xist(), u".ns.doc · Python software · LivingLogic AG"),
440                header=(abbr.xist(), u".ns.doc"),
441                subheader=u"Namespace module for automated documentation generation",
442                url=u"root:xist/ns/doc/index.html",
443                linktitle=u"Module ll.xist.ns.doc: Namespace for automated documentation generation",
444            ),
445            PythonSourcePage(u"kid",
446                crumb=u"kid",
447                title=(abbr.xist(), u".ns.kid · Python software · LivingLogic AG"),
448                header=(abbr.xist(), u".ns.kid"),
449                subheader=u"Namespace module for Kid templates",
450                url=u"root:xist/ns/kid/index.html",
451                linktitle=u"Module ll.xist.ns.kid: Namespace for Kid templates",
452            ),
453            PythonSourcePage(u"detox",
454                crumb=u"detox",
455                title=(abbr.xist(), u".ns.detox · Python software · LivingLogic AG"),
456                header=(abbr.xist(), u".ns.detox"),
457                subheader=(abbr.xist(), u" based Python templating language"),
458                url=u"root:xist/ns/detox/index.html",
459                linktitle=u"Module ll.xist.ns.detox: Namespace for detox templates",
460            ),
461            PythonSourcePage(u"toxic",
462                crumb=u"toxic",
463                title=(abbr.xist(), u".ns.toxic · Python software · LivingLogic AG"),
464                header=(abbr.xist(), u".ns.toxic"),
465                subheader=(u"Generate Oracle functions from PL/SQL embedded in ", abbr.xml()),
466                url=u"root:xist/ns/toxic/index.html",
467                localkeywords=[u"Oracle", u"user defined function", u"PL/SQL", u"XML", u"HTML", u"processing instruction", u"PI", u"embed"],
468                linktitle=u"Embed PL/SQL in XIST XML",
469                description=u"""
470                toxic is an XIST namespace that can be used for generating Oracle
471                database functions that return XML strings. This is done by
472                embedding processing instructions containing PL/SQL code into XML
473                files and transforming those files with XIST.
474                """,
475            ),
476            PythonSourcePage(u"rng",
477                crumb=u"rng",
478                title=(abbr.xist(), u".ns.rng · Python software · LivingLogic AG"),
479                header=(abbr.xist(), u".ns.rng"),
480                subheader=u"Namespace module for Relax NG",
481                url=u"root:xist/ns/rng/index.html",
482                linktitle=u"Module ll.xist.ns.rng: Namespace for Relax NG",
483            ),
484            PythonSourcePage(u"rss091",
485                crumb=u"rss091",
486                title=(abbr.xist(), u".ns.rss091 · Python software · LivingLogic AG"),
487                header=(abbr.xist(), u".ns.rss091"),
488                subheader=u"Namespace module for RSS 0.91",
489                url=u"root:xist/ns/rss091/index.html",
490                linktitle=u"Module ll.xist.ns.rss091: Namespace for RSS 0.91",
491            ),
492            PythonSourcePage(u"rss20",
493                crumb=u"rss20",
494                title=(abbr.xist(), u".ns.rss20 · Python software · LivingLogic AG"),
495                header=(abbr.xist(), u".ns.rss20"),
496                subheader=u"Namespace module for RSS 2.0",
497                url=u"root:xist/ns/rss20/index.html",
498                linktitle=u"Module ll.xist.ns.rss20: Namespace for RSS 2.0",
499            ),
500            PythonSourcePage(u"atom",
501                crumb=u"atom",
502                title=(abbr.xist(), u".ns.atom · Python software · LivingLogic AG"),
503                header=(abbr.xist(), u".ns.atom"),
504                subheader=u"Namespace module for Atom 1.0",
505                url=u"root:xist/ns/atom/index.html",
506                linktitle=u"Module ll.xist.ns.atom: Namespace for Atom 1.0",
507            ),
508            PythonSourcePage(u"struts_html",
509                crumb=u"struts_html",
510                title=(abbr.xist(), u"ns.struts_html · Python software · LivingLogic AG"),
511                header=(abbr.xist(), u".ns.struts_html"),
512                subheader=(u"Mamespace module implementing the the Struts ", abbr.html(), u" tags"),
513                url=u"root:xist/ns/struts_html/index.html",
514                linktitle=u"Module ll.xist.ns.struts_html: Namespace for Jakarta Struts HTML tags",
515            ),
516            PythonSourcePage(u"struts_config",
517                crumb=u"struts_config",
518                title=(abbr.xist(), u".ns.struts_config · Python software · LivingLogic AG"),
519                header=(abbr.xist(), u".ns.struts_config"),
520                subheader=(u"Namespace module for Struts configuration files"),
521                url=u"root:xist/ns/struts_config/index.html",
522                linktitle=u"Module ll.xist.ns.struts_html: Namespace for Jakarta Struts configuration file tags",
523            ),
524            crumb=u"ns",
525            title=(abbr.xist(), u".ns"),
526            header=(abbr.xist(), u".ns"),
527            subheader=u"Subpackage containing namespace modules",
528            url=u"root:xist/ns/index.html",
529            linktitle=u"Package ll.xist.ns: Contains namespace modules",
530        ),
531        PythonSourcePage(u"parsers",
532            crumb=u"parsers",
533            title=(abbr.xist(), u".parsers · Python software · LivingLogic AG"),
534            header=(abbr.xist(), u".parsers"),
535            subheader=u"Module with classes for parsing files",
536            url=u"root:xist/parsers/index.html",
537            linktitle=u"Module ll.xist.parsers: Parsing XML",
538        ),
539        PythonSourcePage(u"converters",
540            crumb=u"converters",
541            title=(abbr.xist(), u".converters · Python software · LivingLogic AG"),
542            header=(abbr.xist(), u".converters"),
543            subheader=u"Module with the converter class",
544            url=u"root:xist/converters/index.html",
545            linktitle=u"Module ll.xist.converters: Configuring the XML transformation",
546        ),
547        PythonSourcePage(u"presenters",
548            crumb=u"presenters",
549            title=(abbr.xist(), u".presenters · Python software · LivingLogic AG"),
550            header=(abbr.xist(), u".presenters"),
551            subheader=u"Module with classes for printing trees",
552            url=u"root:xist/presenters/index.html",
553            linktitle=u"Module ll.xist.presenters: Screen output of XML trees",
554        ),
555        PythonSourcePage(u"publishers",
556            crumb=u"publishers",
557            title=(abbr.xist(), u".publishers · Python software · LivingLogic AG"),
558            header=(abbr.xist(), u".publishers"),
559            subheader=u"Module with classes for publishing trees",
560            url=u"root:xist/publishers/index.html",
561            linktitle=u"Module ll.xist.publishers: XML output",
562        ),
563        PythonSourcePage(u"sims",
564            crumb=u"sims",
565            title=(abbr.xist(), u".sims · Python software · LivingLogic AG"),
566            header=(abbr.xist(), u".sims"),
567            subheader=u"Simple schema validation",
568            url=u"root:xist/sims/index.html",
569            linktitle=u"Module ll.xist.sims: Simple schema validation",
570        ),
571        PythonSourcePage(u"xfind",
572            crumb=u"xfind",
573            title=(abbr.xist(), u".xfind · Python software · LivingLogic AG"),
574            header=(abbr.xist(), u".xfind"),
575            subheader=u"Tree iteration and filtering",
576            url=u"root:xist/xfind/index.html",
577            linktitle=u"Module ll.xist.xfind: Tree iteration and filtering",
578        ),
579        PythonSourcePage(u"css",
580            crumb=u"css",
581            title=(abbr.xist(), u".css · Python software · LivingLogic AG"),
582            header=(abbr.xist(), u".css"),
583            subheader=(abbr.css(), " related funtions"),
584            url=u"root:xist/css/index.html",
585            linktitle=u"Module ll.xist.css: CSS related functions",
586        ),
587        XISTPage(u"history",
588            XISTPage(u"old",
589                crumb=u"Old history",
590                title=u"Old history · Python software · LivingLogic AG",
591                header=u"Old history",
592                subheader=u"The history before distribution restructuring",
593                url=u"root:xist/OldHistory.html",
594                localkeywords=[u"history", u"changes", u"version"],
595                linktitle=(u"Old ChangeLog for modules merged into ", abbr.xist()),
596            ),
597            crumb=u"History",
598            title=(abbr.xist(), u" history · Python software · LivingLogic AG"),
599            header=(abbr.xist(), u" history"),
600            subheader=u"The development history",
601            url=u"root:xist/History.html",
602            localkeywords=[u"history", u"changes", u"version"],
603            linktitle=u"ChangeLog for XIST",
604        ),
605        XISTPage(u"installation",
606            crumb=u"Installation",
607            title=(abbr.xist(), u" requirements and installation · Python software · LivingLogic AG"),
608            header=(abbr.xist(), u" installation"),
609            subheader=u"Requirements, installation and configuration",
610            url=u"root:xist/Installation.html",
611            localkeywords=[u"installation", u"distutils"],
612            linktitle=u"How to install and configure XIST",
613        ),
614        XISTPage(u"migration",
615            XISTPage(u"old",
616                crumb=u"Old migration info",
617                title=u"Old migration info · Python software · LivingLogic AG",
618                header=u"Old migration info",
619                subheader=u"Migration infomation for old versions before distribution restructuring",
620                url=u"root:xist/OldMigration.html",
621                localkeywords=[u"history", u"changes", u"version"],
622                linktitle=u"Old migration info",
623            ),
624            crumb=u"Migration",
625            title=(abbr.xist(), u" migration guide · Python software · LivingLogic AG"),
626            header=(abbr.xist(), u" migration"),
627            subheader=(u"How to update your code to new versions of ", abbr.xist()),
628            url=u"root:xist/Migration.html",
629            localkeywords=[],
630            linktitle=u"How to update your code to new versions of XIST",
631        ),
632        XISTPage(u"mailinglists",
633            crumb=u"Mailing lists",
634            title=(abbr.xist(), u" mailing lists · Python software · LivingLogic AG"),
635            header=(abbr.xist(), u" mailing lists"),
636            subheader=u"How to subscribe to the mailing lists",
637            url=u"root:xist/Mailinglists.html",
638            localkeywords=[u"mailing list", u"list", u"posting", u"discussion", u"announcement"],
639            linktitle=u"How to subscribe to the XIST mailing lists",
640        ),
641        crumb="ll.xist",
642        title=(abbr.xist(), u" · Python software · LivingLogic AG"),
643        header=abbr.xist(),
644        subheader=(u"An extensible ", abbr.html(), u"/", abbr.xml(), u" generator"),
645        url=u"root:xist/index.html",
646        inheritablekeywords=[abbr.xist(), abbr.xml(), u"transformation", abbr.xsl(), u"hsc"],
647        linktitle=u"Package ll.xist: An extensible XML/HTML generator",
648        description=u"""
649        XIST is an extensible HTML/XML generator written in Python. XIST is also a
650        DOM parser (built on top of SAX2) with a very simple and pythonesque tree
651        API. Every XML element type corresponds to a Python class and these Python
652        classes provide a conversion method to transform the XML tree (e.g. into
653        HTML). XIST can be considered 'object oriented XSL'.
654        """,
655    ),
656    PythonSourcePage(u"url",
657        XISTPage(u"howto",
658            crumb=u"Howto",
659            title=u"ll.url howto · Python software · LivingLogic AG",
660            header=u"ll.url documentation",
661            subheader=u"Special features of URL",
662            url=u"root:url/Howto.html",
663            localkeywords=[],
664            linktitle=u"Special features of URL",
665        ),
666        crumb=u"ll.url",
667        title=u"ll.url · Python software · LivingLogic AG",
668        header=u"ll.url",
669        subheader=(u"Module implementing ", abbr.url(), u"s"),
670        url=u"root:url/index.html",
671        linktitle=u"Module ll.url: RFC 2396 compliant URLs",
672        description=u"""
673        ll.url is a Python module that provides classes for parsing and
674        constructing RFC 2396 compliant URLs.
675        """,
676    ),
677    PythonSourcePage(u"make",
678        crumb=u"ll.make",
679        title=u"ll.make · Python software · LivingLogic AG",
680        header=u"ll.make",
681        subheader=u"Object oriented make replacement",
682        url=u"root:make/index.html",
683        localkeywords=[u"make", u"build", u"dependencies", u"development", u"target"],
684        linktitle=u"Module ll.make: Object oriented make replacement",
685        description=u"""
686        ll.make is a Python module that provides an object oriented make replacement.
687        Like make it allows you to specify dependencies between files and actions
688        to be executed when files don't exist or are out of date with respect to
689        one of their sources. But unlike make you can do this in a object oriented
690        way and targets are not only limited to files, but you can implement
691        e.g. dependencies on database records.
692        """,
693    ),
694    PythonSourcePage(u"daemon",
695        crumb=u"ll.daemon",
696        title=u"ll.daemon · Python software · LivingLogic AG",
697        header=u"ll.daemon",
698        subheader=u"Forking daemon processes with Python",
699        url=u"root:daemon/index.html",
700        inheritablekeywords=[u"daemon", u"fork", u"process"],
701        linktitle=u"Module ll.daemon: Forking daemon processes",
702        description=u"""
703        ll.daemon is a Python module that can be used on UNIX to fork a daemon process.
704        """,
705    ),
706    PythonSourcePage(u"sisyphus",
707        crumb=u"ll.sisyphus",
708        title=u"ll.sisyphus · Python software · LivingLogic AG",
709        header=u"ll.sisyphus",
710        subheader=u"Writing cron jobs with Python",
711        url=u"root:sisyphus/index.html",
712        inheritablekeywords=[u"packages", u"Sisyphus", u"cron", u"job"],
713        linktitle=u"Module ll.sisyphus: Writing cron jobs with Python",
714        description=u"""
715        ll.sisyphus is a Python module that simplifies writing Python scripts
716        that run as cron jobs.
717        """,
718    ),
719    PythonSourcePage(u"color",
720        crumb=u"ll.color",
721        title=u"ll.color · Python software · LivingLogic AG",
722        header=u"ll.color",
723        subheader=u"RGB color values and color model conversion",
724        url=u"root:color/index.html",
725        localkeywords=[u"RGB", u"red", u"green", u"blue", u"HSV", u"HSB", u"HSL", u"HLS", u"hue", u"saturation", u"value", u"brightness", u"luminance"],
726        linktitle=u"Module ll.color: RGB color values and color model conversion",
727        description=u"""
728        ll.color is a Python module that provides classes and functions for handling
729        RGB color values. This includes the ability to convert between different
730        color models (RGB, HSV, HLS) as well as to and from CSS format, and several
731        functions for modifying and mixing colors.
732        """,
733    ),
734    PythonSourcePage(u"misc",
735        crumb=u"ll.misc",
736        title=u"ll.misc · Python software · LivingLogic AG",
737        header=u"ll.misc",
738        subheader=u"Miscellaneous utility functions and classes",
739        url=u"root:misc/index.html",
740        localkeywords=[u"utilities", u"decorator", u"property", u"module", u"namespace"],
741        linktitle=u"Module ll.misc: Misc utility functions and classes",
742        description=u"""
743        ll.misc provides serveral utility classes and functions.
744        """,
745    ),
746    PythonSourcePage(u"xpit",
747        crumb=u"ll.xpit",
748        title=u"ll.xpit · Python software · LivingLogic AG",
749        header=u"ll.xpit",
750        subheader=u"Embed Python expressions in text",
751        url=u"root:xpit/index.html",
752        localkeywords=[u"template", u"embed", u"processing instruction", u"PI", u"Python expression"],
753        linktitle=u"Module ll.xpit: Embed Python expressions in text",
754        description=u"""
755        ll.xpit is a Python module that allows you to embed Python expressions
756        in text files.
757        """,
758    ),
759    PythonSourcePage(u"orasql",
760        XISTPage(u"history",
761            crumb=u"History",
762            title=u"ll.orasql history · Python software · LivingLogic AG",
763            header=u"ll.orasql history",
764            subheader=u"The development history",
765            url=u"root:orasql/History.html",
766            localkeywords=[u"packages", u"history", u"changes", u"version"],
767            linktitle=u"ChangeLog for ll-orasql",
768        ),
769        XISTPage(u"installation",
770            crumb=u"Installation",
771            title=u"ll.orasql installation · Python software · LivingLogic AG",
772            header=u"ll.orasql installation",
773            subheader=u"Requirements and installation",
774            url=u"root:orasql/Installation.html",
775            localkeywords=[u"installation", u"distutils"],
776            linktitle=u"How to install ll-orasql",
777        ),
778        crumb=u"ll.orasql",
779        title=u"ll.orasql · Python software · LivingLogic AG",
780        header=u"ll.orasql",
781        subheader=u"Utilities for working with cx_Oracle",
782        url=u"root:orasql/index.html",
783        localkeywords=[u"Oracle", u"cx_Oracle"],
784        linktitle=u"Module ll.orasql: Utilities for cx_Oracle",
785        description=u"""
786        ll.orasql is a Python module that provides utilities for working with cx_Oracle:
787        It allows calling Oracle procedures via keyword arguments and it wraps the
788        result of fetch calls in a custom dictionary.
789        """,
790    ),
791    PythonSourcePage(u"nightshade",
792        XISTPage(u"history",
793            crumb=u"History",
794            title=u"ll.nightshade history · Python software · LivingLogic AG",
795            header=u"ll.nightshade history",
796            subheader=u"The development history",
797            url=u"root:nightshade/History.html",
798            localkeywords=[u"packages", u"history", u"changes", u"version"],
799            linktitle=u"ChangeLog for ll-nightshade",
800        ),
801        XISTPage(u"installation",
802            crumb=u"Installation",
803            title=u"ll.nightshade installation · Python software · LivingLogic AG",
804            header=u"ll.nightshade installation",
805            subheader=u"Requirements and installation",
806            url=u"root:nightshade/Installation.html",
807            localkeywords=[u"installation", u"distutils"],
808            linktitle=u"How to install ll-nightshade",
809        ),
810        XISTPage(u"migration",
811            crumb=u"Migration",
812            title=(u"nightshade migration guide · Python software · LivingLogic AG"),
813            header=(u"nightshade migration"),
814            subheader=(u"How to update your code to new versions of nightshade"),
815            url=u"root:nightshade/Migration.html",
816            localkeywords=[],
817            linktitle=u"How to update your code to new versions of nightshade",
818        ),
819        crumb=u"ll.nightshade",
820        title=u"ll.nightshade · Python software · LivingLogic AG",
821        header=u"ll.nightshade",
822        subheader=u"Serving the output of Oracle functions/procedures with CherryPy",
823        url=u"root:nightshade/index.html",
824        localkeywords=[u"Oracle", u"cx_Oracle"],
825        linktitle=u"Module ll.nightshade: Serve the output of Oracle functions/procedures with CherryPy",
826        description=u"""
827        ll.orasql is a Python module that provides utilities for working with cx_Oracle:
828        It allows calling Oracle procedures via keyword arguments and it wraps the
829        result of fetch calls in a custom dictionary.
830        """,
831    ),
832    PythonSourcePage(u"aplora",
833        XISTPage(u"history",
834            crumb=u"History",
835            title=u"Aplora history · Python software · LivingLogic AG",
836            header=u"Aplora history",
837            subheader=u"The development history",
838            url=u"root:aplora/History.html",
839            localkeywords=[u"packages", u"history", u"changes", u"version"],
840            linktitle=u"ChangeLog for ll-aplora",
841        ),
842        XISTPage(u"installation",
843            crumb=u"Installation",
844            title=u"Aplora requirements, installation and configuration · Python software · LivingLogic AG",
845            header=u"Aplora installation",
846            subheader=u"Requirements, installation and configuration",
847            url=u"root:aplora/Installation.html",
848            localkeywords=[u"installation", u"distutils"],
849            linktitle=u"How to install ll-aplora",
850        ),
851        crumb=u"Aplora",
852        title=u"Aplora · Python software · LivingLogic AG",
853        header=u"Aplora",
854        subheader=(u"Logging Apache ", abbr.http(), u" requests to an Oracle database"),
855        url=u"root:aplora/index.html",
856        localkeywords=[u"make", u"build", u"dependencies", u"development", u"target"],
857        linktitle=u"Script ll.aplora: Logging Apache HTTP requests to an Oracle database",
858        description=u"""
859        ll-aplora is a script that can be used with Apaches piped logging facility
860        to log HTTP request to an Oracle database.
861        """,
862    ),
863    PythonSourcePage(u"pycoco",
864        XISTPage(u"history",
865            crumb=u"History",
866            title=u"Pycoco history · Python software · LivingLogic AG",
867            header=u"Pycoco history",
868            subheader=u"The development history",
869            url=u"root:pycoco/History.html",
870            localkeywords=[u"packages", u"history", u"changes", u"version"],
871            linktitle=u"ChangeLog for pycoco",
872        ),
873        XISTPage(u"installation",
874            crumb=u"Installation",
875            title=u"Pycoco requirements, installation and configuration · Python software · LivingLogic AG",
876            header=u"Pycoco installation",
877            subheader=u"Requirements, installation and configuration",
878            url=u"root:pycoco/Installation.html",
879            localkeywords=[u"installation", u"distutils"],
880            linktitle=u"How to install pycoco",
881        ),
882        crumb=u"Pycoco",
883        title=u"Pycoco · Python software · LivingLogic AG",
884        header=u"Pycoco",
885        subheader=(u"Python code coverage report"),
886        url=u"root:pycoco/index.html",
887        localkeywords=[u"test", u"Python", "code coverage"],
888        linktitle=u"Script pycoco: Python code coverage",
889        description=u"""
890        A script that can be used to generate code coverage info
891        for the Python source code.
892        """,
893    ),
894    XISTPage(u"download",
895        XISTPage(u"old",
896            crumb=u"Old download",
897            title=u"Old downloads · Python software · LivingLogic AG",
898            header=u"Old downloads",
899            subheader=u"Download old modules as separate distributions",
900            url=u"root:OldDownload.html",
901            localkeywords=[u"download", u"file", u"archive"],
902            linktitle=u"Links to older distributions",
903        ),
904        crumb=u"Download",
905        title=u"Download · Python software · LivingLogic AG",
906        header="Downloads",
907        subheader=u"All versions for download",
908        url=u"root:Download.html",
909        localkeywords=[u"download", u"file", u"archive"],
910        linktitle=u"Links to Windows and Linux, source and binary distributions",
911    ),
912    XISTPage(u"source",
913        crumb=u"Source code",
914        title=u"Source code · Python software · LivingLogic AG",
915        header=u"Source code",
916        subheader=(u"Access to the Mercurial repositories"),
917        url=u"root:Source.html",
918        localkeywords=[u"Mercurial", u"development", u"repository"],
919        linktitle=u"Access to the Mercurial repositories",
920        description=u"""
921        Provides a link to the Mercurial repositories for all
922        Open Source Python projects by LivingLogic.
923        """
924    ),
925    crumb=u"Python software",
926    title=u"Python software · LivingLogic AG",
927    header=u"Python packages",
928    subheader=u"Python packages and modules by LivingLogic",
929    url=u"root:index.html",
930    inheritablekeywords=[u"Living", u"Logic", u"LivingLogic", u"Bayreuth", u"Python"],
931    localkeywords=[u"packages", abbr.xist(), u"sisyphus", u"toxic", u"orasql"],
932    linktitle=u"Startpage with project list",
933    description=u"""
934    LivingLogic provides several Open Source Python packages:
935    XIST, ll-url, ll-make, ll-color, ll-sisyphus, ll-toxic, ll-xpit, ll-orasql
936    """
937)
938
939
940class pageref(xsc.Element):
941    xmlns = xmlns
942    model = sims.NoElements()
943    class Attrs(xsc.Element.Attrs):
944        class ref(xsc.TextAttr): pass
945
946    def convert(self, converter):
947        if "ref" in self.attrs:
948            page = pages[unicode(self.attrs.ref.convert(converter))]
949        else:
950            page = pages
951        e = html.a(self.content, href=page.url, title=page.linktitle)
952        return e.convert(converter)
953
954
955class download(xsc.Element):
956    xmlns = xmlns
957    model = sims.Empty()
958    class Attrs(xsc.Element.Attrs):
959        class version(xsc.TextAttr): pass
960        class date(xsc.TextAttr): pass
961
962    base = "ssh://root@ftp.livinglogic.de/~ftp/pub/livinglogic/"
963
964    def file(self, converter, u):
965        target = converter.target
966        name = u.file
967        if name.endswith(".tar.gz") or name.endswith(".tar.bz2") or name.endswith(".zip"):
968            type = "Source"
969        elif name.endswith(".egg"):
970            if "win32" in name:
971                type = "Windows egg"
972            elif "linux" in name:
973                type = "Linux egg"
974            else:
975                type = "Egg"
976            pos = name.rfind("py")
977            if pos >= 0:
978                version = name[pos+2:pos+5]
979                type += " (Python %s)" % version
980        elif name.endswith(".exe"):
981            type = "Windows installer"
982            pos = name.rfind("py")
983            if pos >= 0:
984                version = name[pos+2:-4]
985                type += " (Python %s)" % version
986        elif name.endswith(".src.rpm"):
987            type = "Source RPM"
988        elif name.endswith(".rpm"):
989            type = "Binary RPM"
990        else:
991            type = chars.nbsp()
992
993        href = ("http://ftp.livinglogic.de/", u.relative(self.base))
994        if target.xmlns == doc.xmlns:
995            e = target.li(target.a(unicode(name), href=href), " (", type,")")
996        else:
997            e = html.tr(
998                html.td(html.a(unicode(name), href=href, title=("Download ", href)), class_="file"),
999                html.td(type, class_="type"),
1000                html.td(u.size(), class_="size"),
1001                class_="download"
1002            )
1003        return e
1004
1005    def convert(self, converter):
1006        version = str(self.attrs.version.convert(converter))
1007        name = converter[downloads].name
1008        u = url.URL("%s/%s/" % (self.base, name))
1009        files = u/u.files("*-%s[-.][twpz]*" % version)
1010        files = (self.file(converter, f) for f in files)
1011        target = converter.target
1012        if target.xmlns == doc.xmlns:
1013            e = target.section(
1014                target.h("Version ", self.attrs.version, " (released ", self.attrs.date, ")"),
1015                target.ul(files),
1016            )
1017        else:
1018            with xsc.Frag() as e:
1019                with html.tr():
1020                    with html.th(self.attrs.version, class_="version"):
1021                        if "date" in self.attrs:
1022                            xsc.add(" ", html.span("(released ", self.attrs.date, ")", class_="note"))
1023                    +html.th("Type", class_="type")
1024                    +html.th("Bytes", class_="size")
1025                xsc.add(files)
1026        return e.convert(converter)
1027
1028
1029class downloads(xsc.Element):
1030    xmlns = xmlns
1031    model = sims.Elements(download)
1032    class Attrs(xsc.Element.Attrs):
1033        class name(xsc.TextAttr): pass
1034    class Context(xsc.Element.Context):
1035        pass
1036
1037    def convert(self, converter):
1038        converter[self].name = str(self.attrs.name.convert(converter))
1039        target = converter.target
1040        if target.xmlns == doc.xmlns:
1041            e = self.content
1042        else:
1043            e = html.div(
1044                htmlspecials.plaintable(
1045                    self.content,
1046                    class_="downloads",
1047                ),
1048                align="center"
1049            )
1050        return e.convert(converter)
1051
1052
1053class alldownloads(xsc.Element):
1054    xmlns = xmlns
1055    model = sims.Elements(downloads)
1056
1057    def convert(self, converter):
1058        e = html.div(self.content, class_="alldownloads")
1059        return e.convert(converter)
1060
1061
1062class page(xsc.Element):
1063    xmlns = xmlns
1064    model = sims.Elements(alldownloads, doc.block)
1065    class Attrs(xsc.Element.Attrs):
1066        class refresh(xsc.TextAttr): pass
1067        class path(xsc.TextAttr): pass
1068
1069    def _nodetype(self, path, activepath):
1070        if path[-1] is activepath[-1]:
1071            return "here"
1072        elif path[-1] in activepath:
1073            return "path"
1074        else:
1075            return "other"
1076
1077    def _node(self, path, activepath):
1078        type = self._nodetype(path, activepath)
1079        page = path[-1]
1080        if type == "here":
1081            e = html.div(page.crumb)
1082            children = True
1083        else:
1084            e = html.a(
1085                html.span(u"\u2713", class_=u"visited", title=u"You have already visited that page"),
1086                page.crumb,
1087                href=page.url,
1088                title=page.linktitle,
1089                class_=type,
1090            )
1091            children = (type == "path")
1092        if len(path) > 1:
1093            e = html.li(e, class_=type)
1094        else:
1095            e = xsc.Frag(e)
1096        if children:
1097            e.append(self._children(path, activepath))
1098        return e
1099
1100    def _children(self, path, activepath):
1101        return html.ul(self._node(path + [child], activepath) for child in path[-1].getChildren())
1102
1103    def _links(self, context):
1104        return self._node([pages], context.page.getPath())
1105
1106    def _crumbs(self, context):
1107        e = xsc.Frag()
1108        page = context.page
1109        while page is not None:
1110            if page is context.page:
1111                e.insert(0, html.span(page.crumb, class_=u"here"))
1112            else:
1113                e.insert(0, pageref(page.crumb, ref=page.getPathString()))
1114            e.insert(0, u"\xa0\u203a\xa0")
1115            page = page.parent
1116        e.insert(0, html.a(u"Home", href=u"http://www.livinglogic.de/", hreflang=u"de", title=u"The company homepage (in german)"))
1117        return e
1118
1119    def convert(self, converter):
1120        converter[doc.pyref].base = "root:"
1121        target = converter.target
1122        context = converter[self]
1123        context.path = unicode(self["path"].convert(converter))
1124        context.page = pages[context.path]
1125        if target.xmlns == doc.xmlns:
1126            return self.content.convert(converter)
1127        elif not target.xmlns == html.xmlns:
1128            raise ValueError("unknown conversion target %r" % target)
1129        else:
1130            with xsc.Frag(xml.XML(), u"\n", target.DocTypeXHTML10transitional(), u"\n") as e:
1131                with target.html(xml.Attrs(lang=u"en"), lang=u"en"):
1132                    with target.head():
1133                        +meta.contenttype()
1134                        +target.title(context.page.title)
1135                        if context.page.keywords:
1136                            +meta.keywords(xsc.Frag(*context.page.keywords).withsep(", "))
1137                        if context.page.description is not None:
1138                            +meta.description(context.page.description)
1139                        +meta.stylesheet(href="root:main_screen.css", media=u"screen, projection, tv")
1140                        +meta.stylesheet(href="root:main_print.css", media=u"print")
1141                        +meta.author(name=u"Walter Dörwald", email=u"walter.doerwald@livinglogic.de")
1142                        icbm = u"49.9550; 11.5909"
1143                        +html.meta(name=u"icbm", content=icbm)
1144                        +html.meta(name=u"geo.position", content=icbm)
1145                        +html.meta(name=u"geo.placename", content=u"Bayreuth, Germany, Europe")
1146                        +html.meta(name=u"geo.region", content=u"DE-BY")
1147                        +html.meta(name=u"DC.title", content=context.page.title)
1148                        +html.link(rel=u"icon", href=u"root:images/favicon.gif", type=u"image/gif")
1149                        top = context.page.getRoot()
1150                        if top is not None and top != context.page:
1151                            +html.link(rel="top", href=top.url)
1152                        parent = context.page.parent
1153                        if parent is not None:
1154                            +html.link(rel="up", href=parent.url)
1155                        firstsibling = context.page.getFirstSibling()
1156                        if firstsibling is not None and firstsibling != context.page:
1157                            +html.link(rel="first", title="First page in set", href=firstsibling.url)
1158                        prevsibling = context.page.getPrevSibling()
1159                        if prevsibling is not None and prevsibling != context.page:
1160                            +html.link(rel="prev", title="Previous page", href=prevsibling.url)
1161                        nextsibling = context.page.getNextSibling()
1162                        if nextsibling is not None and nextsibling != context.page:
1163                            +html.link(rel="next", title="Next page", href=nextsibling.url)
1164                        lastsibling = context.page.getLastSibling()
1165                        if lastsibling is not None and lastsibling != context.page:
1166                            +html.link(rel="last", title="Last page in set", href=lastsibling.url)
1167                        for link in context.page.alternates():
1168                            +html.link(link.attrs)
1169                        if "refresh" in self.attrs:
1170                            +html.meta(http_equiv="refresh", content=self.attrs.refresh)
1171
1172                    with target.body():
1173                        with htmlspecials.plaintable(width="100%", class_="body"):
1174                            with html.tr(valign="bottom", class_="header"):
1175                                +html.td(htmlspecials.pixel(height=150), class_="header1", width="20%")
1176                                with html.td(class_="header2", width="79%"):
1177                                    if context.page.header:
1178                                        +html.h1(context.page.header)
1179                                    if context.page.subheader:
1180                                        +html.h2(context.page.subheader)
1181                            with html.tr(class_="crumbs"):
1182                                +html.td(htmlspecials.pixel(), class_="crumbs1")
1183                                with html.td(class_="crumbs2"):
1184                                    with htmlspecials.plaintable(width="100%"):
1185                                        with html.tr(valign="middle"):
1186                                            +html.td(self._crumbs(context), class_="crumbs")
1187                                            +html.td(xsc.Frag(context.page.alternates()).withsep(u"\xa0\xb7\xa0"), align="right", class_="alternate")
1188                            with html.tr(valign="top", class_="content"):
1189                                +html.td(htmlspecials.pixel(width=200), self._links(context), rowspan=2, class_="links"),
1190                                +html.td(self.content, class_="content")
1191        return e.convert(converter)
Note: See TracBrowser for help on using the browser.