moira-client

Форк
0
/
expression.py 
101 строка · 2.5 Кб
1
import ast
2

3

4
class ConvertError(Exception):
5
    pass
6

7

8
def _parse_cmp_op(node):
9
    if isinstance(node, ast.Lt):
10
        return '<'
11
    if isinstance(node, ast.Gt):
12
        return '>'
13
    if isinstance(node, ast.LtE):
14
        return '<='
15
    if isinstance(node, ast.GtE):
16
        return '>='
17
    if isinstance(node, ast.Eq):
18
        return '=='
19
    if isinstance(node, ast.NotEq):
20
        return '!='
21

22
    raise ConvertError('unknown op node={}'.format(ast.dump(node)))
23

24

25
def _parse_logic_op(node):
26
    if isinstance(node, ast.Or):
27
        return '||'
28
    if isinstance(node, ast.And):
29
        return '&&'
30
    raise ConvertError('unknown logic op node={}'.format(ast.dump(node)))
31

32

33
def _parse_comparator(node):
34
    if isinstance(node, ast.Num):
35
        return node.n
36
    elif isinstance(node, ast.Name):
37
        return node.id
38
    if isinstance(node, ast.BoolOp):
39
        return _parse_boolop(node)
40
    elif isinstance(node, ast.Compare):
41
        return _parse_compare(node)
42
    raise ConvertError('unknown comparator node={}'.format(ast.dump(node)))
43

44

45
def _parse_boolop(node):
46
    need_parens = len(node.values) > 1
47
    cmps = []
48
    for v in node.values:
49
        r = _parse_comparator(v)
50
        if need_parens:
51
            r = '(' + r + ')'
52
        cmps.append(r)
53

54
    op = _parse_logic_op(node.op)
55
    op = f' {op} '
56
    return op.join(cmps)
57

58

59
def _parse_compare(node):
60
    if len(node.ops) != 1 or len(node.comparators) != 1:
61
        raise ConvertError('multiple ops/comparators {}'.format(ast.dump(node.body)))
62

63
    op = _parse_cmp_op(node.ops[0])
64
    right = _parse_comparator(node.comparators[0])
65
    left = node.left.id
66
    return f'{left} {op} {right}'
67

68

69
def _parse_ifnode(node):
70
    cond = _parse_comparator(node.test)
71

72
    if isinstance(node.orelse, ast.IfExp):
73
        else_ = _parse_ifnode(node.orelse)
74
        else_ = '(' + else_ + ')'
75
    else:
76
        else_ = node.orelse.id
77

78
    if_ = node.body.id
79

80
    return f'({cond}) ? {if_} : {else_}'
81

82

83
def _convert_expression(expr):
84
    node = ast.parse(expr, mode='eval')
85
    if not isinstance(node, ast.Expression):
86
        raise ConvertError('unknown root node={}'.format(ast.dump(node)))
87

88
    if not isinstance(node.body, ast.IfExp):
89
        raise ConvertError('unknown if node={}'.format(ast.dump(node.body)))
90

91
    return _parse_ifnode(node.body)
92

93

94
def convert_python_expression(expr):
95
    """
96
    converts old python moira expression to new govaluate expression
97
    """
98
    try:
99
        return _convert_expression(expr)
100
    except Exception as e:
101
        raise ConvertError("convert error") from e
102

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.