Beispiel #1
0
    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
Beispiel #2
0
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)
Beispiel #3
0
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)
Beispiel #5
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])
Beispiel #6
0
 def getQuickKey(self, namespaces):
     try:
         namespace = namespaces[self._prefix]
     except KeyError:
         raise RuntimeException(RuntimeException.UNDEFINED_PREFIX,
                                self._prefix)
     return (self.nodeType, (namespace, self._localName))
Beispiel #7
0
    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
Beispiel #8
0
 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)
Beispiel #9
0
 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
Beispiel #10
0
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
Beispiel #11
0
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''
Beispiel #12
0
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
Beispiel #13
0
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''
Beispiel #14
0
 def error(self, *args):
     raise RuntimeException(RuntimeException.UNDEFINED_FUNCTION, self._name)
Beispiel #15
0
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
Beispiel #16
0
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))
Beispiel #17
0
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'')