(transformers, name, **modifiers)
return execute_expression
This allows the evaluation of a limited subset of Python syntax and built-in functions.

    ```yaml
    columns:
      - name: disk.total
        type: gauge
      - name: disk.used
        type: gauge
    extras:
      - name: disk.free
        expression: disk.total - disk.used
        submit_type: gauge
    ```

    For brevity, if the `expression` attribute exists and `type` does not then it is assumed the type is
    `expression`. The `submit_type` can be any transformer and any extra options are passed down to it.

    The result of every expression is stored, so in lieu of a `submit_type` the above example could also be written as:

    ```yaml
    columns:
      - name: disk.total
        type: gauge
      - name: disk.used
        type: gauge
    extras:
      - name: free
        expression: disk.total - disk.used
      - name: disk.free
        type: gauge
        source: free
    ```

    The order matters though, so for example the following will fail:

    ```yaml
    columns:
      - name: disk.total
        type: gauge
      - name: disk.used
        type: gauge
    extras:
      - name: disk.free
        type: gauge
        source: free
      - name: free
        expression: disk.total - disk.used
    ```

    since the source `free` does not yet exist.
This allows the evaluation of a limited subset of Python syntax and built-in functions.
This allows the evaluation of a limited subset of Python syntax and built - in functions .
def get_expression(transformers, name, **modifiers):
    # type: (Dict[str, Transformer], str, Dict[str, Any]) -> Transformer
    """
    This allows the evaluation of a limited subset of Python syntax and built-in functions.

    ```yaml
    columns:
      - name: disk.total
        type: gauge
      - name: disk.used
        type: gauge
    extras:
      - name: disk.free
        expression: disk.total - disk.used
        submit_type: gauge
    ```

    For brevity, if the `expression` attribute exists and `type` does not then it is assumed the type is
    `expression`. The `submit_type` can be any transformer and any extra options are passed down to it.

    The result of every expression is stored, so in lieu of a `submit_type` the above example could also be written as:

    ```yaml
    columns:
      - name: disk.total
        type: gauge
      - name: disk.used
        type: gauge
    extras:
      - name: free
        expression: disk.total - disk.used
      - name: disk.free
        type: gauge
        source: free
    ```

    The order matters though, so for example the following will fail:

    ```yaml
    columns:
      - name: disk.total
        type: gauge
      - name: disk.used
        type: gauge
    extras:
      - name: disk.free
        type: gauge
        source: free
      - name: free
        expression: disk.total - disk.used
    ```

    since the source `free` does not yet exist.
    """
    available_sources = modifiers.pop('sources')

    expression = modifiers.pop('expression', None)
    if expression is None:
        raise ValueError('the `expression` parameter is required')
    elif not isinstance(expression, str):
        raise ValueError('the `expression` parameter must be a string')
    elif not expression:
        raise ValueError('the `expression` parameter must not be empty')

    if not modifiers.pop('verbose', False):
        # Sort the sources in reverse order of length to prevent greedy matching
        available_sources = sorted(available_sources, key=lambda s: -len(s))

        # Escape special characters, mostly for the possible dots in metric names
        available_sources = list(map(re.escape, available_sources))

        # Finally, utilize the order by relying on the guarantees provided by the alternation operator
        available_sources = '|'.join(available_sources)

        expression = re.sub(
            SOURCE_PATTERN.format(available_sources),
            # Replace by the particular source that matched
            lambda match_obj: 'SOURCES["{}"]'.format(match_obj.group(1)),
            expression,
        )

    expression = compile(expression, filename=name, mode='eval')

    del available_sources

    if 'submit_type' in modifiers:
        if modifiers['submit_type'] not in transformers:
            raise ValueError('unknown submit_type `{}`'.format(modifiers['submit_type']))

        submit_method = transformers[modifiers.pop('submit_type')](transformers, name, **modifiers)  # type: Transformer
        submit_method = create_extra_transformer(submit_method)  # type: Callable

        def execute_expression(sources, **kwargs):
            # type: (Dict[str, Any], Dict[str, Any]) -> float
            result = eval(expression, ALLOWED_GLOBALS, {'SOURCES': sources})  # type: float
            submit_method(sources, result, **kwargs)
            return result

    else:

        def execute_expression(sources, **kwargs):
            # type: (Dict[str, Any], Dict[str, Any]) -> Any
            return eval(expression, ALLOWED_GLOBALS, {'SOURCES': sources})

    return execute_expression
def get_expression ( transformers , name , * * modifiers ) : # type: (Dict[str, Transformer], str, Dict[str, Any]) -> Transformer available_sources = modifiers . pop ( 'sources' ) expression = modifiers . pop ( 'expression' , None ) if expression is None : raise ValueError ( 'the `expression` parameter is required' ) elif not isinstance ( expression , str ) : raise ValueError ( 'the `expression` parameter must be a string' ) elif not expression : raise ValueError ( 'the `expression` parameter must not be empty' ) if not modifiers . pop ( 'verbose' , False ) : # Sort the sources in reverse order of length to prevent greedy matching available_sources = sorted ( available_sources , key = lambda s : - len ( s ) ) # Escape special characters, mostly for the possible dots in metric names available_sources = list ( map ( re . escape , available_sources ) ) # Finally, utilize the order by relying on the guarantees provided by the alternation operator available_sources = '|' . join ( available_sources ) expression = re . sub ( SOURCE_PATTERN . format ( available_sources ) , # Replace by the particular source that matched lambda match_obj : 'SOURCES["{}"]' . format ( match_obj . group ( 1 ) ) , expression , ) expression = compile ( expression , filename = name , mode = 'eval' ) del available_sources if 'submit_type' in modifiers : if modifiers [ 'submit_type' ] not in transformers : raise ValueError ( 'unknown submit_type `{}`' . format ( modifiers [ 'submit_type' ] ) ) submit_method = transformers [ modifiers . pop ( 'submit_type' ) ] ( transformers , name , * * modifiers ) # type: Transformer submit_method = create_extra_transformer ( submit_method ) # type: Callable def execute_expression ( sources , * * kwargs ) : # type: (Dict[str, Any], Dict[str, Any]) -> float result = eval ( expression , ALLOWED_GLOBALS , { 'SOURCES' : sources } ) # type: float submit_method ( sources , result , * * kwargs ) return result else : def execute_expression ( sources , * * kwargs ) : # type: (Dict[str, Any], Dict[str, Any]) -> Any return eval ( expression , ALLOWED_GLOBALS , { 'SOURCES' : sources } ) return execute_expression