diff --git a/lib/pyulib/src/ulib/ext/xpath/__init__.py b/lib/pyulib/src/ulib/ext/xpath/__init__.py index 0741f64..71c2778 100644 --- a/lib/pyulib/src/ulib/ext/xpath/__init__.py +++ b/lib/pyulib/src/ulib/ext/xpath/__init__.py @@ -1,162 +1,2 @@ -from xpath.exceptions import * -import xpath.exceptions -import xpath.expr -import xpath.parser -import xpath.yappsrt - -__all__ = ['find', 'findnode', 'findvalue', 'XPathContext', 'XPath'] -__all__.extend((x for x in dir(xpath.exceptions) if not x.startswith('_'))) - -def api(f): - """Decorator for functions and methods that are part of the external - module API and that can throw XPathError exceptions. - - The call stack for these exceptions can be very large, and not very - interesting to the user. This decorator rethrows XPathErrors to - trim the stack. - - """ - def api_function(*args, **kwargs): - try: - return f(*args, **kwargs) - except XPathError, e: - raise e - api_function.__name__ = f.__name__ - api_function.__doc__ = f.__doc__ - return api_function - -class XPathContext(object): - def __init__(self, document=None, **kwargs): - self.default_namespace = None - self.namespaces = {} - self.variables = {} - - if document is not None: - if document.nodeType != document.DOCUMENT_NODE: - document = document.ownerDocument - if document.documentElement is not None: - attrs = document.documentElement.attributes - for attr in (attrs.item(i) for i in xrange(attrs.length)): - if attr.name == 'xmlns': - self.default_namespace = attr.value - elif attr.name.startswith('xmlns:'): - self.namespaces[attr.name[6:]] = attr.value - - self.update(**kwargs) - - def clone(self): - dup = XPathContext() - dup.default_namespace = self.default_namespace - dup.namespaces.update(self.namespaces) - dup.variables.update(self.variables) - return dup - - def update(self, default_namespace=None, namespaces=None, - variables=None, **kwargs): - if default_namespace is not None: - self.default_namespace = default_namespace - if namespaces is not None: - self.namespaces = namespaces - if variables is not None: - self.variables = variables - self.variables.update(kwargs) - - @api - def find(self, expr, node, **kwargs): - return xpath.find(expr, node, context=self, **kwargs) - - @api - def findnode(self, expr, node, **kwargs): - return xpath.findnode(expr, node, context=self, **kwargs) - - @api - def findvalue(self, expr, node, **kwargs): - return xpath.findvalue(expr, node, context=self, **kwargs) - - @api - def findvalues(self, expr, node, **kwargs): - return xpath.findvalues(expr, node, context=self, **kwargs) - -class XPath(): - _max_cache = 100 - _cache = {} - - def __init__(self, expr): - """Init docs. - """ - try: - parser = xpath.parser.XPath(xpath.parser.XPathScanner(str(expr))) - self.expr = parser.XPath() - except xpath.yappsrt.SyntaxError, e: - raise XPathParseError(str(expr), e.pos, e.msg) - - @classmethod - def get(cls, s): - if isinstance(s, cls): - return s - try: - return cls._cache[s] - except KeyError: - if len(cls._cache) > cls._max_cache: - cls._cache.clear() - expr = cls(s) - cls._cache[s] = expr - return expr - - @api - def find(self, node, context=None, **kwargs): - if context is None: - context = XPathContext(node, **kwargs) - elif kwargs: - context = context.clone() - context.update(**kwargs) - return self.expr.evaluate(node, 1, 1, context) - - @api - def findnode(self, node, context=None, **kwargs): - result = self.find(node, context, **kwargs) - if not xpath.expr.nodesetp(result): - raise XPathTypeError("expression is not a node-set") - if len(result) == 0: - return None - return result[0] - - @api - def findvalue(self, node, context=None, **kwargs): - result = self.find(node, context, **kwargs) - if xpath.expr.nodesetp(result): - if len(result) == 0: - return None - result = xpath.expr.string(result) - return result - - @api - def findvalues(self, node, context=None, **kwargs): - result = self.find(node, context, **kwargs) - if not xpath.expr.nodesetp(result): - raise XPathTypeError("expression is not a node-set") - return [xpath.expr.string_value(x) for x in result] - - def __repr__(self): - return '%s.%s(%s)' % (self.__class__.__module__, - self.__class__.__name__, - repr(str(self.expr))) - - def __str__(self): - return str(self.expr) - -@api -def find(expr, node, **kwargs): - return XPath.get(expr).find(node, **kwargs) - -@api -def findnode(expr, node, **kwargs): - return XPath.get(expr).findnode(node, **kwargs) - -@api -def findvalue(expr, node, **kwargs): - return XPath.get(expr).findvalue(node, **kwargs) - -@api -def findvalues(expr, node, **kwargs): - return XPath.get(expr).findvalues(node, **kwargs) +from main import __all__ +from main import * diff --git a/lib/pyulib/src/ulib/ext/xpath/expr.py b/lib/pyulib/src/ulib/ext/xpath/expr.py index 4199813..a6a1611 100644 --- a/lib/pyulib/src/ulib/ext/xpath/expr.py +++ b/lib/pyulib/src/ulib/ext/xpath/expr.py @@ -6,8 +6,7 @@ import re import xml.dom import weakref -from xpath.exceptions import * -import xpath +from exceptions import * # diff --git a/lib/pyulib/src/ulib/ext/xpath/main.py b/lib/pyulib/src/ulib/ext/xpath/main.py new file mode 100644 index 0000000..bd8d839 --- /dev/null +++ b/lib/pyulib/src/ulib/ext/xpath/main.py @@ -0,0 +1,169 @@ +from exceptions import * +import exceptions +import expr +import parser +import yappsrt + +class MODULE: pass +XPATH = MODULE() +XPATH.exceptions = exceptions +XPATH.expr = expr +XPATH.parser = parser +XPATH.yappsrt = yappsrt + +__all__ = ['find', 'findnode', 'findvalue', 'XPathContext', 'XPath'] +__all__.extend((x for x in dir(XPATH.exceptions) if not x.startswith('_'))) + +def api(f): + """Decorator for functions and methods that are part of the external + module API and that can throw XPathError exceptions. + + The call stack for these exceptions can be very large, and not very + interesting to the user. This decorator rethrows XPathErrors to + trim the stack. + + """ + def api_function(*args, **kwargs): + try: + return f(*args, **kwargs) + except XPathError, e: + raise e + api_function.__name__ = f.__name__ + api_function.__doc__ = f.__doc__ + return api_function + +class XPathContext(object): + def __init__(self, document=None, **kwargs): + self.default_namespace = None + self.namespaces = {} + self.variables = {} + + if document is not None: + if document.nodeType != document.DOCUMENT_NODE: + document = document.ownerDocument + if document.documentElement is not None: + attrs = document.documentElement.attributes + for attr in (attrs.item(i) for i in xrange(attrs.length)): + if attr.name == 'xmlns': + self.default_namespace = attr.value + elif attr.name.startswith('xmlns:'): + self.namespaces[attr.name[6:]] = attr.value + + self.update(**kwargs) + + def clone(self): + dup = XPathContext() + dup.default_namespace = self.default_namespace + dup.namespaces.update(self.namespaces) + dup.variables.update(self.variables) + return dup + + def update(self, default_namespace=None, namespaces=None, + variables=None, **kwargs): + if default_namespace is not None: + self.default_namespace = default_namespace + if namespaces is not None: + self.namespaces = namespaces + if variables is not None: + self.variables = variables + self.variables.update(kwargs) + + @api + def find(self, expr, node, **kwargs): + return XPATH.find(expr, node, context=self, **kwargs) + + @api + def findnode(self, expr, node, **kwargs): + return XPATH.findnode(expr, node, context=self, **kwargs) + + @api + def findvalue(self, expr, node, **kwargs): + return XPATH.findvalue(expr, node, context=self, **kwargs) + + @api + def findvalues(self, expr, node, **kwargs): + return XPATH.findvalues(expr, node, context=self, **kwargs) + +class XPath(): + _max_cache = 100 + _cache = {} + + def __init__(self, expr): + """Init docs. + """ + try: + parser = XPATH.parser.XPath(XPATH.parser.XPathScanner(str(expr))) + self.expr = parser.XPath() + except XPATH.yappsrt.SyntaxError, e: + raise XPathParseError(str(expr), e.pos, e.msg) + + @classmethod + def get(cls, s): + if isinstance(s, cls): + return s + try: + return cls._cache[s] + except KeyError: + if len(cls._cache) > cls._max_cache: + cls._cache.clear() + expr = cls(s) + cls._cache[s] = expr + return expr + + @api + def find(self, node, context=None, **kwargs): + if context is None: + context = XPathContext(node, **kwargs) + elif kwargs: + context = context.clone() + context.update(**kwargs) + return self.expr.evaluate(node, 1, 1, context) + + @api + def findnode(self, node, context=None, **kwargs): + result = self.find(node, context, **kwargs) + if not XPATH.expr.nodesetp(result): + raise XPathTypeError("expression is not a node-set") + if len(result) == 0: + return None + return result[0] + + @api + def findvalue(self, node, context=None, **kwargs): + result = self.find(node, context, **kwargs) + if XPATH.expr.nodesetp(result): + if len(result) == 0: + return None + result = XPATH.expr.string(result) + return result + + @api + def findvalues(self, node, context=None, **kwargs): + result = self.find(node, context, **kwargs) + if not XPATH.expr.nodesetp(result): + raise XPathTypeError("expression is not a node-set") + return [XPATH.expr.string_value(x) for x in result] + + def __repr__(self): + return '%s.%s(%s)' % (self.__class__.__module__, + self.__class__.__name__, + repr(str(self.expr))) + + def __str__(self): + return str(self.expr) + +@api +def find(expr, node, **kwargs): + return XPath.get(expr).find(node, **kwargs) + +@api +def findnode(expr, node, **kwargs): + return XPath.get(expr).findnode(node, **kwargs) + +@api +def findvalue(expr, node, **kwargs): + return XPath.get(expr).findvalue(node, **kwargs) + +@api +def findvalues(expr, node, **kwargs): + return XPath.get(expr).findvalues(node, **kwargs) diff --git a/lib/pyulib/src/ulib/ext/xpath/parser.py b/lib/pyulib/src/ulib/ext/xpath/parser.py index 504de78..2fd7b4f 100644 --- a/lib/pyulib/src/ulib/ext/xpath/parser.py +++ b/lib/pyulib/src/ulib/ext/xpath/parser.py @@ -1,5 +1,5 @@ -import xpath.expr as X -from xpath.yappsrt import * +import expr as X +from yappsrt import * from string import *