class Attrs(tuple):
    """Immutable sequence type that stores the attributes of an element.
    
    Ordering of the attributes is preserved, while access by name is also
    supported.
    
    >>> attrs = Attrs([('href', '#'), ('title', 'Foo')])
    >>> attrs
    Attrs([('href', '#'), ('title', 'Foo')])
    
    >>> 'href' in attrs
    True
    >>> 'tabindex' in attrs
    False
    >>> attrs.get('title')
    'Foo'
    
    Instances may not be manipulated directly. Instead, the operators ``|`` and
    ``-`` can be used to produce new instances that have specific attributes
    added, replaced or removed.
    
    To remove an attribute, use the ``-`` operator. The right hand side can be
    either a string or a set/sequence of strings, identifying the name(s) of
    the attribute(s) to remove:
    
    >>> attrs - 'title'
    Attrs([('href', '#')])
    >>> attrs - ('title', 'href')
    Attrs()
    
    The original instance is not modified, but the operator can of course be
    used with an assignment:

    >>> attrs
    Attrs([('href', '#'), ('title', 'Foo')])
    >>> attrs -= 'title'
    >>> attrs
    Attrs([('href', '#')])
    
    To add a new attribute, use the ``|`` operator, where the right hand value
    is a sequence of ``(name, value)`` tuples (which includes `Attrs`
    instances):
    
    >>> attrs | [('title', 'Bar')]
    Attrs([('href', '#'), ('title', 'Bar')])
    
    If the attributes already contain an attribute with a given name, the value
    of that attribute is replaced:
    
    >>> attrs | [('href', 'http://example.org/')]
    Attrs([('href', 'http://example.org/')])
    """
    __slots__ = []

    def __contains__(self, name):
        """Return whether the list includes an attribute with the specified
        name.
        
        :return: `True` if the list includes the attribute
        :rtype: `bool`
        """
        for attr, _ in self:
            if attr == name:
                return True

    def __getitem__(self, i):
        """Return an item or slice of the attributes list.
        
        >>> attrs = Attrs([('href', '#'), ('title', 'Foo')])
        >>> attrs[1]
        ('title', 'Foo')
        >>> attrs[1:]
        Attrs([('title', 'Foo')])
        """
        items = tuple.__getitem__(self, i)
        if type(i) is slice:
            return Attrs(items)
        return items

    def __getslice__(self, i, j):
        """Return a slice of the attributes list.
        
        >>> attrs = Attrs([('href', '#'), ('title', 'Foo')])
        >>> attrs[1:]
        Attrs([('title', 'Foo')])
        """
        return Attrs(tuple.__getslice__(self, i, j))

    def __or__(self, attrs):
        """Return a new instance that contains the attributes in `attrs` in
        addition to any already existing attributes. Any attributes in the new
        set that have a value of `None` are removed.
        
        :return: a new instance with the merged attributes
        :rtype: `Attrs`
        """
        remove = set([an for an, av in attrs if av is None])
        replace = dict([(an, av) for an, av in attrs
                        if an in self and av is not None])
        return Attrs([(sn, replace.get(sn, sv)) for sn, sv in self
                      if sn not in remove] +
                     [(an, av) for an, av in attrs
                      if an not in self and an not in remove])

    def __repr__(self):
        if not self:
            return 'Attrs()'
        return 'Attrs([%s])' % ', '.join([repr(item) for item in self])

    def __sub__(self, names):
        """Return a new instance with all attributes with a name in `names` are
        removed.
        
        :param names: the names of the attributes to remove
        :return: a new instance with the attribute removed
        :rtype: `Attrs`
        """
        if isinstance(names, basestring):
            names = (names,)
        return Attrs([(name, val) for name, val in self if name not in names])

    def get(self, name, default=None):
        """Return the value of the attribute with the specified name, or the
        value of the `default` parameter if no such attribute is found.
        
        :param name: the name of the attribute
        :param default: the value to return when the attribute does not exist
        :return: the attribute value, or the `default` value if that attribute
                 does not exist
        :rtype: `object`
        """
        for attr, value in self:
            if attr == name:
                return value
        return default

    def totuple(self):
        """Return the attributes as a markup event.
        
        The returned event is a `TEXT` event, the data is the value of all
        attributes joined together.
        
        >>> Attrs([('href', '#'), ('title', 'Foo')]).totuple()
        ('TEXT', '#Foo', (None, -1, -1))
        
        :return: a `TEXT` event
        :rtype: `tuple`
        """
        return TEXT, ''.join([x[1] for x in self]), (None, -1, -1) class Namespace(object):
    """Utility class creating and testing elements with a namespace.
    
    Internally, namespace URIs are encoded in the `QName` of any element or
    attribute, the namespace URI being enclosed in curly braces. This class
    helps create and test these strings.
    
    A `Namespace` object is instantiated with the namespace URI.
    
    >>> html = Namespace('http://www.w3.org/1999/xhtml')
    >>> html
    Namespace('http://www.w3.org/1999/xhtml')
    >>> html.uri
    u'http://www.w3.org/1999/xhtml'
    
    The `Namespace` object can than be used to generate `QName` objects with
    that namespace:
    
    >>> html.body
    QName('http://www.w3.org/1999/xhtml}body')
    >>> html.body.localname
    u'body'
    >>> html.body.namespace
    u'http://www.w3.org/1999/xhtml'
    
    The same works using item access notation, which is useful for element or
    attribute names that are not valid Python identifiers:
    
    >>> html['body']
    QName('http://www.w3.org/1999/xhtml}body')
    
    A `Namespace` object can also be used to test whether a specific `QName`
    belongs to that namespace using the ``in`` operator:
    
    >>> qname = html.body
    >>> qname in html
    True
    >>> qname in Namespace('http://www.w3.org/2002/06/xhtml2')
    False
    """
    def __new__(cls, uri):
        if type(uri) is cls:
            return uri
        return object.__new__(cls)

    def __getnewargs__(self):
        return (self.uri,)

    def __getstate__(self):
        return self.uri

    def __setstate__(self, uri):
        self.uri = uri

    def __init__(self, uri):
        self.uri = unicode(uri)

    def __contains__(self, qname):
        return qname.namespace == self.uri

    def __ne__(self, other):
        return not self == other

    def __eq__(self, other):
        if isinstance(other, Namespace):
            return self.uri == other.uri
        return self.uri == other

    def __getitem__(self, name):
        return QName(self.uri + '}' + name)
    __getattr__ = __getitem__

    def __hash__(self):
        return hash(self.uri)

    def __repr__(self):
        return '%s(%s)' % (type(self).__name__, stringrepr(self.uri))

    def __str__(self):
        return self.uri.encode('utf-8')

    def __unicode__(self):
        return self.uri class QName(unicode):
    """A qualified element or attribute name.
    
    The unicode value of instances of this class contains the qualified name of
    the element or attribute, in the form ``{namespace-uri}local-name``. The
    namespace URI can be obtained through the additional `namespace` attribute,
    while the local name can be accessed through the `localname` attribute.
    
    >>> qname = QName('foo')
    >>> qname
    QName('foo')
    >>> qname.localname
    u'foo'
    >>> qname.namespace
    
    >>> qname = QName('http://www.w3.org/1999/xhtml}body')
    >>> qname
    QName('http://www.w3.org/1999/xhtml}body')
    >>> qname.localname
    u'body'
    >>> qname.namespace
    u'http://www.w3.org/1999/xhtml'
    """
    __slots__ = ['namespace', 'localname']

    def __new__(cls, qname):
        """Create the `QName` instance.
        
        :param qname: the qualified name as a string of the form
                      ``{namespace-uri}local-name``, where the leading curly
                      brace is optional
        """
        if type(qname) is cls:
            return qname

        parts = qname.lstrip('{').split('}', 1)
        if len(parts) > 1:
            self = unicode.__new__(cls, '{%s' % qname)
            self.namespace, self.localname = map(unicode, parts)
        else:
            self = unicode.__new__(cls, qname)
            self.namespace, self.localname = None, unicode(qname)
        return self

    def __getnewargs__(self):
        return (self.lstrip('{'),)

    def __repr__(self):
        return '%s(%s)' % (type(self).__name__, stringrepr(self.lstrip('{'))) START = StreamEventKind('START') #: a start tag END = StreamEventKind('END') #: an end tag TEXT = StreamEventKind('TEXT') #: literal text XML_NAMESPACE = Namespace('http://www.w3.org/XML/1998/namespace') def _ensure(stream):
    """Ensure that every item on the stream is actually a markup event."""
    stream = iter(stream)
    event = stream.next()

    # Check whether the iterable is a real markup event stream by examining the
    # first item it yields; if it's not we'll need to do some conversion
    if type(event) is not tuple or len(event) != 3:
        for event in chain([event], stream):
            if hasattr(event, 'totuple'):
                event = event.totuple()
            else:
                event = TEXT, unicode(event), (None, -1, -1)
            yield event
        return

    # This looks like a markup event stream, so we'll just pass it through
    # unchanged
    yield event
    for event in stream:
        yield event class StreamEventKind(str):
    """A kind of event on a markup stream."""
    __slots__ = []
    _instances = {}

    def __new__(cls, val):
        return cls._instances.setdefault(val, str.__new__(cls, val))     class _FakeMapping(object):
class Code(object):
class Expression(Code):
class Suite(Code):
class UndefinedError(TemplateRuntimeError):
class Undefined(object):
class LookupBase(object):
class LenientLookup(LookupBase):
class StrictLookup(LookupBase):
class TemplateASTTransformer(ASTTransformer):
class ExpressionASTTransformer(TemplateASTTransformer):
def _star_import_patch(mapping, modname):
    def __init__(self, source, filename=None, lineno=-1, lookup='strict',
                 xform=None):
    def __getstate__(self):
    def __setstate__(self, state):
    def __eq__(self, other):
    def __hash__(self):
    def __ne__(self, other):
    def __repr__(self):
    def evaluate(self, data):
    def execute(self, data):
    def __init__(self, name, owner=UNDEFINED):
    def __init__(self, name, owner=UNDEFINED):
    def __iter__(self):
    def __nonzero__(self):
    def __repr__(self):
    def __str__(self):
    def _die(self, *args, **kwargs):
    def globals(cls, data):
    def lookup_name(cls, data, name):
    def lookup_attr(cls, obj, key):
    def lookup_item(cls, obj, key):
    def undefined(cls, key, owner=UNDEFINED):
    def undefined(cls, key, owner=UNDEFINED):
    def undefined(cls, key, owner=UNDEFINED):
