Skip to content

Instantly share code, notes, and snippets.

@cb109
Last active February 26, 2024 13:42
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cb109/208cbb65d92b8d31c070ab9e585e5a69 to your computer and use it in GitHub Desktop.
Save cb109/208cbb65d92b8d31c070ab9e585e5a69 to your computer and use it in GitHub Desktop.
Use booleano to evaluate simple symbolic expressions.
"""Use booleano to evaluate simple symbolic expressions.
This is useful to provide a mini DSL to define conditions in
application logic for script-savvy users or as an intermediate
for actual UI elements. The main benefit is that it does not
involve the use of python's eval() and therefore no security
concerns.
booleano supports a number of useful operators out of the box,
like equality, belongs-to, greater-than etc. which frees us
from having to solve those sub-expressions to booleans beforehand.
Requirements:
$ pip install booleano
"""
from booleano.utils import eval_boolean
# This is the main use case: Define some expression and compare
# it with a context and tell me if the condition is met.
raw_expression = "permissions.is_admin and 'chris' in request.user.username"
raw_variables = {
"a": True,
"permissions": {
"is_admin": True,
},
"request": {
"user": {
"username": "christoph",
}
}
}
constants = {}
grammar_tokens = {
"and": "and",
"or": "or",
"not": "not",
"belongs_to": "in",
}
ATTR_SEPARATOR = "__"
def flatten(unflattened_dict, separator=ATTR_SEPARATOR):
"""https://stackoverflow.com/a/54963740"""
flattened_dict = {}
for k, v in unflattened_dict.items():
if isinstance(v, dict):
sub_flattened_dict = flatten(v, separator)
for k2, v2 in sub_flattened_dict.items():
flattened_dict[k + separator + k2] = v2
else:
flattened_dict[k] = v
return flattened_dict
def parse_variables(vars):
return flatten(vars)
def parse_expression(expr):
return expr.replace(".", ATTR_SEPARATOR)
variables = parse_variables(raw_variables)
expression = parse_expression(raw_expression)
is_condition_met = eval_boolean(
expression,
variables=variables,
constants=constants,
grammar_tokens=grammar_tokens,
)
print(f"is_condition_met: {is_condition_met}")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment