Пример #1
0
    def cofeed(self, obj, prefixes=None):
        """
        Feed a structure to the writer, including a cursor.  The structure is
        interpreted as XML and serialized.  The initially fed structure becomes
        the outer envelope of the serialized XML, and then the operation is
        suspended (this method engenders a coroutine).  The user can then send additional
        substructures to the coroutine, which get serialized at the point of the cursor,
        until the user closes the coroutine, at which point the serialization is
        completed.
        
        obj - XML node proxy structure (or iterator thereof), such as
        amara.writers.struct.ROOT (proxy for a root (entity) node),
        amara.writers.struct.E (proxy for an element), or
        amara.writers.struct.E_CURSOR (proxy for a cursor element, whose children
        are then later provided by sending proxy nodes to the coroutine).
        See documentation for other proxy node classes
        """
        #This method is largely a dupe of feed, but rather than calling self.feed to
        #recursively deal with compound structures, it sets up a child coroutine
        #and forwards values sent by the parent.  There is a lot of inelegant
        #duplication because we often can't tidy things up with functions without
        #Breaking the character of cofeed as a coroutine
        #this is one are where Python could very much use cpp-style macros
        #FIXME.  There is some inelegant duplication that might well be refatcored
        #away, even without the benefit of cpp-style macros
        prefixes = prefixes or {}
        if isinstance(obj, ROOT):
            self.printer.start_document()
            for subobj in obj.content:
                try:
                    buf = self.cofeed(subobj, prefixes=None)
                    try:
                        while True:
                            val = (yield)
                            buf.send(val)
                    except GeneratorExit:
                        buf.close()
                except StopIteration:
                    pass
                #self.feed(subobj)
            self.printer.end_document()
            return
        if isinstance(obj, NS):
            return
        if isinstance(obj, RAW):
            doc = amara.parse(obj.content)
            from amara.writers._treevisitor import visitor
            v = visitor(printer=self.printer)
            for child in doc.xml_children:
                v.visit(child)
            return
        if isinstance(obj, E_CURSOR):
            new_prefixes = []
            prefix, local = splitqname(obj.qname)
            prefix = prefix or u''
            if obj.ns == UNSPECIFIED_NAMESPACE:
                obj.ns = prefixes.get(prefix, u'')
            elif prefix not in prefixes or prefixes[prefix] != obj.ns:
                new_prefixes.append((prefix, obj.ns or u''))
            attrs = [a for a in obj.attributes.itervalues()
                     ] if obj.attributes else ()
            if new_prefixes:
                prefixes = prefixes.copy()
                prefixes.update(dict(new_prefixes))
            self.printer.start_element(obj.ns, obj.qname, new_prefixes, attrs)

            try:
                buf = obj.do(self)
                while True:
                    val = (yield)
                    buf.send(val)
            except GeneratorExit:
                buf.close()

            self.printer.end_element(obj.ns, obj.qname)
            return
        if isinstance(obj, E):
            #First attempt used tee.  Seems we ran into the warning at
            #http://www.python.org/doc/2.4.3/whatsnew/node13.html
            #"Note that tee() has to keep copies of the values returned by the iterator;
            #in the worst case, it may need to keep all of them.
            #This should therefore be used carefully if the leading iterator can run
            #far ahead of the trailing iterator in a long stream of inputs.
            #If the separation is large, then you might as well use list() instead.
            #When the iterators track closely with one another, tee()" is ideal. Possible
            #applications include bookmarking, windowing, or lookahead iterators.
            #(Contributed by Raymond Hettinger.)"
            #obj.namespaces = {}
            new_prefixes = []
            lead = None
            content = iter(obj.content)
            for subobj in content:
                if isinstance(subobj, NS):
                    new_prefixes.append((subobj.prefix, subobj.namespace))
                else:
                    lead = subobj
                    break

            prefix, local = splitqname(obj.qname)
            prefix = prefix or u''
            if obj.ns == UNSPECIFIED_NAMESPACE:
                obj.ns = prefixes.get(prefix, u'')
            elif prefix not in prefixes or prefixes[prefix] != obj.ns:
                new_prefixes.append((prefix, obj.ns or u''))
            attrs = [a for a in obj.attributes.itervalues()
                     ] if obj.attributes else ()
            if new_prefixes:
                prefixes = prefixes.copy()
                prefixes.update(dict(new_prefixes))
            self.printer.start_element(obj.ns, obj.qname, new_prefixes, attrs)
            if lead:
                if isinstance(lead, E_CURSOR) or isinstance(lead, E):
                    try:
                        buf = self.cofeed(lead, prefixes=None)
                        try:
                            while True:
                                val = (yield)
                                buf.send(val)
                        except GeneratorExit:
                            buf.close()
                    except StopIteration:
                        pass
                else:
                    self.feed(lead, prefixes)
                for subobj in content:
                    if isinstance(subobj, E_CURSOR) or isinstance(subobj, E):
                        try:
                            buf = self.cofeed(subobj, prefixes=None)
                            try:
                                while True:
                                    val = (yield)
                                    buf.send(val)
                            except GeneratorExit:
                                buf.close()
                        except StopIteration:
                            pass
                    else:
                        self.feed(subobj, prefixes)
            self.printer.end_element(obj.ns, obj.qname)
            return

        if isinstance(obj, basestring):
            self.printer.text(U(obj))
            return
        if isinstance(obj, tree.element):
            #Be smart about bindery nodes
            self.printer.text(unicode(obj))
            return
        try:
            obj = iter(obj)
        except TypeError, e:
            if callable(obj):
                self.feed(obj(), prefixes)
            else:
                #Just try to make it text, i.e. punt
                self.feed(unicode(obj), prefixes)
Пример #2
0
    def cofeed(self, obj, prefixes=None):
        """
        Feed a structure to the writer, including a cursor.  The structure is
        interpreted as XML and serialized.  The initially fed structure becomes
        the outer envelope of the serialized XML, and then the operation is
        suspended (this method engenders a coroutine).  The user can then send additional
        substructures to the coroutine, which get serialized at the point of the cursor,
        until the user closes the coroutine, at which point the serialization is
        completed.
        
        obj - XML node proxy structure (or iterator thereof), such as
        amara.writers.struct.ROOT (proxy for a root (entity) node),
        amara.writers.struct.E (proxy for an element), or
        amara.writers.struct.E_CURSOR (proxy for a cursor element, whose children
        are then later provided by sending proxy nodes to the coroutine).
        See documentation for other proxy node classes
        """
        #This method is largely a dupe of feed, but rather than calling self.feed to
        #recursively deal with compound structures, it sets up a child coroutine
        #and forwards values sent by the parent.  There is a lot of inelegant
        #duplication because we often can't tidy things up with functions without
        #Breaking the character of cofeed as a coroutine
        #this is one are where Python could very much use cpp-style macros
        #FIXME.  There is some inelegant duplication that might well be refatcored
        #away, even without the benefit of cpp-style macros
        prefixes = prefixes or {}
        if isinstance(obj, ROOT):
            self.printer.start_document()
            for subobj in obj.content:
                try:
                    buf = self.cofeed(subobj, prefixes=None)
                    try:
                        while True:
                            val = (yield)
                            buf.send(val)
                    except GeneratorExit:
                        buf.close()
                except StopIteration:
                    pass
                #self.feed(subobj)
            self.printer.end_document()
            return
        if isinstance(obj, NS):
            return
        if isinstance(obj, RAW):
            doc = amara.parse(obj.content)
            from amara.writers._treevisitor import visitor
            v = visitor(printer=self.printer)
            for child in doc.xml_children:
                v.visit(child)
            return
        if isinstance(obj, E_CURSOR):
            new_prefixes = []
            prefix, local = splitqname(obj.qname)
            prefix = prefix or u''
            if obj.ns == UNSPECIFIED_NAMESPACE:
                obj.ns = prefixes.get(prefix, u'')
            elif prefix not in prefixes or prefixes[prefix] != obj.ns:
                new_prefixes.append((prefix, obj.ns or u''))
            attrs = [ a for a in obj.attributes.itervalues() ] if obj.attributes else ()
            if new_prefixes:
                prefixes = prefixes.copy()
                prefixes.update(dict(new_prefixes))
            self.printer.start_element(obj.ns, obj.qname, new_prefixes, attrs)

            try:
                buf = obj.do(self)
                while True:
                    val = (yield)
                    buf.send(val)
            except GeneratorExit:
                buf.close()

            self.printer.end_element(obj.ns, obj.qname)
            return
        if isinstance(obj, E):
            #First attempt used tee.  Seems we ran into the warning at
            #http://www.python.org/doc/2.4.3/whatsnew/node13.html
            #"Note that tee() has to keep copies of the values returned by the iterator;
            #in the worst case, it may need to keep all of them.
            #This should therefore be used carefully if the leading iterator can run
            #far ahead of the trailing iterator in a long stream of inputs.
            #If the separation is large, then you might as well use list() instead.
            #When the iterators track closely with one another, tee()" is ideal. Possible
            #applications include bookmarking, windowing, or lookahead iterators.
            #(Contributed by Raymond Hettinger.)"
            #obj.namespaces = {}
            new_prefixes = []
            lead = None
            content = iter(obj.content)
            for subobj in content:
                if isinstance(subobj, NS):
                    new_prefixes.append((subobj.prefix, subobj.namespace))
                else:
                    lead = subobj
                    break

            prefix, local = splitqname(obj.qname)
            prefix = prefix or u''
            if obj.ns == UNSPECIFIED_NAMESPACE:
                obj.ns = prefixes.get(prefix, u'')
            elif prefix not in prefixes or prefixes[prefix] != obj.ns:
                new_prefixes.append((prefix, obj.ns or u''))
            attrs = [ a for a in obj.attributes.itervalues() ] if obj.attributes else ()
            if new_prefixes:
                prefixes = prefixes.copy()
                prefixes.update(dict(new_prefixes))
            self.printer.start_element(obj.ns, obj.qname, new_prefixes, attrs)
            if lead:
                if isinstance(lead, E_CURSOR) or isinstance(lead, E):
                    try:
                        buf = self.cofeed(lead, prefixes=None)
                        try:
                            while True:
                                val = (yield)
                                buf.send(val)
                        except GeneratorExit:
                            buf.close()
                    except StopIteration:
                        pass
                else:
                    self.feed(lead, prefixes)
                for subobj in content:
                    if isinstance(subobj, E_CURSOR) or isinstance(subobj, E):
                        try:
                            buf = self.cofeed(subobj, prefixes=None)
                            try:
                                while True:
                                    val = (yield)
                                    buf.send(val)
                            except GeneratorExit:
                                buf.close()
                        except StopIteration:
                            pass
                    else:
                        self.feed(subobj, prefixes)
            self.printer.end_element(obj.ns, obj.qname)
            return

        if isinstance(obj, basestring):
            self.printer.text(U(obj))
            return
        if isinstance(obj, tree.element):
            #Be smart about bindery nodes
            self.printer.text(unicode(obj))
            return
        try:
            obj = iter(obj)
        except TypeError, e:
            if callable(obj):
                self.feed(obj(), prefixes)
            else:
                #Just try to make it text, i.e. punt
                self.feed(unicode(obj), prefixes)
Пример #3
0
    def feed(self, obj, prefixes=None):
        """
        Feed a structure to the writer.  The structure is interpreted as XML and
        serialized.
        
        obj - XML node proxy structure (or iterator thereof), such as
        amara.writers.struct.ROOT (proxy for a root (entity) node) or
        amara.writers.struct.E (proxy for an element).

        See documentation for other proxy node classes
        """
        prefixes = prefixes or {}
        if isinstance(obj, ROOT):
            self.printer.start_document()
            for subobj in obj.content:
                self.feed(subobj)
            self.printer.end_document()
            return
        if isinstance(obj, NS):
            return
        if isinstance(obj, RAW):
            #parse_frag returns an entity
            ent = parse_fragment(inputsource.text(obj.content))
            from amara.writers._treevisitor import visitor
            v = visitor(printer=self.printer)
            for child in ent.xml_children:
                v.visit(child)
            return
        if isinstance(obj, E):
            #First attempt used tee.  Seems we ran into the warning at
            #http://www.python.org/doc/2.4.3/whatsnew/node13.html
            #"Note that tee() has to keep copies of the values returned by the iterator;
            #in the worst case, it may need to keep all of them.
            #This should therefore be used carefully if the leading iterator can run
            #far ahead of the trailing iterator in a long stream of inputs.
            #If the separation is large, then you might as well use list() instead.
            #When the iterators track closely with one another, tee()" is ideal. Possible
            #applications include bookmarking, windowing, or lookahead iterators.
            #(Contributed by Raymond Hettinger.)"
            #obj.namespaces = {}
            new_prefixes = []
            lead = None
            content = iter(obj.content)
            for subobj in content:
                if isinstance(subobj, NS):
                    new_prefixes.append((subobj.prefix, subobj.namespace))
                else:
                    lead = subobj
                    break

            prefix, local = splitqname(obj.qname)
            prefix = prefix or u''
            if obj.ns == UNSPECIFIED_NAMESPACE:
                obj.ns = prefixes.get(prefix, u'')
            elif prefix not in prefixes or prefixes[prefix] != obj.ns:
                new_prefixes.append((prefix, obj.ns or u''))
            attrs = [a for a in obj.attributes.itervalues()
                     ] if obj.attributes else ()
            if new_prefixes:
                prefixes = prefixes.copy()
                prefixes.update(dict(new_prefixes))
            self.printer.start_element(obj.ns, obj.qname, new_prefixes, attrs)
            if lead:
                self.feed(lead, prefixes)
                for subobj in content:
                    self.feed(subobj, prefixes)
            self.printer.end_element(obj.ns, obj.qname)
            return

        if isinstance(obj, basestring):
            self.printer.text(U(obj))
            return
        if isinstance(obj, tree.element):
            #Be smart about bindery nodes
            self.printer.text(unicode(obj))
            return
        try:
            obj = iter(obj)
        except TypeError, e:
            if callable(obj):
                self.feed(obj(), prefixes)
            else:
                #Just try to make it text, i.e. punt
                self.feed(unicode(obj), prefixes)
Пример #4
0
    def feed(self, obj, prefixes=None):
        """
        Feed a structure to the writer.  The structure is interpreted as XML and
        serialized.
        
        obj - XML node proxy structure (or iterator thereof), such as
        amara.writers.struct.ROOT (proxy for a root (entity) node) or
        amara.writers.struct.E (proxy for an element).

        See documentation for other proxy node classes
        """
        prefixes = prefixes or {}
        if isinstance(obj, ROOT):
            self.printer.start_document()
            for subobj in obj.content:
                self.feed(subobj)
            self.printer.end_document()
            return
        if isinstance(obj, NS):
            return
        if isinstance(obj, RAW):
            #parse_frag returns an entity
            ent = parse_fragment(inputsource.text(obj.content))
            from amara.writers._treevisitor import visitor
            v = visitor(printer=self.printer)
            for child in ent.xml_children:
                v.visit(child)
            return
        if isinstance(obj, E):
            #First attempt used tee.  Seems we ran into the warning at
            #http://www.python.org/doc/2.4.3/whatsnew/node13.html
            #"Note that tee() has to keep copies of the values returned by the iterator;
            #in the worst case, it may need to keep all of them.
            #This should therefore be used carefully if the leading iterator can run
            #far ahead of the trailing iterator in a long stream of inputs.
            #If the separation is large, then you might as well use list() instead.
            #When the iterators track closely with one another, tee()" is ideal. Possible
            #applications include bookmarking, windowing, or lookahead iterators.
            #(Contributed by Raymond Hettinger.)"
            #obj.namespaces = {}
            new_prefixes = []
            lead = None
            content = iter(obj.content)
            for subobj in content:
                if isinstance(subobj, NS):
                    new_prefixes.append((subobj.prefix, subobj.namespace))
                else:
                    lead = subobj
                    break

            prefix, local = splitqname(obj.qname)
            prefix = prefix or u''
            if obj.ns == UNSPECIFIED_NAMESPACE:
                obj.ns = prefixes.get(prefix, u'')
            elif prefix not in prefixes or prefixes[prefix] != obj.ns:
                new_prefixes.append((prefix, obj.ns or u''))
            attrs = [ a for a in obj.attributes.itervalues() ] if obj.attributes else ()
            if new_prefixes:
                prefixes = prefixes.copy()
                prefixes.update(dict(new_prefixes))
            self.printer.start_element(obj.ns, obj.qname, new_prefixes, attrs)
            if lead:
                self.feed(lead, prefixes)
                for subobj in content:
                    self.feed(subobj, prefixes)
            self.printer.end_element(obj.ns, obj.qname)
            return

        if isinstance(obj, basestring):
            self.printer.text(U(obj))
            return
        if isinstance(obj, tree.element):
            #Be smart about bindery nodes
            self.printer.text(unicode(obj))
            return
        try:
            obj = iter(obj)
        except TypeError, e:
            if callable(obj):
                self.feed(obj(), prefixes)
            else:
                #Just try to make it text, i.e. punt
                self.feed(unicode(obj), prefixes)