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']