예제 #1
0
    def Transform(self, func_name, active=0):
        """Parses one or more transform calls and returns a _Transform call object.

    The initial '(' has already been consumed by the caller.

    Args:
      func_name: The name of the first transform function.
      active: The transform active level, None for always active.

    Returns:
      The _Transform object containing the ordered list of transform calls.
    """
        here = self.GetPosition()
        calls = _Transform()
        map_transform = 0
        while True:
            transform = self._ParseTransform(func_name,
                                             active=active,
                                             map_transform=map_transform)
            if transform.func == resource_transform.TransformAlways:
                active = None  # Always active.
                func_name = None
            elif transform.func == resource_transform.TransformMap:
                map_transform = int(transform.args[0]) if transform.args else 1
                func_name = None
            elif transform.func == resource_transform.TransformIf:
                if len(transform.args) != 1:
                    raise resource_exceptions.ExpressionSyntaxError(
                        'Conditional filter expression expected [{0}].'.format(
                            self.Annotate(here)))
                calls.SetConditional(transform.args[0])
            elif transform.func == resource_transform.TransformSynthesize:
                transform.func = self._ParseSynthesize(transform.args)
                transform.args = []
                transform.kwargs = {}
                calls.Add(transform)
            else:
                # always() applies to all transforms for key.
                # map() applies to the next transform.
                map_transform = 0
                calls.Add(transform)
            if not self.IsCharacter('.', eoi_ok=True):
                break
            call = self.Key()
            here = self.GetPosition()
            if not self.IsCharacter('('):
                raise resource_exceptions.ExpressionSyntaxError(
                    'Transform function expected [{0}].'.format(
                        self.Annotate(here)))
            if len(call) != 1:
                raise resource_exceptions.UnknownTransformError(
                    'Unknown transform function {0} [{1}].'.format(
                        '.'.join(call), self.Annotate(here)))
            func_name = call.pop()
        return calls
예제 #2
0
    def _ParseTransform(self, func_name, active=0, map_transform=None):
        """Parses a transform function call.

    The initial '(' has already been consumed by the caller.

    Args:
      func_name: The transform function name.
      active: The transform active level or None if always active.
      map_transform: Apply the transform to each resource list item this many
        times.

    Returns:
      A _TransformCall object. The caller appends these to a list that is used
      to apply the transform functions.

    Raises:
      ExpressionSyntaxError: The expression has a syntax error.
    """
        here = self.GetPosition()
        func = self._defaults.symbols.get(func_name)
        if not func:
            raise resource_exceptions.UnknownTransformError(
                'Unknown transform function {0} [{1}].'.format(
                    func_name, self.Annotate(here)))
        args = []
        kwargs = {}
        doc = getattr(func, '__doc__', None)
        if doc and resource_projection_spec.PROJECTION_ARG_DOC in doc:
            # The second transform arg is the caller projection.
            args.append(self._defaults)
        if getattr(func, '__defaults__', None):
            # Separate the args from the kwargs.
            for arg in self.Args():
                name, sep, val = arg.partition('=')
                if sep:
                    kwargs[name] = val
                else:
                    args.append(arg)
        else:
            # No kwargs.
            args += self.Args()
        return _TransformCall(func_name,
                              func,
                              active=active,
                              map_transform=map_transform,
                              args=args,
                              kwargs=kwargs)