[Cvs-annodex] commit (annodex): cmmlwiki/trunk/README
cmmlwiki/trunk/cmmlwiki/request.py
+cmmlwiki/trunk/cmmlwiki/clearsilver.py
+cmmlwiki/trunk/cmmlwiki/css.py +cmmlwiki/trunk/cmmlwiki/template.py
conrad
nobody at lists.annodex.net
Tue Sep 12 03:15:40 UTC 2006
Update of /var/local/lib/svn/annodex (new revision 2455)
Added files:
cmmlwiki/trunk/cmmlwiki/clearsilver.py
cmmlwiki/trunk/cmmlwiki/css.py
cmmlwiki/trunk/cmmlwiki/template.py
Modified files:
cmmlwiki/trunk/README
cmmlwiki/trunk/cmmlwiki/request.py
Log Message:
add Clearsilver templating, a general Template class, a CSS class, and a
handler for Special:CSS which munges in the current CSS skin with appropriate
substitutions
Modified: cmmlwiki/trunk/README
===================================================================
--- cmmlwiki/trunk/README 2006-09-12 00:38:29 UTC (rev 2454)
+++ cmmlwiki/trunk/README 2006-09-12 03:15:40 UTC (rev 2455)
@@ -8,6 +8,8 @@
pyannodex: http://benno.id.au/code/pyannodex.pml
+Clearsilver, and its Python bindings: http://www.clearsilver.net/
+
Additionally, the following commandline tools are required:
oggzinfo, oggz-scan
@@ -19,7 +21,7 @@
Available from http://www.mplayerhq.hu/
On Debian, the oggz tools and required python packages are:
- oggz-tools python-xml python-sqlite
+ oggz-tools python-xml python-sqlite python-clearsilver
in addition to
python apache2
To use GStreamer for frame extraction, you also need:
Added: cmmlwiki/trunk/cmmlwiki/clearsilver.py
===================================================================
--- cmmlwiki/trunk/cmmlwiki/clearsilver.py 2006-09-12 00:38:29 UTC (rev 2454)
+++ cmmlwiki/trunk/cmmlwiki/clearsilver.py 2006-09-12 03:15:40 UTC (rev 2455)
@@ -0,0 +1,337 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2005 Edgewall Software
+# Copyright (C) 2005 Christopher Lenz <cmlenz at gmx.de>
+# All rights reserved.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at http://trac.edgewall.com/license.html.
+#
+# This software consists of voluntary contributions made by many
+# individuals. For the exact contribution history, see the revision
+# history and logs, available at http://projects.edgewall.com/trac/.
+#
+# Author: Christopher Lenz <cmlenz at gmx.de>
+
+# Adapted from Trac
+# We don't use Trac's Markup, Fragment objects
+
+#from trac.core import TracError
+#from trac.util.markup import Markup, Fragment, escape
+#from trac.util.text import to_unicode
+
+from xml.sax.saxutils import escape
+
+def to_unicode(text, charset=None, lossy=True):
+ """Convert a `str` object to an `unicode` object.
+
+ If `charset` is not specified, we'll make some guesses,
+ first trying the UTF-8 encoding then trying the locale
+ preferred encoding (this differs from the `unicode` function
+ which only tries with the locale preferred encoding, in 'strict'
+ mode).
+
+ If the `lossy` argument is `True`, which is the default, then
+ we use the 'replace' mode:
+
+ If the `lossy` argument is `False`, we fallback to the 'iso-8859-15'
+ charset in case of an error (encoding a `str` using 'iso-8859-15'
+ will always work, as there's one Unicode character for each byte of
+ the input).
+ """
+ if not isinstance(text, str):
+ if isinstance(text, Exception):
+ # two possibilities for storing unicode strings in exception data:
+ try:
+ # custom __str__ method on the exception (e.g. PermissionError)
+ return unicode(text)
+ except UnicodeError:
+ # unicode arguments given to the exception (e.g. parse_date)
+ return ' '.join([to_unicode(arg) for arg in text.args])
+ return unicode(text)
+ errors = lossy and 'replace' or 'strict'
+ try:
+ if charset:
+ return unicode(text, charset, errors)
+ else:
+ try:
+ return unicode(text, 'utf-8')
+ except UnicodeError:
+ return unicode(text, locale.getpreferredencoding(), errors)
+ except UnicodeError:
+ return unicode(text, 'iso-8859-15')
+
+class HDFWrapper:
+ """
+ Convenience layer on top of the low-level ClearSilver python bindings
+ for HDF manipulation. This class makes the HDF look and behave more
+ like a standard Python dict.
+
+ >>> hdf = HDFWrapper()
+ >>> hdf['trac.url'] = 'http://projects.edgewall.com/trac/'
+ >>> hdf['trac.version'] = '1.0'
+ >>> print hdf
+ trac {
+ url = http://projects.edgewall.com/trac/
+ version = 1.0
+ }
+
+ HDFWrapper can also assign Python lists and dicts to HDF nodes,
+ automatically expanding them into the corresponding HDF structure.
+
+ A dictionary is mapped to a HDF node with named children:
+
+ >>> hdf = HDFWrapper()
+ >>> hdf['item'] = {'name': 'An item', 'value': '0'}
+ >>> print hdf
+ item {
+ name = An item
+ value = 0
+ }
+
+ A sequence is mapped to a HDF node with children whose names are
+ the indexes of the elements:
+
+ >>> hdf = HDFWrapper()
+ >>> hdf['items'] = ['Item 1', 'Item 2']
+ >>> print hdf
+ items {
+ 0 = Item 1
+ 1 = Item 2
+ }
+
+ Simple values can also be easily retrieved using the same syntax.
+
+ >>> hdf = HDFWrapper()
+ >>> hdf['time'] = 42
+ >>> hdf['time']
+ u'42'
+ >>> hdf['name'] = 'Foo'
+ >>> hdf['name']
+ u'Foo'
+
+ An attempt to retrieve a value that hasn't been set will raise a KeyError,
+ just like a standard dictionary:
+
+ >>> hdf['undef']
+ Traceback (most recent call last):
+ ...
+ KeyError: 'undef'
+
+ It may be preferable to return a default value if the given key does not exit.
+ It will return 'None' when the specified key is not present:
+
+ >>> hdf.get('time')
+ u'42'
+ >>> hdf.get('undef')
+
+ A second argument may be passed to specify the default return value:
+
+ >>> hdf.get('time', 'Undefined Key')
+ u'42'
+ >>> hdf.get('undef', 'Undefined Key')
+ 'Undefined Key'
+
+ The 'in' and 'not in' operators can be used to test whether the HDF contains
+ a value with a given name.
+
+ >>> 'name' in hdf
+ True
+ >>> 'undef' in hdf
+ False
+
+ has_key() performs the same function:
+
+ >>> hdf.has_key('name')
+ True
+ >>> hdf.has_key('undef')
+ False
+ """
+
+ def __init__(self, loadpaths=[]):
+ """Create a new HDF dataset.
+
+ The loadpaths parameter can be used to specify a sequence of paths under
+ which ClearSilver will search for template files:
+
+ >>> hdf = HDFWrapper(loadpaths=['/etc/templates',
+ ... '/home/john/templates'])
+ >>> print hdf
+ hdf {
+ loadpaths {
+ 0 = /etc/templates
+ 1 = /home/john/templates
+ }
+ }
+ """
+ #try:
+ import neo_cgi
+ # The following line is needed so that ClearSilver can be loaded when
+ # we are being run in multiple interpreters under mod_python
+ neo_cgi.update()
+ import neo_util
+ self.hdf = neo_util.HDF()
+ #except ImportError, e:
+ # raise TracError, "ClearSilver not installed (%s)" % e
+
+ self['hdf.loadpaths'] = loadpaths
+
+ def __getattr__(self, name):
+ # For backwards compatibility, expose the interface of the underlying HDF
+ # object
+ return getattr(self.hdf, name)
+
+ def __contains__(self, name):
+ return self.hdf.getObj(str(name)) != None
+ has_key = __contains__
+
+ def get(self, name, default=None):
+ value = self.hdf.getValue(str(name), '<<NONE>>')
+ if value == '<<NONE>>':
+ return default
+ return value.decode('utf-8')
+
+ def __getitem__(self, name):
+ value = self.get(name, None)
+ if value == None:
+ raise KeyError, name
+ return value
+
+ def __setitem__(self, name, value):
+ """Add data to the HDF dataset.
+
+ The `name` parameter is the path of the node in dotted syntax. The
+ `value` parameter can be a simple value such as a string or number, but
+ also data structures such as dicts and lists.
+
+ >>> hdf = HDFWrapper()
+
+ Adding a simple value results in that value being inserted into the HDF
+ after being converted to a string.
+
+ >>> hdf['test.num'] = 42
+ >>> hdf['test.num']
+ u'42'
+ >>> hdf['test.str'] = 'foo'
+ >>> hdf['test.str']
+ u'foo'
+
+ The boolean literals `True` and `False` are converted to there integer
+ representation before being added:
+
+ >>> hdf['test.true'] = True
+ >>> hdf['test.true']
+ u'1'
+ >>> hdf['test.false'] = False
+ >>> hdf['test.false']
+ u'0'
+
+ If value is `None`, nothing is added to the HDF:
+
+ >>> hdf['test.true'] = None
+ >>> hdf['test.none']
+ Traceback (most recent call last):
+ ...
+ KeyError: 'test.none'
+ """
+ self.set_value(name, value, True)
+
+ def set_unescaped(self, name, value):
+ """
+ Add data to the HDF dataset.
+
+ This method works the same way as `__setitem__` except that `value`
+ is not escaped if it is a string.
+ """
+ self.set_value(name, value, False)
+
+ def set_value(self, name, value, do_escape=True):
+ """
+ Add data to the HDF dataset.
+ """
+ def set_unicode(prefix, value):
+ self.hdf.setValue(prefix.encode('utf-8'), value.encode('utf-8'))
+ def set_str(prefix, value):
+ self.hdf.setValue(prefix.encode('utf-8'), str(value))
+
+ def add_value(prefix, value):
+ if value is None:
+ return
+ if value in (True, False):
+ set_str(prefix, int(value))
+ #elif isinstance(value, (Markup, Fragment)):
+ # set_unicode(prefix, unicode(value))
+ elif isinstance(value, str):
+ if do_escape:
+ # Assume UTF-8 here, for backward compatibility reasons
+ set_unicode(prefix, escape(to_unicode(value)))
+ else:
+ set_str(prefix, value)
+ elif isinstance(value, unicode):
+ if do_escape:
+ set_unicode(prefix, escape(value))
+ else:
+ set_unicode(prefix, value)
+ elif isinstance(value, dict):
+ for k in value.keys():
+ add_value('%s.%s' % (prefix, k), value[k])
+ else:
+ if hasattr(value, '__iter__') or \
+ isinstance(value, (list, tuple)):
+ for idx, item in enumerate(value):
+ add_value('%s.%d' % (prefix, idx), item)
+ else:
+ set_str(prefix, value)
+ add_value(name, value)
+
+ def __str__(self):
+ from StringIO import StringIO
+ buf = StringIO()
+ def hdf_tree_walk(node, prefix=''):
+ while node:
+ name = node.name() or ''
+ buf.write('%s%s' % (prefix, name))
+ value = node.value()
+ if value or not node.child():
+ if value.find('\n') == -1:
+ buf.write(' = %s' % value)
+ else:
+ buf.write(' = << EOM\n%s\nEOM' % value)
+ if node.child():
+ buf.write(' {\n')
+ hdf_tree_walk(node.child(), prefix + ' ')
+ buf.write('%s}\n' % prefix)
+ else:
+ buf.write('\n')
+ node = node.next()
+ hdf_tree_walk(self.hdf.child())
+ return buf.getvalue().strip()
+
+ def parse(self, string):
+ """Parse the given string as template text, and returns a neo_cs.CS
+ object.
+ """
+ import neo_cs
+ cs = neo_cs.CS(self.hdf)
+ cs.parseStr(string)
+ return cs
+
+ def render(self, template):
+ """Render the HDF using the given template.
+
+ The template parameter can be either an already parse neo_cs.CS
+ object, or a string. In the latter case it is interpreted as name of the
+ template file.
+ """
+ if isinstance(template, basestring):
+ filename = template
+ import neo_cs
+ template = neo_cs.CS(self.hdf)
+ template.parseFile(filename)
+ return template.render()
+
+
+if __name__ == '__main__':
+ import doctest, sys
+ doctest.testmod(sys.modules[__name__])
Added: cmmlwiki/trunk/cmmlwiki/css.py
===================================================================
--- cmmlwiki/trunk/cmmlwiki/css.py 2006-09-12 00:38:29 UTC (rev 2454)
+++ cmmlwiki/trunk/cmmlwiki/css.py 2006-09-12 03:15:40 UTC (rev 2455)
@@ -0,0 +1,27 @@
+# -*- coding: iso8859-1 -*-
+#
+# Copyright (C) 2006 CSIRO Australia
+# All rights reserved.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution.
+#
+# This software consists of voluntary contributions made by many
+# individuals. For exact contribution history, see the revision
+# history and logs.
+#
+# Author: Conrad Parker <conrad at annodex.net>
+
+from cmmlwiki.template import Template
+
+class CSS:
+ def content_type(self):
+ return "text/css"
+
+ def template(self, vars):
+ main_css = "/usr/share/cmmlwiki/htdocs/stylesheets/main.css"
+ video_monitor_css = "/usr/share/cmmlwiki/htdocs/stylesheets/video-monitor.css"
+ s = Template(main_css).template(vars)
+ s += Template(video_monitor_css).template(vars)
+
+ return s
Modified: cmmlwiki/trunk/cmmlwiki/request.py
===================================================================
--- cmmlwiki/trunk/cmmlwiki/request.py 2006-09-12 00:38:29 UTC (rev 2454)
+++ cmmlwiki/trunk/cmmlwiki/request.py 2006-09-12 03:15:40 UTC (rev 2455)
@@ -18,6 +18,7 @@
import sys
from cmmlwiki.response import Response
+from cmmlwiki.css import CSS
from cmmlwiki.rssfeed import RSSFeed
from cmmlwiki.htmlpage import HTMLPage
from cmmlwiki.channel import Channel
@@ -153,6 +154,8 @@
o = HTMLPage(s)
elif (command == "RSS"):
o = RSSFeed(handler)
+ elif (command == "CSS"):
+ o = CSS()
else:
o = handler.error ('Invalid request %s' % (command))
Added: cmmlwiki/trunk/cmmlwiki/template.py
===================================================================
--- cmmlwiki/trunk/cmmlwiki/template.py 2006-09-12 00:38:29 UTC (rev 2454)
+++ cmmlwiki/trunk/cmmlwiki/template.py 2006-09-12 03:15:40 UTC (rev 2455)
@@ -0,0 +1,26 @@
+# -*- coding: iso8859-1 -*-
+#
+# Copyright (C) 2006 CSIRO Australia
+# All rights reserved.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution.
+#
+# This software consists of voluntary contributions made by many
+# individuals. For exact contribution history, see the revision
+# history and logs.
+#
+# Author: Conrad Parker <conrad at annodex.net>
+
+from cmmlwiki.clearsilver import HDFWrapper
+from cmmlwiki.location import WikiURL
+
+class Template:
+ def __init__(self, tfile):
+ self.tfile = tfile
+ self.hdf = HDFWrapper()
+
+ def template(self, vars):
+ self.hdf['vars'] = vars
+ self.hdf['StaticURL'] = WikiURL(htdocs=True).template(vars)
+ return self.hdf.render(self.tfile)
--
conrad
More information about the cvs-annodex
mailing list