Development Guide

This document gives an overview of the code in boolean.py, explaining the layout and design decisions and some difficult algorithms. All used definitions and laws are stated in Concepts and Definitions.

Testing

Test boolean.py with your current Python environment:

python setup.py test

Test with all of the supported Python environments using tox:

pip install -r test-requirements.txt
tox

If tox throws InterpreterNotFound, limit it to python interpreters that are actually installed on your machine:

tox -e py27,py36

Classes Hierarchy

Expression

Symbol

Function

NOT

AND

OR

Class creation

Except for BooleanAlgebra and Symbol, no other classes are is designed to be instantiated directly. Instead you should create a BooleanAlgebra instance, then use BooleanAlgebra.symbol, BooleanAlgebra.NOT, BooleanAlgebra.AND, BooleanAlgebra.OR BooleanAlgebra.TRUE and BooleanAlgebra.FALSE to compose your expressions in the context of this algebra.

Class initialization

In this section for all classes is stated which arguments they will accept and how these arguments are processed before they are used.

Symbol

& obj (Named Symbol)

Ordering

As far as possible every expression should always be printed in exactly the same way. Therefore a strict ordering between different boolean classes and between instances of same classes is needed. This is defined primarily by the sort_order attribute.

Class ordering

BaseElement < Symbol < AND < OR

NOT is an exception in this scheme. It will be sorted based on the sort order of its argument.

Class ordering is implemented by an attribute sort_order in all relevant classes. It holds an integer that will be used for comparison if it is available in both compared objects. For Symbols, the attached obj object is used instead.

Class sort_order
BaseElement 0
Symbol 5
AND 10
OR 25

Instance ordering

BaseElement
FALSE < TRUE

Symbol

Symbol.obj o Symbol.obj
NOT

if NOT.args[0] == other —> other < NOT

NOT o other —> NOT.args[0] o other

AND

AND o AND —> AND.args[0] o AND.args[0]

if undecided: repeat for all args

if undecided: len(AND.args) o len(AND.args)

if undecided: return AND < AND

OR

OR o OR —> OR.args[0] o OR.args[0]

if undecided: repeat for all args

if undecided: len(OR.args) o len(OR.args)

if undecided: return OR < OR

Parsing

Parsing is done in two steps: A tokenizer iterates over string characters assigning a TOKEN_TYPE to each token. The parser receives this stream of token types and strings and creates adequate boolean objects from a parse tree.