def _parse(source, mode='eval'):
def _compile(node, source=None, mode='eval', filename=None, lineno=-1,
             xform=None):
def _new(class_, *args, **kwargs):
    def __init__(self):
    def _extract_names(self, node):
        def _process(node):
    def visit_Str(self, node):
    def visit_ClassDef(self, node):
    def visit_Import(self, node):
    def visit_ImportFrom(self, node):
    def visit_FunctionDef(self, node):
    def visit_GeneratorExp(self, node):
    def visit_Lambda(self, node):
    def visit_Name(self, node):
    def visit_Attribute(self, node):
    def visit_Subscript(self, node):
UNDEFINED = object()
BUILTINS = __builtin__.__dict__.copy()
CONSTANTS = frozenset(['False', 'True', 'None', 'NotImplemented', 'Ellipsis']) class DirectiveFactory(object):
    """Base for classes that provide a set of template directives.
    
    :since: version 0.6
    """
    __metaclass__ = DirectiveFactoryMeta

    directives = []
    """A list of ``(name, cls)`` tuples that define the set of directives
    provided by this factory.
    """

    def get_directive(self, name):
        """Return the directive class for the given name.
        
        :param name: the directive name as used in the template
        :return: the directive class
        :see: `Directive`
        """
        return self._dir_by_name.get(name)

    def get_directive_index(self, dir_cls):
        """Return a key for the given directive class that should be used to
        sort it among other directives on the same `SUB` event.
        
        The default implementation simply returns the index of the directive in
        the `directives` list.
        
        :param dir_cls: the directive class
        :return: the sort key
        """
        if dir_cls in self._dir_order:
            return self._dir_order.index(dir_cls)
        return len(self._dir_order) EXPR = StreamEventKind('EXPR') SUB = StreamEventKind('SUB') def _apply_directives(stream, directives, ctxt, vars):
    """Apply the given directives to the stream.
    
    :param stream: the stream the directives should be applied to
    :param directives: the list of directives to apply
    :param ctxt: the `Context`
    :param vars: additional variables that should be available when Python
                 code is executed
    :return: the stream with the given directives applied
    """
    if directives:
        stream = directives[0](iter(stream), directives[1:], ctxt, **vars)
    return stream class Directive(object):
    """Abstract base class for template directives.
    
    A directive is basically a callable that takes three positional arguments:
    ``ctxt`` is the template data context, ``stream`` is an iterable over the
    events that the directive applies to, and ``directives`` is is a list of
    other directives on the same stream that need to be applied.
    
    Directives can be "anonymous" or "registered". Registered directives can be
    applied by the template author using an XML attribute with the
    corresponding name in the template. Such directives should be subclasses of
    this base class that can  be instantiated with the value of the directive
    attribute as parameter.
    
    Anonymous directives are simply functions conforming to the protocol
    described above, and can only be applied programmatically (for example by
    template filters).
    """
    __metaclass__ = DirectiveMeta
    __slots__ = ['expr']

    def __init__(self, value, template=None, namespaces=None, lineno=-1,
                 offset=-1):
        self.expr = self._parse_expr(value, template, lineno, offset)

    @classmethod
    def attach(cls, template, stream, value, namespaces, pos):
        """Called after the template stream has been completely parsed.
        
        :param template: the `Template` object
        :param stream: the event stream associated with the directive
        :param value: the argument value for the directive; if the directive was
                      specified as an element, this will be an `Attrs` instance
                      with all specified attributes, otherwise it will be a
                      `unicode` object with just the attribute value
        :param namespaces: a mapping of namespace URIs to prefixes
        :param pos: a ``(filename, lineno, offset)`` tuple describing the
                    location where the directive was found in the source
        
        This class method should return a ``(directive, stream)`` tuple. If
        ``directive`` is not ``None``, it should be an instance of the `Directive`
        class, and gets added to the list of directives applied to the substream
        at runtime. `stream` is an event stream that replaces the original
        stream associated with the directive.
        """
        return cls(value, template, namespaces, *pos[1:]), stream

    def __call__(self, stream, directives, ctxt, **vars):
        """Apply the directive to the given stream.
        
        :param stream: the event stream
        :param directives: a list of the remaining directives that should
                           process the stream
        :param ctxt: the context data
        :param vars: additional variables that should be made available when
                     Python code is executed
        """
        raise NotImplementedError

    def __repr__(self):
        expr = ''
        if getattr(self, 'expr', None) is not None:
            expr = ' "%s"' % self.expr.source
        return '<%s%s>' % (type(self).__name__, expr)

    @classmethod
    def _parse_expr(cls, expr, template, lineno=-1, offset=-1):
        """Parses the given expression, raising a useful error message when a
        syntax error is encountered.
        """
        try:
            return expr and Expression(expr, template.filepath, lineno,
                                       lookup=template.lookup) or None
        except SyntaxError, err:
            err.msg += ' in expression "%s" of "%s" directive' % (expr,
                                                                  cls.tagname)
            raise TemplateSyntaxError(err, template.filepath, lineno,
                                      offset + (err.offset or 0)) class StripDirective(Directive):
    """Implementation of the ``py:strip`` template directive.
    
    When the value of the ``py:strip`` attribute evaluates to ``True``, the
    element is stripped from the output
    
    >>> from genshi.template import MarkupTemplate
    >>> tmpl = MarkupTemplate('''<div xmlns:py="http://genshi.edgewall.org/">
    ...   <div py:strip="True"><b>foo</b></div>
    ... </div>''')
    >>> print(tmpl.generate())
    <div>
      <b>foo</b>
    </div>
    
    Leaving the attribute value empty is equivalent to a truth value.
    
    This directive is particulary interesting for named template functions or
    match templates that do not generate a top-level element:
    
    >>> tmpl = MarkupTemplate('''<div xmlns:py="http://genshi.edgewall.org/">
    ...   <div py:def="echo(what)" py:strip="">
    ...     <b>${what}</b>
    ...   </div>
    ...   ${echo('foo')}
    ... </div>''')
    >>> print(tmpl.generate())
    <div>
        <b>foo</b>
    </div>
    """
    __slots__ = []

    def __call__(self, stream, directives, ctxt, **vars):
        def _generate():
            if not self.expr or _eval_expr(self.expr, ctxt, vars):
                stream.next() # skip start tag
                previous = stream.next()
                for event in stream:
                    yield previous
                    previous = event
            else:
                for event in stream:
                    yield event
        return _apply_directives(_generate(), directives, ctxt, vars) class MarkupTemplate(Template):
    DIRECTIVE_NAMESPACE = 'http://genshi.edgewall.org/'
    XINCLUDE_NAMESPACE = 'http://www.w3.org/2001/XInclude'
    def __init__(self, source, filepath=None, filename=None, loader=None,
                 encoding=None, lookup='strict', allow_exec=True):
    def _init_filters(self):
    def _parse(self, source, encoding):
    def _extract_directives(self, stream, namespace, factory):
    def _extract_includes(self, stream):
    def _interpolate_attrs(self, stream):
    def _prepare(self, stream):
    def add_directives(self, namespace, factory):
    def _match(self, stream, ctxt, start=0, end=None, **vars):
        def _strip(stream, append=tail.append):
                    def select(path):
    from genshi.util import any
