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
  • kind (str) – A string representation of the kind of the node

  • children (list) – a list of the children of the node, they must be of type Node.

eval(ref)

Evaluates the condition in the node given a dictionary

Parameters

ref (dict) – the dictionary to be evaluated

Returns bool

True if the condition matches the values in the dictionary, False otherwise.

to_dict()
Returns

The condition in dictionary form.

Return type

dict

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.

eval(ref)

Evaluates the condition in the node given a dictionary

Parameters

ref (dict) – the dictionary to be evaluated

Returns bool

True if the condition matches the values in the dictionary, False otherwise.

class yagwr.checker.NotNode(node)

Bases: yagwr.checker.Node

A NOT Node.

Parameters

node (Node) – The node to be negated

eval(ref)

Evaluates the condition in the node given a dictionary

Parameters

ref (dict) – the dictionary to be evaluated

Returns bool

True if the condition matches the values in the dictionary, False otherwise.

class yagwr.checker.AllNode(nodes)

Bases: yagwr.checker.Node

A AND Node.

Parameters

nodes (list(Node)) – A list of nodes that all must individually match the condition.

eval(ref)

Evaluates the condition in the node given a dictionary

Parameters

ref (dict) – the dictionary to be evaluated

Returns bool

True if the condition matches the values in the dictionary, False otherwise.

class yagwr.checker.AnyNode(nodes)

Bases: yagwr.checker.Node

A OR Node.

Parameters

nodes (list(Node)) – A list of nodes. Only one must match the condition.

eval(ref)

Evaluates the condition in the node given a dictionary

Parameters

ref (dict) – the dictionary to be evaluated

Returns bool

True if the condition matches the values in the dictionary, False otherwise.

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

Node