root/livinglogic.python.www/site/Python_xmlns.py @ 658:b98c15bcdf7f

Revision 658:b98c15bcdf7f, 41.6 KB (checked in by Walter Doerwald <walter@…>, 9 years ago)

Add page for ucp script.

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, parse
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.hint = 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=="hint":
186                self.hint = 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            hint=u"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            hint=(u"Explains parsing/generating XML files, XML transformations via ", abbr.xist(), " classes and other basic concepts.")
260        ),
261        XISTPage(u"searching",
262            crumb=u"Searching",
263            title=(u"Searching ", abbr.xist(), u" trees · Python software · LivingLogic AG"),
264            header=("Searching ", abbr.xist(), u" trees"),
265            subheader=("Searching, tree traversal, xfind and ", abbr.css(), " selectors"),
266            url=u"root:xist/Searching.html",
267            localkeywords=["searching", "traversal", "xfind", "css"],
268            hint=(u"How to iterate through ", abbr.xist(), " trees"),
269        ),
270        XISTPage(u"transformation",
271            crumb=u"Transformation",
272            title=("Transforming ", abbr.xist(), u" trees · Python software · LivingLogic AG"),
273            header=("Transforming ", abbr.xist(), u" trees"),
274            subheader=("The ", doc.func("mapped"), " function, sorting, etc."),
275            url=u"root:xist/Transformation.html",
276            localkeywords=[],
277            hint=(u"How to transform ", abbr.xist(), " trees"),
278        ),
279        XISTPage(u"advanced",
280            crumb=u"Advanced topics",
281            title=("Advanced ", abbr.xist(), u" · Python software · LivingLogic AG"),
282            header=("Advanced ", abbr.xist()),
283            subheader="Converter contexts, pool chaining, namespace extensions, conversion targets, validation",
284            url=u"root:xist/Advanced.html",
285            localkeywords=[],
286            hint=u"Pool chaining, converter contexts, validation"
287        ),
288        XISTPage(u"misc",
289            crumb=u"Miscellaneous",
290            title=(abbr.xist(), u" miscellaneous · Python software · LivingLogic AG"),
291            header=(abbr.xist(), u" miscellaneous"),
292            subheader=(abbr.url(), u"s, pretty printing, image sizes, embedding Python code"),
293            url=u"root:xist/Misc.html",
294            localkeywords=[],
295            hint=(u"Explains various odds and ends of ", abbr.xist()),
296        ),
297        PythonSourcePage(u"xsc",
298            crumb=u"xsc",
299            title=(abbr.xist(), u".xsc · Python software · LivingLogic AG"),
300            header=(abbr.xist(), u".xsc"),
301            subheader=(abbr.xist(), u" core classes"),
302            url=u"root:xist/xsc/index.html",
303            hint=(abbr.xist(), u" core classes"),
304        ),
305        PythonSourcePage(u"ns",
306            PythonSourcePage(u"html",
307                crumb=u"html",
308                title=(abbr.xist(), u".ns.html · Python software · LivingLogic AG"),
309                header=(abbr.xist(), u".ns.html"),
310                subheader=(u"Module implementing ", abbr.html(), u" 4.01 (with additions)"),
311                url=u"root:xist/ns/html/index.html",
312                hint=u"HTML namespace",
313            ),
314            PythonSourcePage(u"xml",
315                crumb=u"xml",
316                title=(abbr.xist(), u".ns.xml · Python software · LivingLogic AG"),
317                header=(abbr.xist(), u".ns.xml"),
318                subheader=(u"Module for global attributes from the ", abbr.xml(), u" namespace"),
319                url=u"root:xist/ns/xml/index.html",
320                hint=u"Namespace implementing global XML attributes",
321            ),
322            PythonSourcePage(u"wml",
323                crumb=u"wml",
324                title=(abbr.xist(), u".ns.wml · Python software · LivingLogic AG"),
325                header=(abbr.xist(), u".ns.wml"),
326                subheader=(u"Module implementing ", abbr.wml(), u" 1.3"),
327                url=u"root:xist/ns/wml/index.html",
328                hint=u"WML 1.3 namespace",
329            ),
330            PythonSourcePage(u"ihtml",
331                crumb=u"ihtml",
332                title=(abbr.xist(), u".ns.ihtml · Python software · LivingLogic AG"),
333                header=(abbr.xist(), u".ns.ihtml"),
334                subheader=(u"Module module implementing i-mode compatible ", abbr.html()),
335                url=u"root:xist/ns/ihtml/index.html",
336                hint=u"Namespace implementing i-mode compatible HTML",
337            ),
338            PythonSourcePage(u"docbook",
339                crumb=u"docbook",
340                title=(abbr.xist(), u".ns.docbook · Python software · LivingLogic AG"),
341                header=(abbr.xist(), u".ns.docbook"),
342                subheader=u"Namespace module implementing DocBook 4.3",
343                url=u"root:xist/ns/docbook/index.html",
344                hint=u"Namespace implementing DocBook 4.3",
345            ),
346            PythonSourcePage(u"svg",
347                crumb=u"svg",
348                title=(abbr.xist(), u".ns.svg · Python software · LivingLogic AG"),
349                header=(abbr.xist(), u".ns.svg"),
350                subheader=(u"Namespace module implementing ", abbr.svg(), u" 1.0"),
351                url=u"root:xist/ns/svg/index.html",
352                hint=u"Namespace implementing SVG 1.0",
353            ),
354            PythonSourcePage(u"abbr",
355                crumb=u"abbr",
356                title=(abbr.xist(), u".ns.abbr · Python software · LivingLogic AG"),
357                header=(abbr.xist(), u".ns.abbr"),
358                subheader=u"Namespace module containing many abbreviation entities",
359                url=u"root:xist/ns/abbr/index.html",
360                hint=u"Namespace containing abbreviation entities",
361            ),
362            PythonSourcePage(u"code",
363                crumb=u"code",
364                title=(abbr.xist(), u".ns.code · Python software · LivingLogic AG"),
365                header=(abbr.xist(), u".ns.code"),
366                subheader=(u"Namespace module for embedding Python code in ", abbr.xml()),
367                url=u"root:xist/ns/code/index.html",
368                hint=u"Namespace for embedding Python code in XML",
369            ),
370            PythonSourcePage(u"form",
371                crumb=u"form",
372                title=(abbr.xist(), u".ns.form · Python software · LivingLogic AG"),
373                header=(abbr.xist(), u".ns.form"),
374                subheader=u"Namespace module implementing form related elements",
375                url=u"root:xist/ns/form/index.html",
376                hint=u"Namespace implementing form related elements",
377            ),
378            PythonSourcePage(u"php",
379                crumb=u"php",
380                title=(abbr.xist(), u".ns.php · Python software · LivingLogic AG"),
381                header=(abbr.xist(), u".ns.php"),
382                subheader=(u"Namespace module for PHP processing instructions"),
383                url=u"root:xist/ns/php/index.html",
384                hint=u"Namespace for PHP processing instructions",
385            ),
386            PythonSourcePage(u"jsp",
387                crumb=u"jsp",
388                title=(abbr.xist(), u".ns.jsp · Python software · LivingLogic AG"),
389                header=(abbr.xist(), u".ns.jsp"),
390                subheader=(u"Namespace module for embedding ", abbr.jsp(), u" code as processing instructions"),
391                url=u"root:xist/ns/jsp/index.html",
392                hint=u"Namespace for JSP code as processing instructions",
393            ),
394            PythonSourcePage(u"meta",
395                crumb=u"meta",
396                title=(abbr.xist(), u".ns.meta · Python software · LivingLogic AG"),
397                header=(abbr.xist(), u".ns.meta"),
398                subheader=u"Namespace module containing meta information elements",
399                url=u"root:xist/ns/meta/index.html",
400                hint=u"Namespace containing meta information elements",
401            ),
402            PythonSourcePage(u"ruby",
403                crumb=u"ruby",
404                title=(abbr.xist(), u".ns.ruby · Python software · LivingLogic AG"),
405                header=(abbr.xist(), u".ns.ruby"),
406                subheader=u"Namespace implementing the W3C ruby draft",
407                url=u"root:xist/ns/ruby/index.html",
408                hint=u"Namespace implementing the W3C ruby draft",
409            ),
410            PythonSourcePage(u"specials",
411                crumb=u"specials",
412                title=(abbr.xist(), u".ns.specials · Python software · LivingLogic AG"),
413                header=(abbr.xist(), u".ns.specials"),
414                subheader=u"Common useful elements",
415                url=u"root:xist/ns/specials/index.html",
416                hint=u"Common useful elements",
417            ),
418            PythonSourcePage(u"htmlspecials",
419                crumb=u"htmlspecials",
420                title=(abbr.xist(), u".ns.htmlspecials · Python software · LivingLogic AG"),
421                header=(abbr.xist(), u".ns.htmlspecials"),
422                subheader=(u"Common useful elements for ", abbr.html(), u" generation"),
423                url=u"root:xist/ns/htmlspecials/index.html",
424                hint=u"Common useful elements for HTML generation",
425            ),
426            PythonSourcePage(u"doc",
427                crumb=u"doc",
428                title=(abbr.xist(), u".ns.doc · Python software · LivingLogic AG"),
429                header=(abbr.xist(), u".ns.doc"),
430                subheader=u"Namespace module for automated documentation generation",
431                url=u"root:xist/ns/doc/index.html",
432                hint=u"Namespace for automated documentation generation",
433            ),
434            PythonSourcePage(u"kid",
435                crumb=u"kid",
436                title=(abbr.xist(), u".ns.kid · Python software · LivingLogic AG"),
437                header=(abbr.xist(), u".ns.kid"),
438                subheader=u"Namespace module for Kid templates",
439                url=u"root:xist/ns/kid/index.html",
440                hint=u"Namespace for Kid templates",
441            ),
442            PythonSourcePage(u"detox",
443                crumb=u"detox",
444                title=(abbr.xist(), u".ns.detox · Python software · LivingLogic AG"),
445                header=(abbr.xist(), u".ns.detox"),
446                subheader=(abbr.xist(), u" based Python templating language"),
447                url=u"root:xist/ns/detox/index.html",
448                hint=u"Namespace for detox templates",
449            ),
450            PythonSourcePage(u"toxic",
451                crumb=u"toxic",
452                title=(abbr.xist(), u".ns.toxic · Python software · LivingLogic AG"),
453                header=(abbr.xist(), u".ns.toxic"),
454                subheader=(u"Generate Oracle functions from PL/SQL embedded in ", abbr.xml()),
455                url=u"root:xist/ns/toxic/index.html",
456                localkeywords=[u"Oracle", u"user defined function", u"PL/SQL", u"XML", u"HTML", u"processing instruction", u"PI", u"embed"],
457                hint=u"Embed PL/SQL in XIST XML",
458                description=u"""
459                toxic is an XIST namespace that can be used for generating Oracle
460                database functions that return XML strings. This is done by
461                embedding processing instructions containing PL/SQL code into XML
462                files and transforming those files with XIST.
463                """,
464            ),
465            PythonSourcePage(u"rng",
466                crumb=u"rng",
467                title=(abbr.xist(), u".ns.rng · Python software · LivingLogic AG"),
468                header=(abbr.xist(), u".ns.rng"),
469                subheader=u"Namespace module for Relax NG",
470                url=u"root:xist/ns/rng/index.html",
471                hint=u"Namespace for Relax NG",
472            ),
473            PythonSourcePage(u"rss091",
474                crumb=u"rss091",
475                title=(abbr.xist(), u".ns.rss091 · Python software · LivingLogic AG"),
476                header=(abbr.xist(), u".ns.rss091"),
477                subheader=u"Namespace module for RSS 0.91",
478                url=u"root:xist/ns/rss091/index.html",
479                hint=u"Namespace for RSS 0.91",
480            ),
481            PythonSourcePage(u"rss20",
482                crumb=u"rss20",
483                title=(abbr.xist(), u".ns.rss20 · Python software · LivingLogic AG"),
484                header=(abbr.xist(), u".ns.rss20"),
485                subheader=u"Namespace module for RSS 2.0",
486                url=u"root:xist/ns/rss20/index.html",
487                hint=u"Namespace for RSS 2.0",
488            ),
489            PythonSourcePage(u"atom",
490                crumb=u"atom",
491                title=(abbr.xist(), u".ns.atom · Python software · LivingLogic AG"),
492                header=(abbr.xist(), u".ns.atom"),
493                subheader=u"Namespace module for Atom 1.0",
494                url=u"root:xist/ns/atom/index.html",
495                hint=u"Namespace for Atom 1.0",
496            ),
497            PythonSourcePage(u"struts_html",
498                crumb=u"struts_html",
499                title=(abbr.xist(), u"ns.struts_html · Python software · LivingLogic AG"),
500                header=(abbr.xist(), u".ns.struts_html"),
501                subheader=(u"Mamespace module implementing the the Struts ", abbr.html(), u" tags"),
502                url=u"root:xist/ns/struts_html/index.html",
503                hint=u"Namespace for Jakarta Struts HTML tags",
504            ),
505            PythonSourcePage(u"struts_config",
506                crumb=u"struts_config",
507                title=(abbr.xist(), u".ns.struts_config · Python software · LivingLogic AG"),
508                header=(abbr.xist(), u".ns.struts_config"),
509                subheader=u"Namespace module for Struts configuration files",
510                url=u"root:xist/ns/struts_config/index.html",
511                hint=u"Namespace for Jakarta Struts configuration file tags",
512            ),
513            crumb=u"ns",
514            title=(abbr.xist(), u".ns"),
515            header=(abbr.xist(), u".ns"),
516            subheader=u"Subpackage containing namespace modules",
517            url=u"root:xist/ns/index.html",
518            hint=u"Package containing namespace modules",
519        ),
520        PythonSourcePage(u"parse",
521            crumb=u"parse",
522            title=(abbr.xist(), u".parse · Python software · LivingLogic AG"),
523            header=(abbr.xist(), u".parse"),
524            subheader=(u"Tools for parsing ", abbr.xml(), " from various sources"),
525            url=u"root:xist/parse/index.html",
526            hint=u"Parsing XML",
527        ),
528        PythonSourcePage(u"present",
529            crumb=u"present",
530            title=(abbr.xist(), u".present · Python software · LivingLogic AG"),
531            header=(abbr.xist(), u".present"),
532            subheader=u"Module with classes for printing trees",
533            url=u"root:xist/present/index.html",
534            hint=u"Screen output of XML trees",
535        ),
536        PythonSourcePage(u"sims",
537            crumb=u"sims",
538            title=(abbr.xist(), u".sims · Python software · LivingLogic AG"),
539            header=(abbr.xist(), u".sims"),
540            subheader=u"Simple schema validation",
541            url=u"root:xist/sims/index.html",
542            hint=u"Simple schema validation",
543        ),
544        PythonSourcePage(u"xfind",
545            crumb=u"xfind",
546            title=(abbr.xist(), u".xfind · Python software · LivingLogic AG"),
547            header=(abbr.xist(), u".xfind"),
548            subheader=u"Tree iteration and filtering",
549            url=u"root:xist/xfind/index.html",
550            hint=u"Tree iteration and filtering",
551        ),
552        PythonSourcePage(u"css",
553            crumb=u"css",
554            title=(abbr.xist(), u".css · Python software · LivingLogic AG"),
555            header=(abbr.xist(), u".css"),
556            subheader=(abbr.css(), " related funtions"),
557            url=u"root:xist/css/index.html",
558            hint=u"CSS related functions",
559        ),
560        XISTPage(u"history",
561            XISTPage(u"old",
562                crumb=u"Old history",
563                title=u"Old history · Python software · LivingLogic AG",
564                header=u"Old history",
565                subheader=u"The history before distribution restructuring",
566                url=u"root:xist/OldHistory.html",
567                localkeywords=[u"history", u"changes", u"version"],
568                hint=(u"Old ChangeLog for modules merged into ", abbr.xist()),
569            ),
570            crumb=u"History",
571            title=(abbr.xist(), u" history · Python software · LivingLogic AG"),
572            header=(abbr.xist(), u" history"),
573            subheader=u"The development history",
574            url=u"root:xist/History.html",
575            localkeywords=[u"history", u"changes", u"version"],
576            hint=("ChangeLog for ", abbr.xist()),
577        ),
578        XISTPage(u"installation",
579            crumb=u"Installation",
580            title=(abbr.xist(), u" requirements and installation · Python software · LivingLogic AG"),
581            header=(abbr.xist(), u" installation"),
582            subheader=u"Requirements, installation and configuration",
583            url=u"root:xist/Installation.html",
584            localkeywords=[u"installation", u"distutils"],
585            hint=("How to install and configure ", abbr.xist()),
586        ),
587        XISTPage(u"migration",
588            XISTPage(u"old",
589                crumb=u"Old migration info",
590                title=u"Old migration info · Python software · LivingLogic AG",
591                header=u"Old migration info",
592                subheader=u"Migration infomation for old versions before distribution restructuring",
593                url=u"root:xist/OldMigration.html",
594                localkeywords=[u"history", u"changes", u"version"],
595                hint=u"Old migration info",
596            ),
597            crumb=u"Migration",
598            title=(abbr.xist(), u" migration guide · Python software · LivingLogic AG"),
599            header=(abbr.xist(), u" migration"),
600            subheader=(u"How to update your code to new versions of ", abbr.xist()),
601            url=u"root:xist/Migration.html",
602            localkeywords=[],
603            hint=(u"How to update your code to new versions of ", abbr.xist()),
604        ),
605        XISTPage(u"mailinglists",
606            crumb=u"Mailing lists",
607            title=(abbr.xist(), u" mailing lists · Python software · LivingLogic AG"),
608            header=(abbr.xist(), u" mailing lists"),
609            subheader=u"How to subscribe to the mailing lists",
610            url=u"root:xist/Mailinglists.html",
611            localkeywords=[u"mailing list", u"list", u"posting", u"discussion", u"announcement"],
612            hint=(u"How to subscribe to the ", abbr.xist(), " mailing lists"),
613        ),
614        crumb="ll.xist",
615        title=(abbr.xist(), u" · Python software · LivingLogic AG"),
616        header=abbr.xist(),
617        subheader=(u"An extensible ", abbr.html(), u"/", abbr.xml(), u" generator"),
618        url=u"root:xist/index.html",
619        inheritablekeywords=[abbr.xist(), abbr.xml(), u"transformation", abbr.xsl(), u"hsc"],
620        hint=u"An extensible XML/HTML generator",
621        description=u"""
622        XIST is an extensible HTML/XML generator written in Python. XIST is also a
623        DOM parser (built on top of SAX2) with a very simple and pythonesque tree
624        API. Every XML element type corresponds to a Python class and these Python
625        classes provide a conversion method to transform the XML tree (e.g. into
626        HTML). XIST can be considered 'object oriented XSL'.
627        """,
628    ),
629    PythonSourcePage(u"ul4",
630        XISTPage(u"howto",
631            crumb=u"Howto",
632            title=u"ll.ul4c howto · Python software · LivingLogic AG",
633            header=u"ll.ul4c documentation",
634            subheader=u"How to use UL4",
635            url=u"root:ul4c/Howto.html",
636            localkeywords=[],
637            hint=u"How to use UL4",
638        ),
639        crumb=u"ll.ul4c",
640        title=u"ll.ul4c · Python software · LivingLogic AG",
641        header=u"ll.ul4c",
642        subheader=(u"Crossplatform templating language"),
643        url=u"root:ul4c/index.html",
644        hint=u"A templating language",
645        description=u"""
646        ll.ul4c provides a crossplatform templating language.
647        """,
648    ),
649    PythonSourcePage(u"url",
650        XISTPage(u"howto",
651            crumb=u"Howto",
652            title=u"ll.url howto · Python software · LivingLogic AG",
653            header=u"ll.url documentation",
654            subheader=u"Special features of URL",
655            url=u"root:url/Howto.html",
656            localkeywords=[],
657            hint=u"Special features of URL",
658        ),
659        crumb=u"ll.url",
660        title=u"ll.url · Python software · LivingLogic AG",
661        header=u"ll.url",
662        subheader=(u"Module implementing ", abbr.url(), u"s"),
663        url=u"root:url/index.html",
664        hint=u"RFC 2396 compliant URLs",
665        description=u"""
666        ll.url is a Python module that provides classes for parsing and
667        constructing RFC 2396 compliant URLs.
668        """,
669    ),
670    PythonSourcePage(u"make",
671        crumb=u"ll.make",
672        title=u"ll.make · Python software · LivingLogic AG",
673        header=u"ll.make",
674        subheader=u"Object oriented make replacement",
675        url=u"root:make/index.html",
676        localkeywords=[u"make", u"build", u"dependencies", u"development", u"target"],
677        hint=u"Object oriented make replacement",
678        description=u"""
679        ll.make is a Python module that provides an object oriented make replacement.
680        Like make it allows you to specify dependencies between files and actions
681        to be executed when files don't exist or are out of date with respect to
682        one of their sources. But unlike make you can do this in a object oriented
683        way and targets are not only limited to files, but you can implement
684        e.g. dependencies on database records.
685        """,
686    ),
687    PythonSourcePage(u"daemon",
688        crumb=u"ll.daemon",
689        title=u"ll.daemon · Python software · LivingLogic AG",
690        header=u"ll.daemon",
691        subheader=u"Forking daemon processes with Python",
692        url=u"root:daemon/index.html",
693        inheritablekeywords=[u"daemon", u"fork", u"process"],
694        hint=u"Forking daemon processes",
695        description=u"""
696        ll.daemon is a Python module that can be used on UNIX to fork a daemon process.
697        """,
698    ),
699    PythonSourcePage(u"sisyphus",
700        crumb=u"ll.sisyphus",
701        title=u"ll.sisyphus · Python software · LivingLogic AG",
702        header=u"ll.sisyphus",
703        subheader=u"Writing cron jobs with Python",
704        url=u"root:sisyphus/index.html",
705        inheritablekeywords=[u"packages", u"Sisyphus", u"cron", u"job"],
706        hint=u"Writing cron jobs with Python",
707        description=u"""
708        ll.sisyphus is a Python module that simplifies writing Python scripts
709        that run as cron jobs.
710        """,
711    ),
712    PythonSourcePage(u"color",
713        crumb=u"ll.color",
714        title=u"ll.color · Python software · LivingLogic AG",
715        header=u"ll.color",
716        subheader=u"RGB color values and color model conversion",
717        url=u"root:color/index.html",
718        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"],
719        hint=u"RGB color values and color model conversion",
720        description=u"""
721        ll.color is a Python module that provides classes and functions for handling
722        RGB color values. This includes the ability to convert between different
723        color models (RGB, HSV, HLS) as well as to and from CSS format, and several
724        functions for modifying and mixing colors.
725        """,
726    ),
727    PythonSourcePage(u"misc",
728        crumb=u"ll.misc",
729        title=u"ll.misc · Python software · LivingLogic AG",
730        header=u"ll.misc",
731        subheader=u"Miscellaneous utility functions and classes",
732        url=u"root:misc/index.html",
733        localkeywords=[u"utilities", u"decorator", u"property", u"module", u"namespace"],
734        hint=u"Misc utility functions and classes",
735        description=u"""
736        ll.misc provides serveral utility classes and functions.
737        """,
738    ),
739    PythonSourcePage(u"orasql",
740        XISTPage(u"history",
741            crumb=u"History",
742            title=u"ll.orasql history · Python software · LivingLogic AG",
743            header=u"ll.orasql history",
744            subheader=u"The development history",
745            url=u"root:orasql/History.html",
746            localkeywords=[u"packages", u"history", u"changes", u"version"],
747            hint=(u"ChangeLog for ", doc.mod("ll.orasql")),
748        ),
749        XISTPage(u"installation",
750            crumb=u"Installation",
751            title=u"ll.orasql installation · Python software · LivingLogic AG",
752            header=u"ll.orasql installation",
753            subheader=u"Requirements and installation",
754            url=u"root:orasql/Installation.html",
755            localkeywords=[u"installation", u"distutils"],
756            hint=(u"How to install ", doc.mod("ll.orasql")),
757        ),
758        crumb=u"ll.orasql",
759        title=u"ll.orasql · Python software · LivingLogic AG",
760        header=u"ll.orasql",
761        subheader=(u"Utilities for working with ", doc.mod("cx_Oracle")),
762        url=u"root:orasql/index.html",
763        localkeywords=[u"Oracle", u"cx_Oracle"],
764        hint=u"Utilities for cx_Oracle",
765        description=u"""
766        ll.orasql is a Python module that provides utilities for working with cx_Oracle:
767        It allows calling Oracle procedures via keyword arguments and it wraps the
768        result of fetch calls in a custom dictionary.
769        """,
770    ),
771    PythonSourcePage(u"nightshade",
772        XISTPage(u"history",
773            crumb=u"History",
774            title=u"ll.nightshade history · Python software · LivingLogic AG",
775            header=u"ll.nightshade history",
776            subheader=u"The development history",
777            url=u"root:nightshade/History.html",
778            localkeywords=[u"packages", u"history", u"changes", u"version"],
779            hint=(u"ChangeLog for ", doc.mod("ll.nightshade")),
780        ),
781        XISTPage(u"installation",
782            crumb=u"Installation",
783            title=u"ll.nightshade installation · Python software · LivingLogic AG",
784            header=u"ll.nightshade installation",
785            subheader=u"Requirements and installation",
786            url=u"root:nightshade/Installation.html",
787            localkeywords=[u"installation", u"distutils"],
788            hint=(u"How to install ", doc.mod("ll.nightshade")),
789        ),
790        XISTPage(u"migration",
791            crumb=u"Migration",
792            title=(u"nightshade migration guide · Python software · LivingLogic AG"),
793            header=(u"nightshade migration"),
794            subheader=(u"How to update your code to new versions of nightshade"),
795            url=u"root:nightshade/Migration.html",
796            localkeywords=[],
797            hint=u"How to update your code to new versions of nightshade",
798        ),
799        crumb=u"ll.nightshade",
800        title=u"ll.nightshade · Python software · LivingLogic AG",
801        header=u"ll.nightshade",
802        subheader=u"Serving the output of Oracle functions/procedures with CherryPy",
803        url=u"root:nightshade/index.html",
804        localkeywords=[u"Oracle", u"cx_Oracle"],
805        hint=u"Serve the output of Oracle functions/procedures with CherryPy",
806        description=u"""
807        ll.orasql is a Python module that provides utilities for working with cx_Oracle:
808        It allows calling Oracle procedures via keyword arguments and it wraps the
809        result of fetch calls in a custom dictionary.
810        """,
811    ),
812    PythonSourcePage(u"scripts",
813        PythonSourcePage(u"db2ul4",
814            crumb=u"db2ul4",
815            title=u"ll.scripts.db2ul4 · Python software · LivingLogic AG",
816            header=u"ll.scripts.db2ul4",
817            subheader=u"Script for rendering UL4 templates with database content",
818            url=u"root:scripts/db2ul4.html",
819            inheritablekeywords=[u"UL4", "template", "database"],
820            hint=u"Script for rendering UL4 templates with database content",
821            description=u"""
822            db2ul4 renders an UL4 template. The available template variables
823            allow system command and database access. Supported databases are
824            Oracle, sqllite and MySQL.
825            """,
826        ),
827        PythonSourcePage(u"uls",
828            crumb=u"uls",
829            title=u"ll.scripts.uls · Python software · LivingLogic AG",
830            header=u"ll.scripts.uls",
831            subheader=u"Script for listing directory contents of URLs",
832            url=u"root:scripts/uls.html",
833            inheritablekeywords=[u"uls"],
834            hint=u"Script for listing directory contents of URLs",
835            description=u"""
836            uls is a script that lists directory contents. It is an URL-enabled version
837            of the ls system command. Via ll.url and ll.orasql uls supports
838            ssh and oracle URLs too.
839            """,
840        ),
841        PythonSourcePage(u"ucp",
842            crumb=u"ucp",
843            title=u"ll.scripts.ucp · Python software · LivingLogic AG",
844            header=u"ll.scripts.ucp",
845            subheader=u"Script for copying files/directories",
846            url=u"root:scripts/ucp.html",
847            inheritablekeywords=[u"ucp"],
848            hint=u"Script for  for copying files/directories",
849            description=u"""
850            ucp is a script that copies files/directory contents. It is an URL-enabled
851            version of the cp system command. Via ll.url and ll.orasql ucp supports
852            ssh and oracle URLs too.
853            """,
854        ),
855        crumb=u"ll.scripts",
856        title=u"ll.scripts · Python software · LivingLogic AG",
857        header=u"ll.scripts",
858        subheader=u"Scripts for rendering UL4 templates and working with URLs",
859        url=u"root:scripts/index.html",
860        inheritablekeywords=[u"script"],
861        localkeywords=[u"UL4", "template", "URL", "db2ul4", "uls", "ucp", "ucat"],
862        hint=u"Scripts for UL4 template rendering and URL handling",
863        description=u"""
864        ll.scripts is a Python packaged that contains the scripts db2ul4, ucls,
865        ucp and ucat.
866        """,
867    ),
868    PythonSourcePage(u"aplora",
869        XISTPage(u"history",
870            crumb=u"History",
871            title=u"Aplora history · Python software · LivingLogic AG",
872            header=u"Aplora history",
873            subheader=u"The development history",
874            url=u"root:aplora/History.html",
875            localkeywords=[u"packages", u"history", u"changes", u"version"],
876            hint=(u"ChangeLog for ", doc.mod("aplora")),
877        ),
878        XISTPage(u"installation",
879            crumb=u"Installation",
880            title=u"Aplora requirements, installation and configuration · Python software · LivingLogic AG",
881            header=u"Aplora installation",
882            subheader=u"Requirements, installation and configuration",
883            url=u"root:aplora/Installation.html",
884            localkeywords=[u"installation", u"distutils"],
885            hint=(u"How to install ", doc.mod("aplora")),
886        ),
887        crumb=u"Aplora",
888        title=u"Aplora · Python software · LivingLogic AG",
889        header=u"Aplora",
890        subheader=(u"Logging Apache ", abbr.http(), u" requests to an Oracle database"),
891        url=u"root:aplora/index.html",
892        localkeywords=[u"make", u"build", u"dependencies", u"development", u"target"],
893        hint=u"Logging Apache HTTP requests to an Oracle database",
894        description=u"""
895        ll-aplora is a script that can be used with Apaches piped logging facility
896        to log HTTP request to an Oracle database.
897        """,
898    ),
899    PythonSourcePage(u"pycoco",
900        XISTPage(u"history",
901            crumb=u"History",
902            title=u"Pycoco history · Python software · LivingLogic AG",
903            header=u"Pycoco history",
904            subheader=u"The development history",
905            url=u"root:pycoco/History.html",
906            localkeywords=[u"packages", u"history", u"changes", u"version"],
907            hint=(u"ChangeLog for", doc.mod("pycoco")),
908        ),
909        XISTPage(u"installation",
910            crumb=u"Installation",
911            title=u"Pycoco requirements, installation and configuration · Python software · LivingLogic AG",
912            header=u"Pycoco installation",
913            subheader=u"Requirements, installation and configuration",
914            url=u"root:pycoco/Installation.html",
915            localkeywords=[u"installation", u"distutils"],
916            hint=(u"How to install ", doc.mod("pycoco")),
917        ),
918        crumb=u"Pycoco",
919        title=u"Pycoco · Python software · LivingLogic AG",
920        header=u"Pycoco",
921        subheader=(u"Python code coverage report"),
922        url=u"root:pycoco/index.html",
923        localkeywords=[u"test", u"Python", "code coverage"],
924        hint=u"Python code coverage",
925        description=u"""
926        A script that can be used to generate code coverage info
927        for the Python source code.
928        """,
929    ),
930    XISTPage(u"download",
931        crumb=u"Download",
932        title=u"Download · Python software · LivingLogic AG",
933        header="Downloads",
934        subheader=u"All versions for download",
935        url=u"root:Download.html",
936        localkeywords=[u"download", u"file", u"archive"],
937        hint=u"Links to Windows and Linux, source and binary distributions",
938    ),
939    XISTPage(u"source",
940        crumb=u"Source code",
941        title=u"Source code · Python software · LivingLogic AG",
942        header=u"Source code",
943        subheader=(u"Access to the Mercurial repositories"),
944        url=u"root:Source.html",
945        localkeywords=[u"Mercurial", u"development", u"repository"],
946        hint=u"Access to the Mercurial repositories",
947        description=u"""
948        Provides a link to the Mercurial repositories for all
949        Open Source Python projects by LivingLogic.
950        """
951    ),
952    crumb=u"Python software",
953    title=u"Python software · LivingLogic AG",
954    header=u"Python packages",
955    subheader=u"Python packages and modules by LivingLogic",
956    url=u"root:index.html",
957    inheritablekeywords=[u"Living", u"Logic", u"LivingLogic", u"Bayreuth", u"Python"],
958    localkeywords=[u"packages", abbr.xist(), u"sisyphus", u"toxic", u"orasql"],
959    hint=u"list of projects",
960    description=u"""
961    LivingLogic provides several Open Source Python packages:
962    XIST, ll-url, ll-make, ll-color, ll-sisyphus, ll-toxic, ll-ul4, ll-orasql
963    """
964)
965
966
967class pageref(xsc.Element):
968    xmlns = xmlns
969    model = sims.NoElements()
970    class Attrs(xsc.Element.Attrs):
971        class ref(xsc.TextAttr): pass
972
973    def convert(self, converter):
974        if "ref" in self.attrs:
975            page = pages[unicode(self.attrs.ref.convert(converter))]
976        else:
977            page = pages
978        e = html.a(self.content, href=page.url, title=page.hint)
979        return e.convert(converter)
980
981
982class download(xsc.Element):
983    xmlns = xmlns
984    model = sims.Empty()
985    class Attrs(xsc.Element.Attrs):
986        class version(xsc.TextAttr): pass
987        class date(xsc.TextAttr): pass
988
989    base = "ssh://root@ftp.livinglogic.de/~ftp/pub/livinglogic/"
990
991    def file(self, converter, u):
992        target = converter.target
993        name = u.file
994        if name.endswith(".tar.gz") or name.endswith(".tar.bz2") or name.endswith(".zip"):
995            type = "Source"
996        elif name.endswith(".egg"):
997            if "win32" in name:
998                type = "Windows egg"
999            elif "linux" in name:
1000                type = "Linux egg"
1001            else:
1002                type = "Egg"
1003            pos = name.rfind("py")
1004            if pos >= 0:
1005                version = name[pos+2:pos+5]
1006                type += " (Python %s)" % version
1007        elif name.endswith(".exe"):
1008            type = "Windows installer"
1009            pos = name.rfind("py")
1010            if pos >= 0:
1011                version = name[pos+2:-4]
1012                type += " (Python %s)" % version
1013        elif name.endswith(".src.rpm"):
1014            type = "Source RPM"
1015        elif name.endswith(".rpm"):
1016            type = "Binary RPM"
1017        else:
1018            type = chars.nbsp()
1019
1020        href = ("http://ftp.livinglogic.de/", u.relative(self.base))
1021        if target.xmlns == doc.xmlns:
1022            e = target.li(target.a(unicode(name), href=href), " (", type,")")
1023        else:
1024            e = html.tr(
1025                html.td(html.a(unicode(name), href=href, title=("Download ", href)), class_="file"),
1026                html.td(type, class_="type"),
1027                html.td(u.size(), class_="size"),
1028                class_="download"
1029            )
1030        return e
1031
1032    def convert(self, converter):
1033        version = str(self.attrs.version.convert(converter))
1034        name = converter[downloads].name
1035        u = url.URL("%s/%s/" % (self.base, name))
1036        files = u/u.files("*-%s[-.][twpz]*" % version)
1037        files = (self.file(converter, f) for f in files)
1038        target = converter.target
1039        if target.xmlns == doc.xmlns:
1040            e = target.section(
1041                target.h("Version ", self.attrs.version, " (released ", self.attrs.date, ")"),
1042                target.ul(files),
1043            )
1044        else:
1045            with xsc.build():
1046                with xsc.Frag() as e:
1047                    with html.tr():
1048                        with html.th(self.attrs.version, class_="version"):
1049                            if "date" in self.attrs:
1050                                xsc.add(" ", html.span("(released ", self.attrs.date, ")", class_="note"))
1051                        +html.th("Type", class_="type")
1052                        +html.th("Bytes", class_="size")
1053                    xsc.add(files)
1054        return e.convert(converter)
1055
1056
1057class downloads(xsc.Element):
1058    xmlns = xmlns
1059    model = sims.Elements(download)
1060    class Attrs(xsc.Element.Attrs):
1061        class name(xsc.TextAttr): pass
1062    class Context(xsc.Element.Context):
1063        pass
1064
1065    def convert(self, converter):
1066        converter[self].name = str(self.attrs.name.convert(converter))
1067        target = converter.target
1068        if target.xmlns == doc.xmlns:
1069            e = self.content
1070        else:
1071            e = html.div(
1072                htmlspecials.plaintable(
1073                    self.content,
1074                    class_="downloads",
1075                ),
1076                align="center"
1077            )
1078        return e.convert(converter)
1079
1080
1081class alldownloads(xsc.Element):
1082    xmlns = xmlns
1083    model = sims.Elements(downloads)
1084
1085    def convert(self, converter):
1086        e = html.div(self.content, class_="alldownloads")
1087        return e.convert(converter)
1088
1089
1090class page(xsc.Element):
1091    xmlns = xmlns
1092    model = sims.Elements(alldownloads, doc.block)
1093    class Attrs(xsc.Element.Attrs):
1094        class refresh(xsc.TextAttr): pass
1095        class path(xsc.TextAttr): pass
1096
1097    def _nodetype(self, path, activepath):
1098        if path[-1] is activepath[-1]:
1099            return "here"
1100        elif path[-1] in activepath:
1101            return "path"
1102        else:
1103            return "other"
1104
1105    def _node(self, path, activepath):
1106        type = self._nodetype(path, activepath)
1107        page = path[-1]
1108        if type == "here":
1109            e = html.div(page.crumb, html.span(page.hint, class_="hint"))
1110            children = True
1111        else:
1112            e = html.a(
1113                page.crumb,
1114                html.span(page.hint, class_="hint"),
1115                href=page.url,
1116                class_=type,
1117            )
1118            children = (type == "path")
1119        if len(path) > 1:
1120            e = html.li(e, class_=type)
1121        else:
1122            e = xsc.Frag(e)
1123        if children:
1124            e.append(self._children(path, activepath))
1125        return e
1126
1127    def _children(self, path, activepath):
1128        return html.ul(self._node(path + [child], activepath) for child in path[-1].getChildren())
1129
1130    def _links(self, context):
1131        return self._node([pages], context.page.getPath())
1132
1133    def _crumbs(self, context):
1134        e = xsc.Frag()
1135        page = context.page
1136        while page is not None:
1137            if page is context.page:
1138                e.insert(0, html.span(page.crumb, class_=u"here"))
1139            else:
1140                e.insert(0, pageref(page.crumb, ref=page.getPathString()))
1141            e.insert(0, u"\xa0\u203a\xa0")
1142            page = page.parent
1143        e.insert(0, html.a(u"Home", href=u"http://www.livinglogic.de/", hreflang=u"de", title=u"The company homepage (in german)"))
1144        return e
1145
1146    def convert(self, converter):
1147        converter[doc.pyref].base = "root:"
1148        target = converter.target
1149        context = converter[self]
1150        context.path = unicode(self["path"].convert(converter))
1151        context.page = pages[context.path]
1152        if target.xmlns == doc.xmlns:
1153            return self.content.convert(converter)
1154        elif not target.xmlns == html.xmlns:
1155            raise ValueError("unknown conversion target %r" % target)
1156        else:
1157            with xsc.build():
1158                with xsc.Frag(xml.XML(), u"\n", target.DocTypeXHTML10transitional(), u"\n") as e:
1159                    with target.html(xml.Attrs(lang=u"en"), lang=u"en"):
1160                        with target.head():
1161                            +meta.contenttype()
1162                            +target.title(unicode(xsc.Frag(context.page.title).convert(converter)))
1163                            if context.page.keywords:
1164                                +meta.keywords(xsc.Frag(*context.page.keywords).withsep(", "))
1165                            if context.page.description is not None:
1166                                +meta.description(context.page.description)
1167                            +meta.stylesheet(href="root:main_screen.css", media=u"screen, projection, tv")
1168                            +meta.stylesheet(href="root:main_print.css", media=u"print")
1169                            +meta.author(name=u"Walter Dörwald", email=u"walter.doerwald@livinglogic.de")
1170                            icbm = u"49.9550; 11.5909"
1171                            +html.meta(name=u"icbm", content=icbm)
1172                            +html.meta(name=u"geo.position", content=icbm)
1173                            +html.meta(name=u"geo.placename", content=u"Bayreuth, Germany, Europe")
1174                            +html.meta(name=u"geo.region", content=u"DE-BY")
1175                            +html.meta(name=u"DC.title", content=context.page.title)
1176                            +html.link(rel=u"icon", href=u"root:images/favicon.gif", type=u"image/gif")
1177                            top = context.page.getRoot()
1178                            if top is not None and top != context.page:
1179                                +html.link(rel="top", href=top.url)
1180                            parent = context.page.parent
1181                            if parent is not None:
1182                                +html.link(rel="up", href=parent.url)
1183                            firstsibling = context.page.getFirstSibling()
1184                            if firstsibling is not None and firstsibling != context.page:
1185                                +html.link(rel="first", title="First page in set", href=firstsibling.url)
1186                            prevsibling = context.page.getPrevSibling()
1187                            if prevsibling is not None and prevsibling != context.page:
1188                                +html.link(rel="prev", title="Previous page", href=prevsibling.url)
1189                            nextsibling = context.page.getNextSibling()
1190                            if nextsibling is not None and nextsibling != context.page:
1191                                +html.link(rel="next", title="Next page", href=nextsibling.url)
1192                            lastsibling = context.page.getLastSibling()
1193                            if lastsibling is not None and lastsibling != context.page:
1194                                +html.link(rel="last", title="Last page in set", href=lastsibling.url)
1195                            for link in context.page.alternates():
1196                                +html.link(link.attrs)
1197                            if "refresh" in self.attrs:
1198                                +html.meta(http_equiv="refresh", content=self.attrs.refresh)
1199
1200                        with target.body():
1201                            with html.div(class_="header"):
1202                                if context.page.header:
1203                                    +html.h1(context.page.header)
1204                                if context.page.subheader:
1205                                    +html.h2(context.page.subheader)
1206                            with html.div(class_="crumbs"):
1207                                with htmlspecials.plaintable(width="100%"):
1208                                    with html.tr(valign="middle"):
1209                                        +html.td(self._crumbs(context), class_="crumbs")
1210                                        +html.td(xsc.Frag(context.page.alternates()).withsep(u"\xa0\xb7\xa0"), align="right", class_="alternate")
1211                            with html.div(class_="body"):
1212                                +html.div(self._links(context), class_="links")
1213                                +html.div(self.content, class_="content")
1214        return e.convert(converter)
Note: See TracBrowser for help on using the browser.