2

I am trying to use pptx-python on Google App Engine (to create a powerpoint file). I don't need images, so I just commented out the dependencies on Pillow. That left me with something that almost works, except I have a version problem. The version of lxml in GAE is 2.3, and apparently the method SubElement was added in version 2.3.2.

The pptx code nicely wraps the lxml calls, so it looks like I could get around this by re-writing SubElement up at the application level. Unfortunately, I really don't have the first clue how to do that. And the lxml code appears to just be python wrappers around something written in C. So before I spend a couple days coming up to speed on lxml, I'm hoping that one of you geniuses can help me out.

This is the code in pptx/oxml/shared.py:

def SubElement(parent, nsptag_str, **extra):
    """
    Return an lxml element having *nsptag_str*, newly added as a direct child
    of *parent*. The new element is appended to the sequence of children, so
    this method is not suitable if the child element must be inserted at a
    different position in the sequence. The class of the returned element is
    the custom element class for its tag, if one is defined. Additional
    named parameters defined on lxml ``makeelement()`` are accepted, such as
    attrib=attr_dct and e.g. ``visible='1'``.
    """
    nsptag = NamespacePrefixedTag(nsptag_str)
    return objectify.SubElement(
        parent, nsptag.clark_name, nsmap=nsptag.nsmap, **extra
    )

Can someone tell me how to rewrite that function so that it doesn't rely on objectify.SubElement, and instead uses only methods available in lxml 2.3?

Joshua Smith
  • 3,689
  • 4
  • 32
  • 45

1 Answers1

2

The develop branch of python-pptx on GitHub has SubElement and actually all lxml.objectify removed in favor of lxml.etree library calls. Long story, but short version is objectify was way more trouble than it was worth when using it at scale.

So if you can install from the develop branch this problem might disappear. The develop branch is just as stable as master, they're both supported by about 1,000 unit tests at this point and 175 integration/acceptance tests.

That's where I'd start. Let us know how you go :)

Actually, now that I think of it, although I would prefer the approach above because it would mean you don't have to pin your python-pptx version, this might do the trick:

def SubElement(parent, nsptag_str, **extra):
    nsptag = NamespacePrefixedTag(nsptag_str)
    nsmap = nsptag.nsmap
    element = oxml_parser.makeelement(nsptag.clark_name, nsmap=nsmap, **extra)
    parent.append(element)
    return element
scanny
  • 26,423
  • 5
  • 54
  • 80
  • Added a possible rewrite of SubElement() in case that turns out to be more convenient. – scanny Jul 11 '14 at 20:25
  • I added that code, and changed a bunch of places that passed cleanup_namespaces=True to instead use lxml.etree.cleanupnamespaces: `` etree.cleanup_namespaces(txBody) objectify.deannotate(txBody)#, cleanup_namespaces=True)`` and that did the trick! – Joshua Smith Jul 14 '14 at 13:54