0001"""Utility functions used by generated kid modules.
0002"""
0003
0004from __future__ import generators
0005
0006__revision__ = "$Rev: 314 $"
0007__date__ = "$Date: 2006-04-18 00:37:38 +0000 (Tue, 18 Apr 2006) $"
0008__author__ = "Ryan Tomayko (rtomayko@gmail.com)"
0009__copyright__ = "Copyright 2004-2005, Ryan Tomayko"
0010__license__ = "MIT <http://www.opensource.org/licenses/mit-license.php>"
0011
0012import inspect
0013import sys
0014from types import TypeType, ModuleType
0015from os.path import join, normpath, abspath, dirname
0016
0017
0018import kid
0019from kid.pull import XML, document, ElementStream, Element, SubElement, Comment, ProcessingInstruction, START, END, TEXT, START_NS, COMMENT, PI, DOCTYPE, XML_DECL, to_unicode
0023
0024class TemplateNotFound(Exception): pass
0025
0026_local_excludes = ['generate', 'module', 'pull', 'serialize', 'transform', 'write']
0027def get_locals(inst, _locals=None):
0028 if _locals is None:
0029 _locals = {}
0030 ls = []
0031 local_excludes = _local_excludes
0032 for var, value in inspect.getmembers(inst):
0033 if not var.startswith('_') and not var in local_excludes and var not in _locals:
0035 ls.append('%s=self.%s' % (var, var))
0036 return ';'.join(ls)
0037
0038def get_base_class(thing, from_file):
0039 if thing is None or thing is kid.BaseTemplate:
0040 cls = kid.BaseTemplate
0041 elif isinstance(thing, basestring):
0042 path = kid.path.find(thing, from_file)
0043 cls = kid.load_template(path).Template
0044 elif isinstance(thing, TypeType):
0045 cls = thing
0046 elif isinstance(thing, ModuleType):
0047 cls = thing.Template
0048 else:
0049 raise TemplateNotFound("Could not find template: %r" % thing)
0050 return cls
0051
0052def make_attrib(attrib, encoding=None):
0053 if attrib is None:
0054 return {}
0055 if encoding is None:
0056 encoding = sys.getdefaultencoding()
0057
0058 for (k, v) in attrib.items():
0059 if isinstance(v, list):
0060 ls = [to_unicode(i, encoding) for i in v if i is not None]
0061 if not ls:
0062 del attrib[k]
0063 else:
0064 attrib[k] = ''.join(ls)
0065 else:
0066 attrib[k] = to_unicode(v, encoding)
0067 return attrib
0068
0069def generate_content(content, parent=None):
0070 if content is None:
0071 return []
0072 if isinstance(content, basestring):
0073 return [(TEXT, content)]
0074 elif hasattr(content, 'tag') and hasattr(content, 'attrib'):
0075
0076 return ElementStream(content)
0077 elif hasattr(content, '__iter__'):
0078
0079 if hasattr(content, '__getitem__'):
0080
0081 def flatten(seq):
0082 for i in seq:
0083 for ev, item in generate_content(i):
0084 yield ev, item
0085 return flatten(content)
0086 else:
0087
0088 return content
0089 else:
0090 return [(TEXT, unicode(content))]
0091
0092def filter_names(names, omit_list):
0093 for ns in names.keys():
0094 if ns in omit_list:
0095 del names[ns]
0096 return names
0097
0098def update_dict(a, s, globals, locals):
0099 """Update dictionary a from keyword argument string s."""
0100 try:
0101 strings = None
0102 try:
0103 b = eval('dict(%s)' % s, globals, locals)
0104 except (TypeError, SyntaxError):
0105
0106
0107
0108
0109
0110
0111 try:
0112 from cStringIO import StringIO
0113 except ImportError:
0114 from StringIO import StringIO
0115 from tokenize import generate_tokens
0116 from token import NAME, OP
0117 depth, types, strings = 0, [], []
0118 for token in generate_tokens(StringIO(s).readline):
0119 type_, string = token[:2]
0120 if type_ == OP:
0121 if string == '=':
0122 if depth == 0:
0123 if len(types) > 0 and types[-1] == NAME and strings[-1]:
0125 if len(types) > 2 and types[-2] == OP and strings[-2] == ':' and types[-3] == NAME and strings[-3]:
0128 strings[-3:] = ["'%s'" % ''.join(strings[-3:])]
0129 else:
0130 strings[-1] = "'%s'" % strings[-1]
0131 string = ':'
0132 elif string in '([{':
0133 depth += 1
0134 elif depth > 0 and string in ')]}':
0135 depth -= 1
0136 types.append(type_)
0137 strings.append(string)
0138 b = eval('{%s}' % ''.join(strings), globals, locals)
0139 except Exception:
0140 exc_type, exc_obj, tb = sys.exc_info()
0141 if strings is None:
0142 code = s
0143 else:
0144 code = "%s -> %s" % (s, ''.join(strings))
0145 raise exc_type("%s in %s" % (exc_obj, code))
0146 for k in b.keys():
0147 if b[k] is None:
0148 del b[k]
0149 if k in a:
0150 del a[k]
0151 a.update(b)
0152 return a
0153
0154__all__ = ['XML', 'document', 'ElementStream',
0155 'Element', 'SubElement', 'Comment', 'ProcessingInstruction',
0156 'START', 'END', 'TEXT', 'START_NS', 'COMMENT',
0157 'PI', 'DOCTYPE', 'XML_DECL']