from gettext import NullTranslations
from types import FunctionType
from genshi.core import Attrs, Namespace, QName, START, END, TEXT, \
                        XML_NAMESPACE, _ensure, StreamEventKind
from genshi.template.eval import _ast
from genshi.template.base import DirectiveFactory, EXPR, SUB, _apply_directives
from genshi.template.directives import Directive, StripDirective
from genshi.template.markup import MarkupTemplate, EXEC
import os
import re
                        )
                    if newval != value:
                        value = newval
                        changed = True
                    new_attrs.append((name, value))
                if changed:
                    attrs = Attrs(new_attrs)

                yield kind, (tag, attrs), pos

            elif translate_text and kind is TEXT:
                text = data.strip()
                if text:
                    data = data.replace(text, unicode(gettext(text)))
                yield kind, data, pos

            elif kind is SUB:
                directives, substream = data
                current_domain = None
                for idx, directive in enumerate(directives):
                    # Organize directives to make everything work
                    # FIXME: There's got to be a better way to do this!
                    if isinstance(directive, DomainDirective):
                        # Grab current domain and update context
                        current_domain = directive.domain
                        ctxt.push({'_i18n.domain': current_domain})
                        # Put domain directive as the first one in order to
                        # update context before any other directives evaluation
                        directives.insert(0, directives.pop(idx))

                # If this is an i18n directive, no need to translate text
                # nodes here
                is_i18n_directive = any([
                    isinstance(d, ExtractableI18NDirective)
                    for d in directives
                ])
                substream = list(self(substream, ctxt,
                                      translate_text=not is_i18n_directive,
                                      translate_attrs=translate_attrs))
                yield kind, (directives, substream), pos

                if current_domain:
                    ctxt.pop()
            else:
                yield kind, data, pos

    def extract(self, stream, gettext_functions=GETTEXT_FUNCTIONS,
                search_text=True, comment_stack=None):
        """Extract localizable strings from the given template stream.
        
        For every string found, this function yields a ``(lineno, function,
        message, comments)`` tuple, where:
        
        * ``lineno`` is the number of the line on which the string was found,
        * ``function`` is the name of the ``gettext`` function used (if the
          string was extracted from embedded Python code), and
        *  ``message`` is the string itself (a ``unicode`` object, or a tuple
           of ``unicode`` objects for functions with multiple string
           arguments).
        *  ``comments`` is a list of comments related to the message, extracted
           from ``i18n:comment`` attributes found in the markup
        
        >>> tmpl = MarkupTemplate('''<html xmlns:py="http://genshi.edgewall.org/">
        ...   <head>
        ...     <title>Example</title>
        ...   </head>
        ...   <body>
        ...     <h1>Example</h1>
        ...     <p>${_("Hello, %(name)s") % dict(name=username)}</p>
        ...     <p>${ngettext("You have %d item", "You have %d items", num)}</p>
        ...   </body>
        ... </html>''', filename='example.html')
        >>> for line, func, msg, comments in Translator().extract(tmpl.stream):
        ...    print('%d, %r, %r' % (line, func, msg))
        3, None, u'Example'
        6, None, u'Example'
        7, '_', u'Hello, %(name)s'
        8, 'ngettext', (u'You have %d item', u'You have %d items', None)
        
        :param stream: the event stream to extract strings from; can be a
                       regular stream or a template stream
        :param gettext_functions: a sequence of function names that should be
                                  treated as gettext-style localization
                                  functions
        :param search_text: whether the content of text nodes should be
                            extracted (used internally)
        
        :note: Changed in 0.4.1: For a function with multiple string arguments
               (such as ``ngettext``), a single item with a tuple of strings is
               yielded, instead an item for each string argument.
        :note: Changed in 0.6: The returned tuples now include a fourth
               element, which is a list of comments for the translator.
        """
        if not self.extract_text:
            search_text = False
        if comment_stack is None:
            comment_stack = []
        skip = 0

        xml_lang = XML_NAMESPACE['lang']

        for kind, data, pos in stream:
            if skip:
                if kind is START:
                    skip += 1
                if kind is END:
                    skip -= 1

            if kind is START and not skip:
                tag, attrs = data
                if tag in self.ignore_tags or \
                        isinstance(attrs.get(xml_lang), basestring):
                    skip += 1
                    continue

                for message in self._extract_attrs((kind, data, pos),
                                                   gettext_functions,
                                                   search_text=search_text):
                    yield message


            elif not skip and search_text and kind is TEXT: