[Checkins] SVN: Sandbox/malthe/chameleon.core/ Do not use XPath during compilation if lxml is not available.
Malthe Borch
mborch at gmail.com
Mon Dec 1 10:30:52 EST 2008
Log message for revision 93488:
Do not use XPath during compilation if lxml is not available.
Changed:
U Sandbox/malthe/chameleon.core/CHANGES.txt
U Sandbox/malthe/chameleon.core/src/chameleon/core/etree.py
U Sandbox/malthe/chameleon.core/src/chameleon/core/translation.py
-=-
Modified: Sandbox/malthe/chameleon.core/CHANGES.txt
===================================================================
--- Sandbox/malthe/chameleon.core/CHANGES.txt 2008-12-01 12:44:06 UTC (rev 93487)
+++ Sandbox/malthe/chameleon.core/CHANGES.txt 2008-12-01 15:30:52 UTC (rev 93488)
@@ -4,6 +4,9 @@
HEAD
~~~~
+- Do not use XPath-expressions during compilation if lxml is not
+ available. [malthe]
+
- Ensure argument uniqueness for macro functions over the combined set of
scope and keyword arguments. [hannosch]
Modified: Sandbox/malthe/chameleon.core/src/chameleon/core/etree.py
===================================================================
--- Sandbox/malthe/chameleon.core/src/chameleon/core/etree.py 2008-12-01 12:44:06 UTC (rev 93487)
+++ Sandbox/malthe/chameleon.core/src/chameleon/core/etree.py 2008-12-01 15:30:52 UTC (rev 93488)
@@ -63,6 +63,17 @@
XMLSyntaxError = lxml.etree.XMLSyntaxError
+ def elements_with_attribute(element, ns, name, value=None):
+ if value is None:
+ expression = './/*[@prefix:%s] | .//prefix:*[@%s]' % (name, name)
+ else:
+ expression = './/*[@prefix:%s="%s"] | .//prefix:*[@%s="%s"]' % (
+ name, value, name, value)
+
+ return element.xpath(
+ expression,
+ namespaces={'prefix': ns})
+
class BufferIO(list):
write = list.append
@@ -229,13 +240,23 @@
except ImportError:
ET = import_elementtree()
- try:
- from pdis.xpath import XPath
- except ImportError:
- raise ImportError("PDIS-XPath is required when lxml is unavailable.")
+ XMLSyntaxError = SyntaxError
- XMLSyntaxError = ET.XMLSyntaxError
-
+ def elements_with_attribute(element, ns, name, value=None):
+ attributes = utils.get_attributes_from_namespace(
+ element, ns)
+
+ if value is not None:
+ if value in (
+ attributes.get(name), attributes.get('{%s}%s' % (ns, name))):
+ yield element
+ elif 'name' in attributes or '{%s}%s' % (ns, name) in attributes:
+ yield element
+
+ for child in element:
+ for match in elements_with_attribute(child, ns, name):
+ yield match
+
class ElementBase(object, ET._ElementInterface):
_parent = None
@@ -268,8 +289,8 @@
return ET.tostring(self)
def xpath(self, path, namespaces={}):
- xpath = XPath(path, namespace_mapping=namespaces)
- return xpath.evaluate(self)
+ raise NotImplementedError(
+ "No XPath-engine available.")
@property
def nsmap(self):
@@ -335,7 +356,7 @@
def handle_cdata_end(self):
self._target.end(utils.xhtml_attr('cdata'))
- def parse(body, element_mapping):
+ def parse(body, element_mapping, fallback=None):
def element_factory(tag, attrs=None, nsmap=None):
if attrs is None:
attrs = {}
@@ -348,7 +369,7 @@
ns_tag = None
namespace = element_mapping[ns]
- factory = namespace.get(ns_tag) or namespace.get(None) or ElementBase
+ factory = namespace.get(ns_tag) or namespace.get(None) or fallback
element = object.__new__(factory)
element.__init__(tag, attrs)
@@ -359,6 +380,7 @@
parser = XMLParser(target=target)
parser.entity = dict([(name, "&%s;" % name) for name in htmlentitydefs.entitydefs])
parser.feed(body)
+
root = parser.close()
return root, parser.doctype
Modified: Sandbox/malthe/chameleon.core/src/chameleon/core/translation.py
===================================================================
--- Sandbox/malthe/chameleon.core/src/chameleon/core/translation.py 2008-12-01 12:44:06 UTC (rev 93487)
+++ Sandbox/malthe/chameleon.core/src/chameleon/core/translation.py 2008-12-01 15:30:52 UTC (rev 93488)
@@ -372,9 +372,8 @@
# for each fill-slot element, create a new output stream
# and save value in a temporary variable
kwargs = []
- for element in self.element.xpath(
- './/*[@metal:fill-slot] | .//metal:*[@fill-slot]',
- namespaces={'metal': config.METAL_NS}):
+ for element in etree.elements_with_attribute(
+ self.element, config.METAL_NS, 'fill-slot'):
if element.node.fill_slot is None:
# XXX this should not be necessary, but the above
# xpath expression finds non-"metal:fill-slot"
@@ -691,10 +690,8 @@
# if macro is non-trivial, start compilation at the element
# where the macro is defined
if macro:
- elements = self.root.xpath(
- 'descendant-or-self::*[@metal:define-macro="%s"] |'
- 'descendant-or-self::metal:*[@define-macro="%s"]' % (macro, macro),
- namespaces={'metal': config.METAL_NS})
+ elements = tuple(etree.elements_with_attribute(
+ self.root, config.METAL_NS, 'define-macro', macro))
if not elements:
raise ValueError("Macro not found: %s." % macro)
@@ -855,8 +852,11 @@
return selectors
self._selectors = selectors = {}
- for element in self.tree.xpath(
- './/*[@meta:select]', namespaces={'meta': config.META_NS}):
+
+ elements = etree.elements_with_attribute(
+ self.tree, config.META_NS, 'select')
+
+ for element in elements:
name = element.attrib[utils.meta_attr('select')]
selectors[name] = element.xpath
More information about the Checkins
mailing list