Esempio n. 1
0
def evaluateTokens(requestContext, tokens, replacements=None, pipedArg=None):
  if tokens.template:
    arglist = dict()
    if tokens.template.kwargs:
      arglist.update(dict([(kwarg.argname, evaluateScalarTokens(kwarg.args[0])) for kwarg in tokens.template.kwargs]))
    if tokens.template.args:
      arglist.update(dict([(str(i+1), evaluateScalarTokens(arg)) for i, arg in enumerate(tokens.template.args)]))
    if 'template' in requestContext:
      arglist.update(requestContext['template'])
    return evaluateTokens(requestContext, tokens.template, arglist)

  if tokens.expression:
    if tokens.expression.pipedCalls:
      # when the expression has piped calls, we pop the right-most call and pass the remaining
      # expression into it via pipedArg, to get the same result as a nested call
      rightMost = tokens.expression.pipedCalls.pop()
      return evaluateTokens(requestContext, rightMost, replacements, tokens)

    return evaluateTokens(requestContext, tokens.expression, replacements)

  if tokens.pathExpression:
    expression = tokens.pathExpression
    if replacements:
      for name in replacements:
        if expression == '$'+name:
          val = replacements[name]
          if not isinstance(val, six.string_types):
            return val
          elif re.match('^-?[\d.]+$', val):
            return float(val)
          else:
            return val
        else:
          expression = expression.replace('$'+name, str(replacements[name]))
    return fetchData(requestContext, expression)

  if tokens.call:
    if tokens.call.funcname == 'template':
      # if template propagates down here, it means the grammar didn't match the invocation
      # as tokens.template. this generally happens if you try to pass non-numeric/string args
      raise ValueError("invalid template() syntax, only string/numeric arguments are allowed")

    if tokens.call.funcname == 'seriesByTag':
      return fetchData(requestContext, tokens.call.raw)

    func = SeriesFunction(tokens.call.funcname)
    rawArgs = tokens.call.args or []
    if pipedArg is not None:
      rawArgs.insert(0, pipedArg)
    args = [evaluateTokens(requestContext, arg, replacements) for arg in rawArgs]
    requestContext['args'] = rawArgs
    kwargs = dict([(kwarg.argname, evaluateTokens(requestContext, kwarg.args[0], replacements))
                   for kwarg in tokens.call.kwargs])
    try:
      return func(requestContext, *args, **kwargs)
    except NormalizeEmptyResultError:
      return []

  return evaluateScalarTokens(tokens)
Esempio n. 2
0
def functionDetails(request, queryParams, name):
    if request.method != 'GET':
        return HttpResponse(status=405)

    try:
        if queryParams.get('type') == 'pie':
            func = PieFunction(name)
        else:
            func = SeriesFunction(name)
    except KeyError:
        raise HttpError('Function not found: %s' % name, status=404)

    return functionInfo(name, func)
def evaluateTokens(requestContext, tokens, replacements=None, pipedArg=None):
  if tokens.template:
    arglist = dict()
    if tokens.template.kwargs:
      arglist.update(dict([(kwarg.argname, evaluateScalarTokens(kwarg.args[0])) for kwarg in tokens.template.kwargs]))
    if tokens.template.args:
      arglist.update(dict([(str(i+1), evaluateScalarTokens(arg)) for i, arg in enumerate(tokens.template.args)]))
    if 'template' in requestContext:
      arglist.update(requestContext['template'])
    return evaluateTokens(requestContext, tokens.template, arglist)

  if tokens.expression:
    if tokens.expression.pipedCalls:
      # when the expression has piped calls, we pop the right-most call and pass the remaining
      # expression into it via pipedArg, to get the same result as a nested call
      rightMost = tokens.expression.pipedCalls.pop()
      return evaluateTokens(requestContext, rightMost, replacements, tokens)

    return evaluateTokens(requestContext, tokens.expression, replacements)

  if tokens.pathExpression:
    expression = tokens.pathExpression
    if replacements:
      for name in replacements:
        if expression == '$'+name:
          val = replacements[name]
          if not isinstance(val, six.string_types):
            return val
          elif re.match(r'^-?[\d.]+$', val):
            return float(val)
          else:
            return val
        else:
          expression = expression.replace('$'+name, str(replacements[name]))
    return fetchData(requestContext, expression)

  if tokens.call:
    if tokens.call.funcname == 'template':
      # if template propagates down here, it means the grammar didn't match the invocation
      # as tokens.template. this generally happens if you try to pass non-numeric/string args
      raise InputParameterError("invalid template() syntax, only string/numeric arguments are allowed")

    if tokens.call.funcname == 'seriesByTag':
      return fetchData(requestContext, tokens.call.raw)

    try:
      func = SeriesFunction(tokens.call.funcname)
    except KeyError:
      raise InputParameterError('Received request for unknown function: {func}'.format(func=tokens.call.funcname))

    rawArgs = tokens.call.args or []
    if pipedArg is not None:
      rawArgs.insert(0, pipedArg)
    args = [evaluateTokens(requestContext, arg, replacements) for arg in rawArgs]
    requestContext['args'] = rawArgs
    kwargs = dict([(kwarg.argname, evaluateTokens(requestContext, kwarg.args[0], replacements))
                   for kwarg in tokens.call.kwargs])

    def handleInvalidParameters(e):
      e.setSourceIdHeaders(requestContext.get('sourceIdHeaders', {}))
      e.setTargets(requestContext.get('targets', []))
      e.setFunction(tokens.call.funcname, args, kwargs)

      if settings.ENFORCE_INPUT_VALIDATION:
        raise e

      if not getattr(handleInvalidParameters, 'alreadyLogged', False):
        log.warning('%s', str(e))

        # only log invalid parameters once
        setattr(handleInvalidParameters, 'alreadyLogged', True)

    if hasattr(func, 'params'):
      try:
        (args, kwargs) = validateParams(tokens.call.funcname, func.params, args, kwargs)
      except InputParameterError as e:
        handleInvalidParameters(e)

    try:
      return func(requestContext, *args, **kwargs)
    except NormalizeEmptyResultError:
      return []
    except InputParameterError as e:
      handleInvalidParameters(e)

  return evaluateScalarTokens(tokens)