Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Booley

A meta-language to evaluate boolean expressions using a dict's keys as context variables.

Booley parses a small, human-readable expression language — things like age >= 18 AND country == "US" — and evaluates it against a Python dict that supplies the values of the variables referenced in the expression.

Installation

pip install booley

Requires pyparsing (installed automatically).

Quick start

from booley import Booley

context = {
    'first_name': 'Michael',
    'last_name': 'Jordan',
    'age': 60,
}

parser = Booley(context)
parser.parse('first_name == "Michael" AND age >= 18')
# True

You can also reuse the same parser with a different context on every call:

parser = Booley()
parser.parse('age >= 18', {'age': 21})   # True
parser.parse('age >= 18', {'age': 15})   # False

Checking syntax without a context

check_syntax validates that an expression is well-formed and evaluates to a boolean, without needing real values for the variables:

parser.check_syntax('age >= 18 AND country == "US"')  # True
parser.check_syntax('age >=')                          # raises BooleySyntaxError

Language reference

Values

Type Examples
String 'single quoted', "double quoted"
Integer 9111, +9111, -9111
Real 1.0, .123, -1.12355
Boolean TRUE, FALSE (case-insensitive)
Variable Any key present in the context dict, e.g. age, first_name

Variables are resolved from the context dict passed to parse() / check_syntax(). A missing variable resolves to an empty string. List values are joined with | before being compared as strings.

Variables can be sliced with name[start:end] (Python-style slicing on the resolved string value):

parser.parse('alpha[2:7] == "cdefg"', {'alpha': 'abcdefghijklmnopqrstuvwxyz'})  # True

Comparison operators

Operator Meaning Works on
=, == Equal numbers, strings, booleans
!= Not equal numbers, strings, booleans
<, <=, >, >= Ordering comparison numbers, strings
HAS Left contains right strings/lists
NOT HAS Left does not contain right strings/lists
IN Left is contained in right strings/lists
NOT IN Left is not contained in right strings/lists
STARTS WITH Left starts with right strings
NOT STARTS WITH Left does not start with right strings
ENDS WITH Left ends with right strings
NOT ENDS WITH Left does not end with right strings
IS NULL Left is None any
IS NOT NULL Left is not None any
LENGTH IS len(left) == right strings
LENGTH IS NOT len(left) != right strings

All keyword operators (HAS, IN, STARTS WITH, ENDS WITH, LENGTH IS, ...) are case-insensitive.

Boolean operators

Operator Meaning
AND Logical and
OR Logical or
NOT Logical negation
( ) Grouping / precedence

Expressions can be nested and combined freely:

parser.parse(
    "TRUE AND (2 > 1) AND NOT 1 == 1 OR 'a' != 'b' OR NOT ((TRUE OR (2 > 1)) == (height > 2))",
    {'height': 1.98}
)

Examples

context = {
    'name': 'Michael Jordan',
    'first_name': 'Michael',
    'last_name': 'Jordan',
    'weight': '98.0',
    'height': '1.98',
    'retired': True,
    'fruits': ['apple', 'banana'],
}
parser = Booley(context)

parser.parse('first_name == "Michael"')                     # True
parser.parse('last_name != "Bryant"')                         # True
parser.parse('fruits HAS "apple"')                            # True
parser.parse('"apple" IN fruits')                             # True
parser.parse('name STARTS WITH "Michael"')                    # True
parser.parse('name ENDS WITH "Jordan"')                        # True
parser.parse('name LENGTH IS 14')                              # True
parser.parse('height > 2')                                     # False

Errors

Booley raises exceptions from booley.exceptions:

  • BooleySyntaxError — the expression could not be parsed, or an operator was used with an invalid operand (e.g. IS NOT NULL compared against something other than NULL).
  • UnknownOperation — an internal/unsupported operator was encountered.
  • VariableNotFound — reserved for variable resolution errors.

Running the tests

python -m unittest booley.tests

License

MIT — see LICENSE.

About

A meta-language to evaluate boolean expressions using a dict keys as context variables.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages