1================= 2Development Guide 3================= 4 5This document gives an overview of the code in `boolean.py`, explaining the 6layout and design decisions and some difficult algorithms. All used definitions 7and laws are stated in :doc:`concepts`. 8 9.. contents:: 10 :depth: 2 11 :backlinks: top 12 13Testing 14------- 15 16Test `boolean.py` with your current Python environment: 17 18.. code-block:: shell 19 20 python setup.py test 21 22Test with all of the supported Python environments using `tox`: 23 24.. code-block:: shell 25 26 pip install -r test-requirements.txt 27 tox 28 29If `tox` throws `InterpreterNotFound`, limit it to python interpreters that are actually installed on your machine: 30 31.. code-block:: shell 32 33 tox -e py27,py36 34 35Classes Hierarchy 36----------------- 37.. 38 boolean.boolean.BooleanAlgebra 39 boolean.boolean.Expression 40 boolean.boolean.BaseElement 41 boolean.boolean._TRUE 42 boolean.boolean._FALSE 43 boolean.boolean.Symbol 44 boolean.boolean.Function 45 boolean.boolean.NOT 46 boolean.boolean.DualBase 47 boolean.boolean.AND 48 boolean.boolean.OR 49 50 51 52Expression 53^^^^^^^^^^ 54.. 55 .. autoclass:: boolean.boolean.Expression 56 57Symbol 58^^^^^^ 59.. 60 .. autoclass:: boolean.boolean.Symbol 61 62Function 63^^^^^^^^ 64.. 65 .. autoclass:: boolean.boolean.Function 66 67NOT 68^^^ 69.. 70 .. autoclass:: boolean.boolean.NOT 71 72AND 73^^^ 74.. 75 .. autoclass:: boolean.boolean.AND 76 77OR 78^^ 79.. 80 .. autoclass:: boolean.boolean.OR 81 82 83.. _class-creation: 84 85Class creation 86-------------- 87 88Except for BooleanAlgebra and Symbol, no other classes are is designed to be instantiated directly. 89Instead you should create a BooleanAlgebra instance, then use BooleanAlgebra.symbol, 90BooleanAlgebra.NOT, BooleanAlgebra.AND, BooleanAlgebra.OR BooleanAlgebra.TRUE and BooleanAlgebra.FALSE 91to compose your expressions in the context of this algebra. 92 93 94.. _class-initialization: 95 96Class initialization 97-------------------- 98 99In this section for all classes is stated which arguments they will accept 100and how these arguments are processed before they are used. 101 102Symbol 103^^^^^^ 104 105& :obj:`obj` (Named Symbol) 106 107 108Ordering 109-------- 110 111As far as possible every expression should always be printed in exactly the 112same way. Therefore a strict ordering between different boolean classes and 113between instances of same classes is needed. This is defined primarily by the 114sort_order attribute. 115 116 117Class ordering 118^^^^^^^^^^^^^^ 119 120:class:`BaseElement` < :class:`Symbol` < :class:`AND` < :class:`OR` 121 122:class:`NOT` is an exception in this scheme. It will be sorted based on the sort order of its 123argument. 124 125Class ordering is implemented by an attribute :attr:`sort_order` in all 126relevant classes. It holds an integer that will be used for comparison 127if it is available in both compared objects. 128For Symbols, the attached `obj` object is used instead. 129 130+----------------------+-----------+ 131| :class:`Class` | sort_order| 132+======================+===========+ 133| :class:`BaseElement` | 0 | 134+----------------------+-----------+ 135| :class:`Symbol` | 5 | 136+----------------------+-----------+ 137| :class:`AND` | 10 | 138+----------------------+-----------+ 139| :class:`OR` | 25 | 140+----------------------+-----------+ 141 142Instance ordering 143^^^^^^^^^^^^^^^^^ 144 145:class:`BaseElement` 146 :obj:`FALSE` < :obj:`TRUE` 147 148:class:`Symbol` 149 150 :obj:`Symbol.obj` o :obj:`Symbol.obj` 151 152:class:`NOT` 153 if :obj:`NOT.args[0]` == :obj:`other` ---> :obj:`other` < :obj:`NOT` 154 155 :obj:`NOT` o :obj:`other` ---> :obj:`NOT.args[0]` o :obj:`other` 156 157:class:`AND` 158 :obj:`AND` o :obj:`AND` ---> :obj:`AND.args[0]` o :obj:`AND.args[0]` 159 160 if undecided: repeat for all args 161 162 if undecided: len(:obj:`AND.args`) o len(:obj:`AND.args`) 163 164 if undecided: return :obj:`AND` < :obj:`AND` 165 166:class:`OR` 167 :obj:`OR` o :obj:`OR` ---> :obj:`OR.args[0]` o :obj:`OR.args[0]` 168 169 if undecided: repeat for all args 170 171 if undecided: len(:obj:`OR.args`) o len(:obj:`OR.args`) 172 173 if undecided: return :obj:`OR` < :obj:`OR` 174 175 176Parsing 177------- 178 179Parsing is done in two steps: 180A tokenizer iterates over string characters assigning a TOKEN_TYPE to each token. 181The parser receives this stream of token types and strings and creates 182adequate boolean objects from a parse tree. 183 184