/usr/share/pyshared/kid/template_util.py is in python-kid 0.9.6-2.1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 | # -*- coding: utf-8 -*-
"""Utility functions used by generated kid modules."""
__revision__ = "$Rev: 492 $"
__date__ = "$Date: 2007-07-06 21:38:45 -0400 (Fri, 06 Jul 2007) $"
__author__ = "Ryan Tomayko (rtomayko@gmail.com)"
__copyright__ = "Copyright 2004-2005, Ryan Tomayko"
__license__ = "MIT <http://www.opensource.org/licenses/mit-license.php>"
import inspect
import sys
from types import TypeType, ModuleType, ClassType, GeneratorType
import itertools
# these are for use by template code
import kid
from kid.parser import XML, document, ElementStream, START, END, TEXT, \
START_NS, COMMENT, PI, DOCTYPE, XML_DECL, to_unicode
from kid.element import Element, SubElement, Comment, ProcessingInstruction
__all__ = ['XML', 'document', 'ElementStream',
'Element', 'SubElement', 'Comment', 'ProcessingInstruction',
'START', 'END', 'TEXT', 'START_NS', 'COMMENT', 'PI',
'DOCTYPE', 'XML_DECL']
class TemplateError(Exception): pass
class TemplateNotFound(TemplateError): pass
class TemplateImportError(TemplateError): pass
class TemplateDictError(TemplateError): pass
class TemplateAttrsError(TemplateError): pass
class TemplateExtendsError(TemplateError): pass
class TemplateLayoutError(TemplateError): pass
_local_excludes = ['generate', 'module', 'parser', 'serialize', 'transform', 'write']
def get_locals(inst, _locals=None):
if _locals is None:
_locals = {}
ls = []
local_excludes = _local_excludes # local copy
for var, value in inspect.getmembers(inst):
if not var.startswith('_') and not var in local_excludes \
and var not in _locals:
ls.append('%s=self.%s' % (var, var))
return ';'.join(ls)
def get_base_class(thing, from_file=None, arg=None):
"""Get template base class for thing, raising an exception on error."""
if thing is None:
return kid.BaseTemplate
if isinstance(thing, TypeType):
return thing
elif isinstance(thing, ModuleType):
try:
cls = thing.Template
except AttributeError:
cls = None
if (isinstance(cls, TypeType)
and issubclass(cls, kid.BaseTemplate)
and cls != kid.Template):
return cls
thing = repr(thing)
if arg:
thing = arg
else:
try:
thing = thing.__name__
except AttributeError:
thing = repr(thing)
raise TemplateNotFound(
'%s is a module without Template class' % thing)
elif isinstance(thing, basestring):
try:
path = kid.path.find(thing, from_file)
except Exception:
path = None
if not path:
if arg:
thing = arg
raise TemplateNotFound('Template file %r not found' % thing)
try:
mod = kid.load_template(path)
except Exception:
mod = None
if not mod:
raise TemplateNotFound('Could not open %r' % path)
try:
cls = mod.Template
except AttributeError:
cls = None
if (isinstance(cls, TypeType)
and issubclass(cls, kid.BaseTemplate)
and cls != kid.Template):
return cls
raise TemplateNotFound('%r does not contain a template class' % path)
thing = repr(thing)
if arg:
thing = '%s (%s)' % (arg, thing)
raise TemplateNotFound('%s is not a Template class' % thing)
def base_class(arg, globals, locals):
"""Get base class for argument with graceful exception handling."""
try:
from_file = globals['__file__']
thing = eval(arg, globals, locals)
return get_base_class(thing, from_file, arg)
except Exception, e:
errors = [str(e)]
# try again without evaluating the argument (forgotten quotes etc.)
try:
return get_base_class(arg, from_file, arg)
except Exception, e:
errors.append(str(e))
# reraise the original problem when we tried to evaluate the thing
errors = '\n'.join(filter(bool, errors)) or arg
raise TemplateNotFound, errors
def base_class_extends(extends, globals, locals, all_extends=None):
"""Get Template base class for 'extends'."""
try:
return base_class(extends, globals, locals)
except Exception, e:
raise TemplateExtendsError((str(e)
+ '\nwhile processing extends=%r'
% (all_extends or extends)).lstrip())
def base_class_layout(layout, globals, locals):
"""Get Template base class for 'layout'."""
try:
return base_class(layout, globals, locals)
except Exception, e:
raise TemplateLayoutError((str(e)
+ '\nwhile processing layout=%r' % layout).lstrip())
def make_attrib(attrib, encoding=None):
"""Generate unicode strings in dictionary."""
if attrib is None:
return {}
if encoding is None:
encoding = sys.getdefaultencoding()
for (k, v) in attrib.items():
if v is not None:
try:
v = generate_attrib(v, encoding)
except TemplateAttrsError:
raise TemplateAttrsError('Illegal value for attribute "%s"'
% k.encode('raw_unicode_escape'))
if v is None:
del attrib[k]
else:
attrib[k] = v
return attrib
def generate_attrib(attrib, encoding):
"""Generate unicode string from attribute."""
if attrib is None:
return None
elif isinstance(attrib, basestring):
return to_unicode(attrib, encoding)
elif isinstance(attrib, ElementStream):
text = []
for ev, item in attrib:
if ev == TEXT:
text.append(to_unicode(item, encoding))
else:
raise TemplateAttrsError
if text:
return ''.join(text)
else:
return None
elif hasattr(attrib, '__iter__'):
# if we get any other iterable, join the strings together:
text = []
for item in attrib:
if item is not None:
item = generate_attrib(item, encoding)
if item is not None:
text.append(item)
if text:
return ''.join(text)
else:
return None
else:
return to_unicode(attrib, encoding)
def generate_content(content):
"""Generate ElementStream from content."""
if content is None:
return []
elif isinstance(content, basestring):
return [(TEXT, content)]
elif isinstance(content, (ElementStream, kid.BaseTemplate)):
return content
elif isinstance(content, GeneratorType):
return ElementStream(content)
elif hasattr(content, 'tag') and hasattr(content, 'attrib'):
# if we get an Element back, make it an ElementStream
return ElementStream(content)
elif hasattr(content, '__iter__'):
# if we get any other iterable, chain the contents together:
return itertools.chain(*itertools.imap(generate_content, content))
else:
return [(TEXT, unicode(content))]
def filter_names(names, omit_list):
for ns in names.keys():
if ns in omit_list:
del names[ns]
return names
def update_dict(a, args, globals, locals):
"""Update dictionary a from keyword argument string args."""
try:
b = eval('%s' % args, globals, locals)
if not isinstance(b, dict):
b = dict(b)
except Exception:
try:
b = eval('dict(%s)' % args, globals, locals)
except SyntaxError:
# TypeErrror could happen with Python versions < 2.3, because
# building dictionaries from keyword arguments was not supported.
# Kid requires a newer Python version, so we do not catch this.
# SyntaxError can happen if one of the keyword arguments is
# the same as a Python keyword (e.g. "class") or if it is
# a qualified name containing a namespace prefixed with a colon.
# In these cases we parse the keyword arguments manually:
try:
try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO
from tokenize import generate_tokens
from token import NAME, OP
depth, types, parts = 0, [], []
for token in generate_tokens(StringIO(args).readline):
type_, string = token[:2]
if type_ == OP:
if string == '=':
if depth == 0:
if len(types) > 0 \
and types[-1] == NAME and parts[-1]:
if len(types) > 2 \
and types[-2] == OP and parts[-2] == ':' \
and types[-3] == NAME and parts[-3]:
parts[-3:] = ["'%s'" % ''.join(parts[-3:])]
else:
parts[-1] = "'%s'" % parts[-1]
string = ':'
elif string in '([{':
depth += 1
elif depth > 0 and string in ')]}':
depth -= 1
types.append(type_)
parts.append(string)
b = eval('{%s}' % ''.join(parts), globals, locals)
except Exception:
b = None
if not isinstance(b, dict):
raise
for k in b.keys():
if b[k] is None:
del b[k]
if k in a:
del a[k]
a.update(b)
return a
def update_attrs(attrib, attrs, globals, locals):
"""Update attributes from attrs string args."""
try:
return update_dict(attrib, attrs, globals, locals)
except Exception, e:
raise TemplateAttrsError((str(e)
+ '\nwhile processing attrs=%r' % attrs).lstrip())
def make_updated_attrib(attrib, attrs, globals, locals, encoding=None):
""""Generate unicode strings in updated dictionary."""
return make_attrib(update_attrs(attrib, attrs, globals, locals), encoding)
|