Source code for glideinwms.lib.exprParser

# SPDX-FileCopyrightText: 2009 Fermi Research Alliance, LLC
# SPDX-License-Identifier: Apache-2.0

"""
Description: general purpose python expression parser and unparser
"""

import ast
import itertools

# These are used in modules importing exprParser, like frontend_match_ana
from ast import And, Not, Or  # noqa: F401
from io import StringIO

from .unparser import Unparser

# Keeping this line from the Python 2 version to have a list of the objects supported
# NOTE: compiler.ast is slightly different from the concrete tree in ast
# from compiler.ast import Name, Const, Keyword, List, Tuple, And, Or, Not, UnaryAdd, UnarySub, Compare, Add, Sub, Mul, FloorDiv, Div, Mod, Power, LeftShift, RightShift, Bitand, Bitor, Bitxor, CallFunc, Getattr, Subscript, Slice, Lambda


[docs] def exp_parse(expression): """Convert an expression string into an ast object Args: expression (str): expression string Returns: ast.AST: ast tree from the expression, starting from ast.Expression node """ # mode='exec' (default) for sequence of statements # eval - single expression # single - single interactive statement return ast.parse(expression, "<string>", mode="eval")
[docs] def exp_compile(obj): """Convert an ast object into a code object Args: obj (ast.AST): AST object to compile Returns: code object """ return compile(obj, "<string>", mode="eval")
[docs] def exp_unparse(obj, raise_on_unknown=False): """Convert an ast object back into a string Args: obj (ast.AST): ast object to convert back to string raise_on_unknown (bool): Returns: str: string with the expression """ with StringIO() as output: Unparser(obj, output) outstr = output.getvalue() return outstr.strip()
[docs] def exp_compare(node1, node2): """Compare 2 AST trees to verify if they are the same Args: node1 (ast.AST): AST tree node2 (ast.AST): AST tree Returns: bool: True if node1 and node2 are the same expression """ if type(node1) is not type(node2): return False if isinstance(node1, ast.AST): for k, v in vars(node1).items(): if k in ("lineno", "col_offset", "ctx", "end_lineno", "end_col_offset"): continue if not exp_compare(v, getattr(node2, k)): return False return True elif isinstance(node1, list): return all(itertools.starmap(exp_compare, zip(node1, node2))) else: return node1 == node2