yagwr.checker
: The condition checker
This module implements a simple checker that checks whether a condition matches in a dictionary. It is similar to JsonLogic but it is also much more simpler because it’s not a general solution and only matches dictionaries whose keys and values are strings only.
With this module you can solve Is the value of key A equals 5 and does this regex match the value of key B?-kind of questions.
The conditions can be built directly by generating Node
objects
and linking them toghether according to your logic rules, or you can
create a dictionary and parse it with parse_from_object()
.
The condition dictionary
You have three basic operators: ANY (corresponds to boolean OR
),
ALL (corresponds to boolean AND
) and NOT (corresponds to boolean NOT
).
The basic grammer rules are:
<node> ::= <terminal-node> | <OP>([<node>, <node>, ...])
<terminal-node> ::= "key = value" | "key != value" | "key ~= regex" | "key !~= regex"
<OP> ::= "ANY" | "ALL" | "NOT"
The <OP>
(operator) corresponds to the dictionary key. The operands (the other <node>
s)
are decoded inside a list. That means that you always need at least one operator.
Example
We want to implement this condition:
(akane != kun) OR ( (genma = san) AND (nabiki ~= tendou?) )
The dictionary with this rules is:
{
"ANY": [
"akane != kun",
{
"ALL": [
"genma = san",
"nabiki ~= tendou?"
]
}
]
}
The following dictionary will match the condition:
{
"akane": "chan",
"ranma": "kun",
"genma": "san",
"nabiki": "tendo",
}
The following dictionary will not match the condition:
{
"akane": "chan",
"ranma": "kun",
"genma": "saotome",
"nabiki": "tendo",
}
Note
For simplicity, the left-hand-side of <terminal-node>
string
supports letters, numbers, dashes and underscores only. The module uses
the following regular expression \w[\w\s]*
to match the left-hand-side.
Adding full unicode support would make the code unnecessarily complicated, specially
since in yagwr
the dictionaries to be matched are going to contains
those characters only.
If you need something more powerful or a more general solution, we recommend JsonLogic.
- exception yagwr.checker.InvalidExpression
Bases:
Exception
This exception is raised when parsing the condition-dictionary fails because of an incorrect type was passed.
- class yagwr.checker.Node(kind, children=[])
Bases:
object
The base node. All nodes must have at least one children.
Do not instantiate this class directly.
- Parameters
- class yagwr.checker.LiteralNode(expr)
Bases:
yagwr.checker.Node
A Literal Node, that means it’s a terminal node. It doesn’t have children.
- Parameters
expr (str) – the boolean expression. The operator can be one of:
=
(equals),!=
(not equals),~=
matches regular expression,!~=
doesn not match regular expression. The left-hand-side and the right-hand-side values are trimmed.
- class yagwr.checker.NotNode(node)
Bases:
yagwr.checker.Node
A NOT Node.
- Parameters
node (Node) – The node to be negated
- class yagwr.checker.AllNode(nodes)
Bases:
yagwr.checker.Node
A AND Node.
- class yagwr.checker.AnyNode(nodes)
Bases:
yagwr.checker.Node
A OR Node.
- yagwr.checker.parse_from_object(obj)
Parses the condition from a dictionary.
- Parameters
obj (dict) – The dictionary containing the condition. See condition dictionary for the structure of the dictionary.
- Returns
The node representing the out-most operator of the condition
- Return type