def getArgumentError(self): if not inspect.isfunction(self._func): # We can only check for argument errors with Python functions return None argcount = len(self._args) args, vararg, kwarg = inspect.getargs(self._func.func_code) defaults = self._func.func_defaults or () # Don't count the context parameter in argument count maxargs = len(args) - 1 minargs = maxargs - len(defaults) if argcount > maxargs and not vararg: if maxargs == 0: return RuntimeException(RuntimeException.ARGCOUNT_NONE, self._name, argcount) elif defaults: return RuntimeException(RuntimeException.ARGCOUNT_ATMOST, self._name, maxargs, argcount) else: return RuntimeException(RuntimeException.ARGCOUNT_EXACT, self._name, maxargs, argcount) elif argcount < minargs: if defaults or vararg: return RuntimeException(RuntimeException.ARGCOUNT_ATLEAST, self._name, minargs, argcount) else: return RuntimeException(RuntimeException.ARGCOUNT_EXACT, self._name, minargs, argcount) # Not an error with arg counts for this function, use current error return None
def Map(context, nodeset, string): if type(nodeset) != type([]): raise RuntimeException(RuntimeException.WRONG_ARGUMENTS, 'map', "expected node set argument") from Ft.Xml.XPath import parser from Ft.Lib import Set from rx import raccoon mapContext = context.clone() mapContext.size = len(nodeset) mapContext.position = 1 #note: exslt-dyn:map implies that parse exception should be caught and an empty nodeset returned expCache = raccoon.RequestProcessor.expCache xpath = StringValue(string) queryCache = getattr(context.node.ownerDocument, 'queryCache', None) def eval(l, node): mapContext.node = node mapContext.position += 1 mapContext.varBindings[(RXWIKI_XPATH_EXT_NS, 'current')] = node result = RxPath.evalXPath(xpath, mapContext, expCache, queryCache) if type(result) != type([]): if not isinstance(result, unicode): result = unicode(str(result), 'utf8') result = String2NodeSet(mapContext, result) l.extend(result) return l nodeset = reduce(eval, nodeset, []) return Set.Unique(nodeset)
def _onMetaData(kw, context, name, func, opname, value=None, authorize=True): from rx import raccoon (prefix, local) = SplitQName(name) if prefix: try: namespace = context.processorNss[prefix] except KeyError: raise RuntimeException(RuntimeException.UNDEFINED_PREFIX, prefix) else: namespace = None local = str(local) #function argument keyword dict can't be unicode if authorize and not kw['__server__'].authorizeMetadata( opname, namespace, local, value, kw): if value is None: value = '' raise raccoon.NotAuthorized('%s-metadata with %s:%s %s' % (opname, namespace, name, value)) dict = None kwdicts = kw['__server__'].kw2varsMap if not namespace: dict = kw elif kwdicts.get(namespace): dictname, attrib, filter = kwdicts[namespace] dict = kw.get(dictname) if dict and attrib: dict = getattr(dict, attrib, None) else: raise raccoon.UnusableNamespaceError('%s uses unusable namespace: %s' % (local, namespace)) #if dict is None: # log.debug('calling %s-metadata on an unavailable namespace %s' % (opname, namespace) ) return func(local, dict)
def Sum(context, nodeSet): """Function: <number> sum(<node-set>)""" if not isinstance(nodeSet, NodesetType): raise RuntimeException(RuntimeException.WRONG_ARGUMENTS, 'sum', _("expected node-set argument")) nns = map(Conversions.NumberValue, nodeSet) return reduce(lambda x, y: x + y, nns, 0)
def evaluate(self, context): """Returns a string""" (prefix, local) = self._key if prefix: try: expanded = (context.processorNss[prefix], local) except KeyError: raise RuntimeException(RuntimeException.UNDEFINED_PREFIX, prefix) else: expanded = self._key try: return context.varBindings[expanded] except KeyError: raise RuntimeException(RuntimeException.UNDEFINED_VARIABLE, expanded[0], expanded[1])
def getQuickKey(self, namespaces): try: namespace = namespaces[self._prefix] except KeyError: raise RuntimeException(RuntimeException.UNDEFINED_PREFIX, self._prefix) return (self.nodeType, (namespace, self._localName))
def evaluate(self, context): args = map(lambda arg, c=context: arg.evaluate(c), self._args) func = self._func if func is None: (prefix, local) = self._key if prefix: try: expanded = (context.processorNss[prefix], local) except: raise RuntimeException(RuntimeException.UNDEFINED_PREFIX, prefix) else: expanded = self._key func = context.functions.get(expanded, self.error) if not ('nocache' in func.__dict__ and func.nocache): self._func = func try: result = func(context, *args) except TypeError: exception = self.getArgumentError() if not exception: # use existing exception (empty raise keeps existing backtrace) raise raise exception #Expensive assert contributed by Adam Souzis. #No effect on Python running in optimized mode, #But would mean significant slowdown for developers, so disabled by default #assert not isinstance(result, list) or len(result) == len(Set.Unique(result)) return result
def match(self, context, node, principalType=Node.ELEMENT_NODE): if node.nodeType != principalType: return 0 try: return node.namespaceURI == context.processorNss[self._prefix] except KeyError: raise RuntimeException(RuntimeException.UNDEFINED_PREFIX, self._prefix)
def expandQName(self, qname): if not qname: return None prefix, local = self.splitQName(qname) if prefix: try: expanded = (self.processorNss[prefix], local) except KeyError: raise RuntimeException(RuntimeException.UNDEFINED_PREFIX, prefix) else: expanded = (EMPTY_NAMESPACE, local) return expanded
def Evaluate(expr, contextNode=None, context=None): """ Evaluates the given XPath expression. Two arguments are required: the expression (as a string or compiled expression object), and a context. The context can be given as a Domlette node via the 'contextNode' named argument, or can be given as an Ft.Xml.XPath.Context.Context object via the 'context' named argument. If namespace bindings or variable bindings are needed, use a Context object. If extension functions are needed, either use a Context object, or set the EXTMODULES environment variable to be a ':'-separated list of names of Python modules that implement extension functions. The return value will be one of the following: node-set: list of Domlette node objects (xml.dom.Node based); string: Unicode string type; number: float type; boolean: Ft.Lib.boolean C extension object; or a non-XPath object (i.e. as returned by an extension function). """ if 'EXTMODULES' in os.environ: ext_modules = os.environ["EXTMODULES"].split(':') else: ext_modules = [] if contextNode and context: con = context.clone() con.node = contextNode elif context: con = context elif contextNode: #contextNode should be a node, not a context obj, #but this is a common error. Be forgiving? if isinstance(contextNode, Context.Context): con = contextNode else: con = Context.Context(contextNode, 0, 0, extModuleList=ext_modules) else: # import here to avoid circularity from Ft.Xml.XPath import RuntimeException raise RuntimeException(RuntimeException.NO_CONTEXT) if hasattr(expr, "evaluate"): retval = expr.evaluate(con) else: retval = XPathParser.new().parse(expr).evaluate(con) return retval
def NamespaceUri(context, nodeSet=None): """Function: <string> namespace-uri(<node-set>?)""" if nodeSet is None: node = context.node elif not isinstance(nodeSet, NodesetType): raise RuntimeException(RuntimeException.WRONG_ARGUMENTS, 'namespace-uri', _("expected node-set")) elif not nodeSet: return u'' else: nodeSet.sort() node = nodeSet[0] # only elements and attributes have a namespace-uri node_type = getattr(node, 'nodeType', None) if node_type in (Node.ELEMENT_NODE, Node.ATTRIBUTE_NODE): return node.namespaceURI or u'' return u''
def ExpandQName(qname, refNode=None, namespaces=None): """ Expand the given QName in the context of the given node, or in the given namespace dictionary. Returns a 2-tuple consisting of the namespace URI and local name. """ nss = {} if refNode: nss = GetAllNs(refNode) elif namespaces: nss = namespaces (prefix, local) = SplitQName(qname) #We're not to use the default namespace if prefix: try: split_name = (nss[prefix], local) except KeyError: from Ft.Xml.XPath import RuntimeException raise RuntimeException(RuntimeException.UNDEFINED_PREFIX, prefix) else: split_name = (EMPTY_NAMESPACE, local) return split_name
def Name(context, nodeSet=None): """Function: <string> name(<node-set>?)""" if nodeSet is None: node = context.node elif not isinstance(nodeSet, NodesetType): raise RuntimeException(RuntimeException.WRONG_ARGUMENTS, 'name', _("expected node-set")) elif not nodeSet: return u'' else: nodeSet.sort() node = nodeSet[0] node_type = getattr(node, 'nodeType', None) if node_type in (Node.ELEMENT_NODE, Node.ATTRIBUTE_NODE): return node.nodeName elif node_type == NAMESPACE_NODE: # localName could be null return node.localName or u'' elif node_type == Node.PROCESSING_INSTRUCTION_NODE: # target cannot be null return node.target return u''
def error(self, *args): raise RuntimeException(RuntimeException.UNDEFINED_FUNCTION, self._name)
def HandleStep(expr, states, nss): from Ft.Xml.XPath.ParsedRelativeLocationPath import \ ParsedRelativeLocationPath from Ft.Xml.XPath.ParsedStep import ParsedStep from Ft.Xml.XPath.ParsedAxisSpecifier import \ ParsedChildAxisSpecifier, ParsedAttributeAxisSpecifier from Ft.Xml.XPath.ParsedNodeTest import \ LocalNameTest, QualifiedNameTest, NamespaceTest, PrincipalTypeTest from Ft.Xml.XPath.ParsedExpr import ParsedNLiteralExpr, ParsedEqualityExpr if isinstance(expr, ParsedRelativeLocationPath): HandleStep(expr._left, states, nss) curr_step = expr._right elif isinstance(expr, ParsedStep): curr_step = expr else: raise NotImplementedError(expr) # Guarantee that only the child axis is used if not isinstance(curr_step._axis, ParsedChildAxisSpecifier): raise NotImplementedError(curr_step._axis) # Set criteria by expanded name node_test = curr_step._nodeTest if isinstance(node_test, LocalNameTest): namespace = None local = node_test._name elif isinstance(node_test, (QualifiedNameTest, NamespaceTest)): try: namespace = nss[node_test._prefix] except KeyError: from Ft.Xml.XPath import RuntimeException from Ft.Xml.XPointer import XPtrException error = RuntimeException(RuntimeException.UNDEFINED_PREFIX, node_test._prefix) raise XPtrException(XPtrException.SYNTAX_ERROR, error.message) local = getattr(node_test, '_localName', None) elif isinstance(node_test, PrincipalTypeTest): namespace = None local = None else: raise NotImplementedError(node_test) criteria = [(ELEMENT_MATCH, namespace, local)] # Set criteria from predicates if curr_step._predicates: pred = curr_step._predicates._predicates[0] if isinstance(pred, ParsedNLiteralExpr): #The third item is a counter used to count elements during the parsing criteria.extend([(ELEMENT_COUNT, int(pred._literal))]) elif isinstance(pred, ParsedEqualityExpr) and pred._op == u'=': if isinstance(pred._left, ParsedStep) and \ isinstance(pred._left._axis, ParsedAttributeAxisSpecifier): # criteria code criterion = [ATTRIBUTE_MATCH] # Add the expanded name if hasattr(pred._left._nodeTest, '_localName'): criterion.append(nss[pred._left._nodeTest._prefix]) criterion.append(pred._left._nodeTest._localName) else: criterion.append(None) criterion.append(pred._left._nodeTest._name) # Add the expected value criterion.append(pred._right._literal) # Add this information to the criteria criteria.append(tuple(criterion)) # Add state transitions for the current step states.append(criteria) return states
def Count(context, nodeSet): """Function: <number> count(<node-set>)""" if not isinstance(nodeSet, NodesetType): raise RuntimeException(RuntimeException.WRONG_ARGUMENTS, 'count', _("expected node-set argument")) return float(len(nodeSet))
def Concat(context, *args): """Function: <string> concat(<string>, <string>, ...)""" if len(args) < 1: raise RuntimeException(RuntimeException.WRONG_ARGUMENTS, 'concat', _("at least 2 arguments expected")) return reduce(lambda a, b: a + Conversions.StringValue(b), args, u'')