Welcome to boolrule’s documentation¶
boolrule is a simpe boolean expression evaluation engine.
boolrule was built by the team at tails.com to evaluate conditional edges between nodes in a graph-like structure, though we’ve found numerous uses for it since.
Contents:
boolrule¶
Simple boolean expression evaluation engine.
- Free software: MIT license
- Documentation: https://boolrule.readthedocs.io.
Features¶
Compare simple boolean statements:
>>> rule = BoolRule('5 > 3')
>>> rule.test()
True
>>> rule = BoolRule('5 < 3')
>>> rule.test()
False
Evaluate boolean statements against a context dict:
>>> can_buy_beer = BoolRule('user.age_years >= 18')
>>> can_buy_beer.test({'user':{'age_years': 12}})
False
>>> can_buy_beer.test({'user':{'age_years': 20}})
True
Combine conditions with and and or operators to produce complex expressions:
>>> is_hipster = BoolRule('address.postcode.outcode in ("E1","E2") or user.has_beard = true')
>>> address = {
>>> 'postcode': {
>>> 'outcode': 'E1'
>>> }
>>> }
>>> is_hipster.test({'has_beard': False, 'address': address})
True
Credits¶
Made possible by the excellent pyparsing library.
This package was created with Cookiecutter and the audreyr/cookiecutter-pypackage project template.
Installation¶
Stable release¶
To install boolrule, run this command in your terminal:
$ pip install boolrule
This is the preferred method to install boolrule, as it will always install the most recent stable release.
If you don’t have pip installed, this Python installation guide can guide you through the process.
From sources¶
The sources for boolrule can be downloaded from the Github repo.
You can either clone the public repository:
$ git clone git://github.com/tailsdotcom/boolrule
Or download the tarball:
$ curl -OL https://github.com/tailsdotcom/boolrule/tarball/master
Once you have a copy of the source, you can install it with:
$ python setup.py install
Usage¶
The entirety of boolrule’s functionality is encapsulated in the BoolRule
class.
Getting started¶
The simplest use case is evaluating simple, self-contained expressions:
from boolrule import BoolRule
expression = '5 > 10'
rule = BoolRule(expression)
rule.test() # False
However, the real power of boolrule comes when the expression makes use of values from the context dict passed to the test() method:
from boolrule import BoolRule
expression = 'content.is_published = true and user.level in content.allowed_levels'
rule = BoolRule(expression)
context = {
'user': {
'level': 'super',
},
'content': {
"is_published": True,
'allowed_levels': [
'admin',
'super'
]
},
}
if rule.test(context):
# Let the user see the content
pass
Lazy compilation¶
By default the expression is compiled when you create a new BoolRule
object. If you’re instantiating a lot of BoolRule
instances but are only
likely to call test
on a few of them (because you’re looking for just the
first match, for example) then you can use the optional lazy`
argument in
the call to BoolRule`
to defer compilation until the first call to
test()
:
rules = [
BoolRule(expression, lazy=True)
for expression in expressions
]
if any(r in rules.test(context)):
# Do a thing
pass
boolrule API¶
BoolRule¶
-
class
boolrule.
BoolRule
(query, lazy=False)[source]¶ Represents a boolean expression and provides a test method to evaluate the expression and determine its truthiness.
Parameters: - query – A string containing the query to be evaluated
- lazy – If
True
, parse the query the first time it’s tested rather than immediately. This can help with performance if you instantiate a lot of rules and only end up evaluating a small handful.
Writing boolean expressions¶
The grammar supported by boolrule is fairly simple but powerful.
Whitespace¶
Except within string literals, all whitespace is ignored.
Literals¶
Numeric literls are written as bare numbers. Floating point and exponent-based numbers are supported:
10 # int
-10 # int with optional sign
10.5 # float (without optional sign)
10.5E-3 # equivalent to 0.0105
String literls can be single or double quoted:
"Hello, world"
'boolrule rulez"
Boolean literals are the bare values true
and false
None
type is the bare value none
Property paths¶
In order to reference values from the context passed into the test()
method you specify the path to the property as a dot-separated identifier:
foo
foo.bar
foo.bar.baz
At evaluation time, these will map to either object attributes or dict keys in that order.
Basic comparison operators¶
Operator | Description | Example |
---|---|---|
= , == , eq |
Equality | foo == 5 |
!= , !== , ne , ≠ |
Inequality | bar != 5 |
> , gt |
Greater than | foo > 5 |
>= , ge , ≥ |
Greater than or equal to | foo >= 5 |
< , lt |
Less than | foo < 5 |
<= , le , ≤ |
Less than or equal to | foo <= 5 |
is |
Identity | foo is True |
isnot |
Inverse identity | foobar isnot True |
Logical operators¶
Operator | Description | Example |
---|---|---|
and |
Logical and | foo == 5 and bar < 10 |
or |
Logical or | bar == 5 or bar < 10 |
Set operators¶
Operator | Description | Example |
---|---|---|
in , ∈ |
Is a member of | foo in ("a","b","c") |
notin , ∉ |
Is not a member of | foo not in ("a","b") |
⊆ |
Is a subset of | foo ⊆ ("a", "b", "c") |
⊇ |
Is a superset of | foo ⊇ ("a", "b") |
∩ |
Intersects | foo ∩ ("a", "b") |
Contributing¶
Contributions are welcome, and they are greatly appreciated! Every little bit helps, and credit will always be given.
You can contribute in many ways:
Types of Contributions¶
Report Bugs¶
Report bugs at https://github.com/tailsdotcom/boolrule/issues.
If you are reporting a bug, please include:
- Your operating system name and version.
- Any details about your local setup that might be helpful in troubleshooting.
- Detailed steps to reproduce the bug.
Fix Bugs¶
Look through the GitHub issues for bugs. Anything tagged with “bug” and “help wanted” is open to whoever wants to implement it.
Implement Features¶
Look through the GitHub issues for features. Anything tagged with “enhancement” and “help wanted” is open to whoever wants to implement it.
Write Documentation¶
boolrule could always use more documentation, whether as part of the official boolrule docs, in docstrings, or even on the web in blog posts, articles, and such.
Submit Feedback¶
The best way to send feedback is to file an issue at https://github.com/tailsdotcom/boolrule/issues.
If you are proposing a feature:
- Explain in detail how it would work.
- Keep the scope as narrow as possible, to make it easier to implement.
- Remember that this is a volunteer-driven project, and that contributions are welcome :)
Get Started!¶
Ready to contribute? Here’s how to set up boolrule for local development.
Fork the boolrule repo on GitHub.
Clone your fork locally:
$ git clone git@github.com:your_name_here/boolrule.git
Install your local copy into a virtualenv. Assuming you have virtualenvwrapper installed, this is how you set up your fork for local development:
$ mkvirtualenv boolrule $ cd boolrule/ $ python setup.py develop
Create a branch for local development:
$ git checkout -b name-of-your-bugfix-or-feature
Now you can make your changes locally.
When you’re done making changes, check that your changes pass flake8 and the tests, including testing other Python versions with tox:
$ flake8 boolrule tests $ python setup.py test or py.test $ tox
To get flake8 and tox, just pip install them into your virtualenv.
Commit your changes and push your branch to GitHub:
$ git add . $ git commit -m "Your detailed description of your changes." $ git push origin name-of-your-bugfix-or-feature
Submit a pull request through the GitHub website.
Pull Request Guidelines¶
Before you submit a pull request, check that it meets these guidelines:
- The pull request should include tests.
- If the pull request adds functionality, the docs should be updated. Put your new functionality into a function with a docstring, and add the feature to the list in README.rst.
- Check https://github.com/tailsdotcom/boolrule/actions/workflows/ci.yml and make sure that the tests pass for all supported Python versions.
Credits¶
Development Lead¶
- Steve Webster <spjwebster@gmail.com>
History¶
0.3.4 (2021-09-24)¶
- Fixed error caused by early return when evaluating nested expressions.
0.3.3 (2021-07-15)¶
- Upgrade dependencies.
0.3.2 (2020-09-23)¶
- Add Type hinting.
0.3.1 (2020-09-09)¶
- Raise an exception when the whole expression cannot be parsed. Previous behaviour would discard the segment that didn’t match the expression grammar.
0.3.0 (2018-01-15)¶
- Add None type and is/isnot operators (contributed by ocurero)
0.2.0 (2016-10-27)¶
- Fixed error caused by refactor from internal codebase that was preventing deep context level values from being referenced in a substitution value
0.1.2 (2016-09-30)¶
- Improved documentation
0.1.1 (2016-09-30)¶
- Made
context
optional - Improved documentation
0.1.0 (2016-09-30)¶
- First release on PyPI.