networkx_query.operator.op_in()   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 5
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
nop 3
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
# type: ignore
2
"""Define few operator."""
3
from typing import Any, List, Tuple
4
5
from .definition import Evaluator, OperatoryArity, Path, register_operator
6
7
8
def lookup_path(context: Any, sub_paths: Path) -> Tuple[bool, Any]:
9
    """Lookup attributs in a context like dictionary.
10
11
    Arguments:
12
        context (Any): a dictionnary like structure with in and [] methods
13
            (support __contains__ or  (__iter__ and __getitem__)).
14
        sub_paths (Path): a path (single string or an ordered tuple of string)
15
16
    Returns:
17
        (Tuple[bool, Any]): (True, attribut value ) or (False, None) if path not found
18
19
    Exceptions:
20
        (RuntimeError): if context did not compliant
21
22
    """
23
    if not context:
24
        return (False, None)
25
26
    if not (hasattr(context, "__contains__") or (hasattr(context, "__iter__") and hasattr(context, "__getitem__"))):
27
        raise RuntimeError('Context must be dictionnary like')
28
29
    if isinstance(sub_paths, Tuple):
30
        if sub_paths:
31
            # len > 0
32
            current = context
33
            i = 0
34
            while i < len(sub_paths):
35
                p = sub_paths[i]
36
                if not current or p not in current:
37
                    return (False, None)
38
                i += 1
39
                current = current[p]
40
            return (True, current)
41
        return (False, None)
42
43
    # simple string
44
    match = sub_paths in context
45
    return (match, context[sub_paths] if match else None)
46
47
48
@register_operator(name="has", arity=OperatoryArity.BINARY, profile=[Any, Path])
49
def op_has(context: Any, path: Path) -> bool:
50
    """Check if path exists in context."""
51
    (match, _) = lookup_path(context, path)
52
    return match
53
54
55
@register_operator(name="contains", arity=OperatoryArity.TERNARY, profile=[Any, Path, str])
56
def op_contains(context: Any, path: Path, value: str) -> bool:
57
    """Check if attribut (specifed with path) exists and contains specified value."""
58
    (match, _current_value) = lookup_path(context, path)
59
    return match and _current_value.find(value) != -1
60
61
62
@register_operator(name="eq", alias="==", arity=OperatoryArity.TERNARY, profile=[Any, Path, Any])
63
def op_eq(context: Any, path: Path, value: Any) -> bool:
64
    """Check if attribut (specifed with path) exists and equals specified value."""
65
    (match, _current_value) = lookup_path(context, path)
66
    return match and _current_value == value
67
68
69
@register_operator(name="neq", alias="!=", arity=OperatoryArity.TERNARY, profile=[Any, Path, Any])
70
def op_neq(context: Any, path: Path, value: Any) -> bool:
71
    """Check if attribut (specifed with path) did not exists or not equals specified value."""
72
    return not op_eq(context, path, value)
73
74
75
@register_operator(name="gt", alias=">", arity=OperatoryArity.TERNARY, profile=[Any, Path, Any])
76
def op_gt(context: Any, path: Path, value: Any) -> bool:
77
    """Check if attribut (specifed with path) exists and greather that specified value."""
78
    (match, _current_value) = lookup_path(context, path)
79
    return match and _current_value > value
80
81
82
@register_operator(name="lt", alias="<", arity=OperatoryArity.TERNARY, profile=[Any, Path, Any])
83
def op_lt(context: Any, path: Path, value: Any) -> bool:
84
    """Check if attribut (specifed with path) exists and lower that specified value."""
85
    (match, _current_value) = lookup_path(context, path)
86
    return match and _current_value < value
87
88
89
@register_operator(name="gte", alias=">=", arity=OperatoryArity.TERNARY, profile=[Any, Path, Any])
90
def op_gte(context: Any, path: Path, value: Any) -> bool:
91
    """Check if attribut (specifed with path) exists and greather or equals that specified value."""
92
    (match, _current_value) = lookup_path(context, path)
93
    return match and _current_value >= value
94
95
96
@register_operator(name="lte", alias="<=", arity=OperatoryArity.TERNARY, profile=[Any, Path, Any])
97
def op_lte(context: Any, path: Path, value: Any) -> bool:
98
    """Check if attribut (specifed with path) exists and lower or equals that specified value."""
99
    (match, _current_value) = lookup_path(context, path)
100
    return match and _current_value <= value
101
102
103
@register_operator(name="in", alias=":=", arity=OperatoryArity.TERNARY, profile=[Any, Path, List[Any]])
104
def op_in(context: Any, path: Path, value: List[Any]) -> bool:
105
    """Check if attribut (specifed with path) exists and attribut value in specified value."""
106
    (match, _current_value) = lookup_path(context, path)
107
    return match and _current_value in value
108
109
110
@register_operator(name="and", alias="&&", arity=OperatoryArity.NARY, combinator=True, profile=[Any, Evaluator])
111
def op_and(context: Any, *filters: Evaluator) -> bool:
112
    """Define And operator."""
113
    for f in filters:
114
        if not f(context):
115
            return False
116
    return True
117
118
119
@register_operator(name="or", alias="||", arity=OperatoryArity.NARY, combinator=True, profile=[Any, Evaluator])
120
def op_or(context: Any, *filters: Evaluator) -> bool:
121
    """Define Or operator."""
122
    for f in filters:
123
        if f(context):
124
            return True
125
    return False
126
127
128
@register_operator(name="xor", arity=OperatoryArity.NARY, combinator=True, profile=[Any, Evaluator])
129
def op_xor(context: Any, *filters: Evaluator) -> bool:
130
    """Define Xor operator."""
131
    is_true = False
132
    for f in filters:
133
        _test = f(context)
134
        is_true = (is_true and not _test) or (not is_true and _test)
135
    return is_true
136
137
138
@register_operator(name="nxor", arity=OperatoryArity.NARY, combinator=True, profile=[Any, Evaluator])
139
def op_nxor(context: Any, *filters: Evaluator) -> bool:
140
    """Define nxor operator."""
141
    return not op_xor(context, *filters)
142
143
144
@register_operator(name="not", arity=OperatoryArity.BINARY, combinator=True, profile=[Any, Evaluator], alias="!")
145
def op_not(context: Any, a_filter: Evaluator) -> bool:
146
    """Define Not operator."""
147
    return not a_filter(context)
148