diff --git a/doc/sphinx/Makefile b/doc/sphinx/Makefile
new file mode 100644
index 0000000..d0c3cbf
--- /dev/null
+++ b/doc/sphinx/Makefile
@@ -0,0 +1,20 @@
+# Minimal makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line, and also
+# from the environment for the first two.
+SPHINXOPTS ?=
+SPHINXBUILD ?= sphinx-build
+SOURCEDIR = source
+BUILDDIR = build
+
+# Put it first so that "make" without argument is like "make help".
+help:
+ @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+
+.PHONY: help Makefile
+
+# Catch-all target: route all unknown targets to Sphinx using the new
+# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
+%: Makefile
+ @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
diff --git a/doc/sphinx/make.bat b/doc/sphinx/make.bat
new file mode 100644
index 0000000..9534b01
--- /dev/null
+++ b/doc/sphinx/make.bat
@@ -0,0 +1,35 @@
+@ECHO OFF
+
+pushd %~dp0
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+ set SPHINXBUILD=sphinx-build
+)
+set SOURCEDIR=source
+set BUILDDIR=build
+
+if "%1" == "" goto help
+
+%SPHINXBUILD% >NUL 2>NUL
+if errorlevel 9009 (
+ echo.
+ echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
+ echo.installed, then set the SPHINXBUILD environment variable to point
+ echo.to the full path of the 'sphinx-build' executable. Alternatively you
+ echo.may add the Sphinx directory to PATH.
+ echo.
+ echo.If you don't have Sphinx installed, grab it from
+ echo.http://sphinx-doc.org/
+ exit /b 1
+)
+
+%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
+goto end
+
+:help
+%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
+
+:end
+popd
diff --git a/doc/sphinx/source/PyCon2008-paper.rst b/doc/sphinx/source/PyCon2008-paper.rst
new file mode 100644
index 0000000..1037e18
--- /dev/null
+++ b/doc/sphinx/source/PyCon2008-paper.rst
@@ -0,0 +1,598 @@
+.. $Id: PyCon2008-paper.txt 057d79259b20 2009-05-14 mtnyogi $
+..
+.. Copyright © 2008 Bruce Frederiksen
+..
+.. Permission is hereby granted, free of charge, to any person obtaining a copy
+.. of this software and associated documentation files (the "Software"), to deal
+.. in the Software without restriction, including without limitation the rights
+.. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+.. copies of the Software, and to permit persons to whom the Software is
+.. furnished to do so, subject to the following conditions:
+..
+.. The above copyright notice and this permission notice shall be included in
+.. all copies or substantial portions of the Software.
+..
+.. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+.. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+.. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+.. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+.. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+.. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+.. THE SOFTWARE.
+
+=========================================================================
+Applying Expert System Technology to Code Reuse with Pyke
+=========================================================================
+-----------------------------
+PyCon 2008, Chicago
+-----------------------------
+
+.. |bullet| unicode:: U+02022
+.. |copy| unicode:: U+000A9
+
+:Author: Bruce Frederiksen
+:Date: Fri, 14 Mar 2008
+:Web: pyke.sourceforge.net
+:Copyright: |copy| 2008, Bruce Frederiksen
+
+Abstract
+=========
+
+This paper explores a new approach to code reuse using a backward-chaining
+rule-based system, similar to prolog, to generate a function call graph *before*
+the functions are called. This is compared with current solutions which build
+the call graph *as* the functions are called.
+
+This approach is introduced through an open source project called Pyke (Python
+Knowledge Engine).
+
+Finally, the initial results show that the utility of this approach far
+exceeds expectations; leading to something more akin to automatic
+programming rather than adaptable libraries. A call for help is given to
+explore the capabilities of this approach across different domains.
+
+.. contents::
+
+The Thinking that Led to Pyke
+=============================
+
+The Need for Code Reuse
+~~~~~~~~~~~~~~~~~~~~~~~
+
+At one of my contracting jobs, they had many clients running essentially the
+same program, but each client needed minor code modifications. Their objective
+was to maximize code reuse.
+
+What is Code Reuse?
+~~~~~~~~~~~~~~~~~~~~~
+
+The first question is what does "code reuse" mean? And the answer that seems
+most logical is *function* reuse. Where code modifications are required, a
+new function can be created incorporating those modifications.
+
+Then the remaining task is to bring the proper collection of functions
+together for each client.
+
+This gets more complicated as several versions of many functions will be
+produced for various clients that are all available for reuse by the next
+client. So it's not simply the case that there will be one standard default
+version of each function, and then several one-off customized versions that
+each only apply to a single client.
+
+The result of this function combination exercise is a function call graph.
+
+Example 1
+---------
+
+Let us imagine that we start out with two functions for client1:
+
+ .. image:: images/PyCon2008/client1.png
+ :scale: 60
+
+And then client2 comes along.
+
+Let us first suppose that we need a new version of function A, but can reuse
+function B\ :sub:`1`:
+
+ .. image:: images/PyCon2008/client2b.png
+ :scale: 60
+
+This is easy in any programming language and leads naturally to the idea that
+the functions to reuse are the lower-level ones, which can be placed into
+libraries.
+
+But now let us suppose the opposite; that we need a new version of function B,
+but can reuse function A\ :sub:`1`:
+
+ .. image:: images/PyCon2008/client2d.png
+ :scale: 60
+
+This is where we need help.
+
+Current Solutions
+---------------------
+
+The current solutions are all run-time solutions that trap the call from
+function A\ :sub:`1` to some function B and figure out which function B to use
+when the call is made. For example:
+
+* O-O Dynamic Binding
+* Zope Adapters
+* Generic Functions
+
+Current Solution Limitations
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+These solutions are all limited for the same reason. Let's look at another
+example to see why.
+
+Example 2
+----------
+
+Real world programs have many more than two functions, but we can start to see
+the limitations of the current solutions by looking at a three function
+example.
+
+We start with one client and three functions.
+
+When client2 was added, it could only share function A\ :sub:`1` and had to
+have a new B (B\ :sub:`2`) that needs a new function with a different call
+interface than C, so we'll call it D\ :sub:`1`.
+
+Then along comes client3. This time things are looking up, because all we
+need is a new version of function D:
+
+ .. image:: images/PyCon2008/client3d.png
+ :scale: 60
+
+Now let's see what happens when we want to call the program for client3. We
+know we need to start with function A\ :sub:`1`, since there is only version of
+function A:
+
+ .. image:: images/PyCon2008/client3e.png
+ :scale: 60
+
+But at this point we have two choices for function B. All we know for client3
+is that we're supposed to use function D\ :sub:`2`, so we're left to guess about
+function B. So we try the first one, function B\ :sub:`1`:
+
+ .. image:: images/PyCon2008/client3f2.png
+ :scale: 60
+
+It's not until function B\ :sub:`1` tries to call some function C that we
+discover a problem.
+
+This is where the current solutions break down.
+
+Certainly for this example, it is easy to imagine a developer telling the
+binding system: oh yea and client3 is going to have to use function B\ :sub:`2`
+as well. But more realistic call graphs are much more complicated than this;
+so the developer would have to specify which functions to use going back many
+levels.
+
+And then when there is a change in these upper level shared functions later on,
+it will affect the call graphs for many clients.
+
+So the current solutions don't scale well.
+
+Continuing on with our example; what we need to do at this point is back up
+and try the other B function:
+
+ .. image:: images/PyCon2008/client3g.png
+ :scale: 60
+
+After doing this, we discover the solution for the final call graph:
+
+ .. image:: images/PyCon2008/client3h.png
+ :scale: 60
+
+What's Needed
+-------------------
+
+By looking at this example, we discover two things about how to solve
+this problem:
+
+#. Do function selection **prior** to calling any of the functions.
+
+ We can't wait until one function calls another to figure out what to do,
+ because we may change our minds!
+
+#. Use a standard backward-chaining rule-based algorithm.
+
+ The process of first trying function B\ :sub:`1`, then backing up and trying
+ function B\ :sub:`2` is exactly the process used in backward-chaining
+ rule-based systems like prolog. They call it *backtracking*.
+
+Applying Backward-Chaining to Code Reuse
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The next question is how do we use a backward-chaining system to produce
+function call graphs?
+
+Let's examine, conceptually, what a set of backward-chaining rules would look
+like to find a solution to this problem. Then we can determine how to turn
+this into a function call graph.
+
+The following diagram shows *goals* as dotted line boxes around the *rules*
+that prove that goal. In this example, some goals only have one rule and some
+have two.
+
+We also see how *rules* link to other *goals*. For example, rule ``Use B1`` and
+rule ``Use B2`` both prove the same goal: ``Find B``. But ``Use B1`` links to
+the ``Find C`` goal, while ``Use B2`` links to ``Find D``.
+
+ .. image:: images/PyCon2008/bc_rules2.png
+ :scale: 60
+
+Now we can follow how these rules would be run by the knowledge engine:
+
+* The whole process is kicked off by asking the knowledge engine for a
+ solution to ``Find A``.
+* There is only one rule for ``Find A``: ``Use A1``, so the knowledge engine
+ tries this rule.
+* ``Use A1`` needs a solution to ``Find B``.
+* The knowledge engine tries the first rule for ``Find B``: ``Use B1``.
+* ``Use B1`` needs a solution to ``Find C``.
+* The knowledge engine tries the only rule for ``Find C``:
+ ``Use C1``, which fails for client3!
+
+The situation now looks like:
+
+ .. image:: images/PyCon2008/bc_rules5.png
+ :scale: 60
+
+Continuing on:
+
+* Since there are no other rules for ``Find C``, the ``Find C`` goal fails.
+* Which means that the ``Use B1`` rule fails.
+* So the knowledge engine tries the next rule for ``Find B``: ``Use B2``.
+* ``Use B2`` needs a solution for ``Find D``.
+* The knowledge engine tries the first rule for ``Find D``: ``Use D1``,
+ which fails for client3.
+* The knowledge engine tries the next rule for ``Find D``: ``Use D2``,
+ which succeeds for client3!
+* The ``Find D`` goal succeeds.
+* The ``Find B`` goal succeeds.
+* And the ``Find A`` goal succeeds.
+
+When we achieve final success, we have the following situation:
+
+ .. image:: images/PyCon2008/bc_rules8.png
+ :scale: 60
+
+What remains is to translate this into a function call graph.
+
+It becomes obvious that we want to attach our python functions directly to the
+backward-chaining rules:
+
+ .. image:: images/PyCon2008/bc_rules9.png
+ :scale: 60
+
+Pyke
+=====
+
+Pyke KRB Syntax
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+How does all of this look in Pyke?
+
+Pyke has its own language for rules, which it compiles into python source
+modules and then imports. This gives a performance boost by circumventing
+nearly all of the inference engine interpretation logic. It also makes it
+very easy to embed short python code snippets directly within the rules to
+help out with the inferencing. This keeps the inference mechanism simpler as
+it does not have to deal with things that are already easy in a procedural
+language (like arithmetic and simple list manipulation).
+
+The Pyke rule source files are called *knowledge rule bases* and have a
+``.krb`` suffix.
+
+We'll continue with the previous example here.
+
+First, let's look at the rules before we attach the python functions.
+Here's three of the rules::
+
+ use_B2
+ use find_B($client)
+ when
+ check_function($client, B, 2)
+ find_D($client)
+
+ use_D1
+ use find_D($client)
+ when
+ check_function($client, D, 1)
+
+ use_D2
+ use find_D($client)
+ when
+ check_function($client, D, 2)
+
+Note that Pyke uses a ``$`` to indicate pattern variables (anonymous pattern
+variables start with ``$_``).
+
+The ``check_function`` goal checks to see what version of the indicated
+function should be used for this client. If this is the incorrect version,
+it fails. If there is no indication for this function, it succeeds to
+allow guessing.
+
+Attaching Python Functions to Backward-Chaining Rules
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Here are the last two rules with the python code added. The rules have the
+python function attached to them so that the function can be returned from
+the goal as an additional parameter. Because this parameter does not affect
+the inferencing process, it is a hidden parameter.
+
+These examples just show one line of python code, but you may have as many
+lines as you want::
+
+ use_D1
+ use find_D($client)
+ when
+ check_function($client, D, 1)
+ with
+ print "D1"
+
+ use_D2
+ use find_D($client)
+ when
+ check_function($client, D, 2)
+ with
+ print "D2"
+
+Pyke calls the function call graphs *plans*. This terms applies to both the
+final top-level call graph, as well as intermediate call graphs.
+
+Calling Subordinate Plans
+---------------------------
+
+Now we do the same thing to add python code to the ``use_B2`` rule::
+
+ use_B2
+ use find_B($client)
+ when
+ check_function($client, B, 2)
+ find_D($client)
+ with
+ print "B2"
+
+We have code for the B\ :sub:`2` function, but how does it call the plan
+returned from the ``find_D`` goal?
+
+The most common way is::
+
+ use_B2
+ use find_B($client)
+ when
+ check_function($client, B, 2)
+ find_D($client)
+ $$()
+ with
+ print "B2"
+
+In general, there may be many goals in the ``when`` clause that produce plans.
+Each would have an indented line of python code under it with ``$$``
+indicating the subordinate function. These indented lines are combined with
+the lines in the ``with`` clause to form the complete python function for this
+rule (with the differences in indenting levels corrected).
+
+But in this case, this would mean that ``print "Dx"`` would be executed before
+``print "B2"``, which seems backwards.
+
+To call the subordinate plan within the ``with`` clause, there is an alternate
+mechanism::
+
+ use_B2
+ use find_B($client)
+ when
+ check_function($client, B, 2)
+ find_D($client) as $d
+ with
+ print "B2"
+ $d()
+
+The ``as $d`` clause stores the plan function in pattern variable ``$d`` rather
+than adding a call to it to the ``with`` clause. Then you can decide in the
+``with`` clause whether to call it, when to call it, how many times to call it,
+etc.
+
+Note that pattern variables in general can be used within the python code.
+These are replaced by their final bound values (as constants) after the
+top-level goal has been proven. Thus, the rules can also be used to determine
+and set constant values within the plan functions to further customize the
+code. This is the reason that the code for the attached python functions is
+placed directly in the .krb file rather than in a separate python module.
+
+Some Final Points about Plans
+------------------------------
+
+* Function parameters are specified at the end of the ``use`` clause with an
+ optional ``taking`` clause::
+
+ use_B2
+ use find_B($client) taking (a, b = None)
+ ...
+
+* A completed plan appears as a normal python function.
+* Plans may be pickled and reused.
+
+ * If you add functools.partial to copy_reg.
+
+* You don't need to import all of Pyke to unpickle and run a plan.
+
+ * Only one small Pyke module is needed.
+
+Other Capabilities
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+* Pyke also supports forward-chaining rules::
+
+ fc_rule_name
+ foreach
+ fact_base_name.fact_name(pattern...)
+ ...
+ assert
+ fact_base_name.fact_name(pattern...)
+ ...
+
+ * Pyke runs all of the forward-chaining rules whose ``foreach`` clause
+ succeeds prior to running any backward-chaining rules. Thus,
+ forward-chaining rules can not call backward-chaining rules and vice versa.
+ But backward-chaining rules *can* examine facts asserted by
+ forward-chaining rules.
+
+* There are different kinds of knowledge bases:
+
+ * Fact Bases:
+
+ * simply store facts.
+
+ * Rule Bases:
+
+ * store both forward-chaining and backward-chaining rules.
+ * can use rule base inheritance to inherit, and build upon, the rules from
+ another rule base.
+
+ * But only single inheritance.
+ * Thus each rule base has a unique root rule base.
+ * All rule bases that share the same root form a *rule base category*.
+
+ * allow selection of which rule base(s) to use through rule base
+ *activation*.
+
+ * But only one rule base per rule base category may be active at one time.
+
+ * Extensibility. You can write your own knowledge bases. These might:
+
+ * look up facts in a database
+ * ask users questions
+ * probe hardware/software settings
+
+Initial Results
+================================
+
+After writing Pyke's younger brother, it occurred to me that backward-chaining
+could be used to automatically figure out how to join database tables together
+and generate SQL statements.
+
+And if the backward-chaining rules could see which substitution variables are
+needed by an HTML templating system, it could automatically generate the SQL
+to get these data and build the code to update the template.
+
+It seemed that it would no longer be necessary to include anything that
+looks like code in the HTML templates. The graphic designers could just add
+simple attributes to their tags and the backward-chaining system would figure
+out the rest. This would mean that the programmers don't need to modify the
+HTML templates, and the graphic designers could maintain full ownership of
+the HTML.
+
+I had a WSGI front-end that would simply assert the data passed to it as facts.
+
+The forward-chaining rules took these starting facts, parsed the cookie
+information, form information, browser information, and url, determined whether
+the user was logged in, figured out which client the request was for,
+established all of this as additional facts and activated the appropriate rule
+base for this client.
+
+Then the WSGI front-end simply asked for a proof of the ``process()`` goal and
+executed the resulting plan function which returned the final HTTP status codes
+and HTML document.
+
+For a page retrieval (vs. form action), the ``process`` goal used two sub-goals:
+
+#. A ``format_retrieval`` goal that read the HTML template, and built a plan
+ to render the template, given the needed data. This goal also returned a
+ simple descriptor of this needed data as part of its inferencing.
+#. A ``retrieve`` goal then took that descriptor of the needed data, built
+ the necessary SQL statements, and cooked them into a plan to execute those
+ statements and return the needed data as a simple dictionary.
+
+Then the two sub plans were combined in the reverse order, to first retrieve
+the data and then populate the template, for the final plan that went back to
+the WSGI front-end.
+
+The Pyke examples/sqlgen and examples/web_framework are simplified examples
+that you can look at.
+
+Now, as it turned out, the company had been running without a president for
+quite awhile, and had finally hired a new president.
+
+So just as I finished the SQL generation logic to handle unique data (vs.
+multi-row data) and was preparing to show some demonstrations; our new
+president, coming from a java background and apparently never having heard of
+python, decided to cancel the project.
+
+End of contract!
+
+Code Reuse through Automatic Programming
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The fundamental lesson learned was that this technique ends up being far more
+capable than what I had first imagined.
+
+More than producing adaptable libraries capable of using B\ :sub:`1` or
+B\ :sub:`2` at some point in their call graphs, this approach leads to
+something more akin to the back-end of a compiler -- except that the compiler
+front-end does not target a textual language that needs to be written and
+parsed; but is rather a simple observer of already known facts:
+
+ Show me your schema, and I'll build your SQL statements.
+
+ Show me your HTML templates, and I'll build the code to populate them for you.
+
+This seems to change the whole concept of *code reuse*; elevating it from the
+realm of static *libraries*, to the realm of dynamic *automatic programming*.
+
+Going Forward
+===============
+
+Thinking that others might find this useful, I've re-implemented the underlying
+knowledge engine from scratch, with numerous improvements gained from the
+experience of the first attempt, and made it open source.
+
+With the backward-chaining rule base system, many applications are possible:
+
+* Complicated decision making applications.
+* Compiler back-ends.
+
+ * The .krb compiler uses Pyke.
+
+* Automatic SQL statement generation.
+* Automatic HTML generation/template processing.
+* The control module for a web framework tool.
+* Incorporate new custom functions into a large set
+ of standard functions, which may change the
+ selection or configuration of standard functions
+ in other parts of the program.
+* Automatically re-distribute the modules of a system
+ over different programs and computers to meet a
+ wide range of performance and capacity goals.
+* Diagnosis systems.
+
+ * E.g., Automated customer service systems.
+
+* Program or library customization for specific uses.
+* Instantiate, configure, and interconnect networks of objects to meet a
+ specific need or situation.
+
+Up to this point, I've been flying solo. For this project to move forward
+to fully explore its capabilities, I'm going to need help!
+
+I'd like to see several early adopters run with this and try it out in different
+domains. Pyke is in alpha status now and is ready to start to lean on.
+
+.. raw:: html
+
+
+
+
+
+
+This paper is licensed under a `Creative Commons Attribution 3.0 Unported
+License`__.
+
+.. __: http://creativecommons.org/licenses/by/3.0/
+
+
diff --git a/doc/sphinx/source/about_pyke/cooking_functions.rst b/doc/sphinx/source/about_pyke/cooking_functions.rst
new file mode 100644
index 0000000..fe46c78
--- /dev/null
+++ b/doc/sphinx/source/about_pyke/cooking_functions.rst
@@ -0,0 +1,160 @@
+.. $Id: cooking_functions.txt abb78effaba9 2009-03-25 mtnyogi $
+..
+.. Copyright © 2008 Bruce Frederiksen
+..
+.. Permission is hereby granted, free of charge, to any person obtaining a copy
+.. of this software and associated documentation files (the "Software"), to deal
+.. in the Software without restriction, including without limitation the rights
+.. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+.. copies of the Software, and to permit persons to whom the Software is
+.. furnished to do so, subject to the following conditions:
+..
+.. The above copyright notice and this permission notice shall be included in
+.. all copies or substantial portions of the Software.
+..
+.. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+.. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+.. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+.. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+.. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+.. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+.. THE SOFTWARE.
+
+===========================
+Cooking Python Functions
+===========================
+
+"Cooking" a Python function means customizing it. And you customize it by
+cooking certain parameter values into it as constant values.
+
+Cooking a single parameter value
+================================
+
+First you define the function that you want to cook with an extra parameter
+at the start:
+
+ >>> def foo(cooked, standard):
+ ... print("foo called with cooked: %s, standard: %s" %
+ ... (cooked, standard))
+
+Now you can call this function with two parameters:
+
+ >>> foo('a', 'b')
+ foo called with cooked: a, standard: b
+
+But your real intention is that it appear to be a function taking one
+parameter, with the first parameter cooked in.
+
+This is done with the ``partial`` class of the functools_ module in the
+standard Python library.
+
+ >>> from functools import partial
+
+And then using ``partial`` to cook the first parameter:
+
+ >>> cooked1 = partial(foo, 'cooked_value1')
+
+Now ``cooked_foo`` is a function that takes one parameter:
+
+ >>> cooked1('value1')
+ foo called with cooked: cooked_value1, standard: value1
+ >>> cooked1('value2')
+ foo called with cooked: cooked_value1, standard: value2
+
+And you can make other cooked functions from foo with other cooked values:
+
+ >>> cooked2 = partial(foo, 'cooked_value2')
+ >>> cooked2('value1')
+ foo called with cooked: cooked_value2, standard: value1
+ >>> cooked2('value2')
+ foo called with cooked: cooked_value2, standard: value2
+
+And you can still use the first cooked function, so now you have two functions
+for the price of one!
+
+ >>> cooked1('value3')
+ foo called with cooked: cooked_value1, standard: value3
+ >>> cooked1('value4')
+ foo called with cooked: cooked_value1, standard: value4
+ >>> cooked2('value5')
+ foo called with cooked: cooked_value2, standard: value5
+ >>> cooked2('value6')
+ foo called with cooked: cooked_value2, standard: value6
+
+And you can keep going with this to make as many functions as you care to
+from your single starting function.
+
+Cooking a Function Call Graph
+=============================
+
+This same technique can be used to cook a function call graph, by making the
+subordinate function a cooked parameter:
+
+ >>> def bar(child_fun, a):
+ ... print("bar called with:", a)
+ ... return child_fun(a)
+
+And now you can cook which function ``bar`` calls the same way you cook any
+other parameter:
+
+ >>> bar_float = partial(bar, float)
+ >>> bar_float('123')
+ bar called with: 123
+ 123.0
+ >>> bar_min = partial(bar, min)
+ >>> bar_min((3,2,5))
+ bar called with: (3, 2, 5)
+ 2
+
+And, of course, you can use cooked functions as these subordinate functions
+too:
+
+ >>> bar_cooked1 = partial(bar, cooked1)
+ >>> bar_cooked1('abc')
+ bar called with: abc
+ foo called with cooked: cooked_value1, standard: abc
+
+Which means that you can create function call graphs to any depth:
+
+ >>> bar_bar_min = partial(bar, bar_min)
+ >>> bar_bar_min((3,2,5))
+ bar called with: (3, 2, 5)
+ bar called with: (3, 2, 5)
+ 2
+
+Cooking Several Parameters
+==========================
+
+In general, you may want to cook several values for each function. Some of
+these values may specify which subordinate functions to call, others may just
+fix certain constant values for the function.
+
+Pyke does this using a single extra parameter called ``context``, which is a
+read-only dictionary. It can then prepare this dictionary with as many values
+as it needs and then cook the whole dictionary into the function using
+``partial``.
+
+Pyke translates each individual access to a cooked parameter into a dictionary
+lookup on ``context`` that looks up that parameter name::
+
+ context['parameter_name']
+
+The Need for Pyke
+=================
+
+Now that you understand how Pyke cooks Python functions, you should be able
+to understand how this technique can achieve the "order of magnitude"
+improvements to Adaptability/Customization, Performance and Code Reuse
+discussed on the `About Pyke`_ page.
+
+You should also now see the need for a tool like Pyke to assemble all of
+these functions to fit specific situations and use cases.
+
+.. note::
+ Pyke calls a customized function call graph a *plan*. Plans_ are explained
+ later, after you've been introduced to `Logic Programming in Pyke`_.
+
+And, finally, you should start to get a sense for how "programming in the
+large" with Pyke dovetails with "programming in the small" with Python.
+
+
diff --git a/doc/sphinx/source/about_pyke/index.rst b/doc/sphinx/source/about_pyke/index.rst
new file mode 100644
index 0000000..f7c7137
--- /dev/null
+++ b/doc/sphinx/source/about_pyke/index.rst
@@ -0,0 +1,144 @@
+.. $Id: index.txt f00035e4dab4 2009-11-02 mtnyogi $
+..
+.. Copyright © 2008 Bruce Frederiksen
+..
+.. Permission is hereby granted, free of charge, to any person obtaining a copy
+.. of this software and associated documentation files (the "Software"), to deal
+.. in the Software without restriction, including without limitation the rights
+.. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+.. copies of the Software, and to permit persons to whom the Software is
+.. furnished to do so, subject to the following conditions:
+..
+.. The above copyright notice and this permission notice shall be included in
+.. all copies or substantial portions of the Software.
+..
+.. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+.. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+.. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+.. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+.. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+.. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+.. THE SOFTWARE.
+
+.. toctree::
+ :maxdepth: 1
+ :hidden:
+
+ cooking_functions
+ what_is_pyke
+ steps_to_using_pyke
+ installing_pyke
+ modifying_pyke
+
+============
+About Pyke
+============
+-------------------------
+What Does Pyke Do for Me?
+-------------------------
+
+Pyke was primarily designed to allow you to "cook" your Python_ code. You
+write Python code, and then you write Pyke code to cook that Python
+code -- i.e. to assemble the Python functions that you've written and
+customize them for a specific situation or use-case.
+
+Pyke can also be used for difficult decision making applications where each
+part of the problem has multiple possible solutions and the selection of a
+solution to one part of the problem affects whether another part of the problem
+can be solved or not.
+
+
+Cooking Your Python Code
+========================
+
+Cooking your Python code is a form of meta-programming, or writing programs
+that manipulate other programs. I.e., it's a means of `programming in the
+large`_.
+
+Thus, Pyke provides a way to directly "program in the large", which dovetails
+with using Python to "program in the small". Pyke supplements but does not
+replace Python!
+
+Pyke helps programmers to achieve order of magnitude improvements in:
+
+- Adaptability/Customization
+
+ - Using Pyke allows your Python code to be combined into thousands of
+ different configurations.
+
+ - Thus, your application or library takes on the characteristics of a
+ Domain Specific Language to achieve an order of magnitude increase in
+ adaptability without a corresponding increase in your program's "surface
+ area" to your users.
+
+- Performance
+
+ - Thinking of your application or library as a Domain Specific Language
+ (DSL), you're using Pyke to "compile" rather than "interpret" your DSL to
+ achieve an order of magnitude improvement in performance.
+
+- Code Reuse
+
+ - Making your code an order of magnitude more adaptable and an order of
+ magnitude faster allows it to be (re)used in a correspondingly broader
+ range of situations.
+
+
+Examples of Cooking Python Code
+===============================
+
+Database Access Library
+-----------------------
+
+You're writing a library package to make it easier for Python programmers to
+access relational databases. You write Python code that deals with the
+mechanics of accessing relational databases, and then you write Pyke code to
+make a cooked version of this code for each database access with your user's
+application.
+
+You might also use Pyke to provide help installing and configuring the
+database and help creating the schema.
+
+By taking this approach, your library will be an order of magnitude faster
+than competing database access libraries because you've used Pyke to
+essentially compile custom code for each database access.
+
+The sqlgen_ example demonstrates this approach.
+
+
+HTML Templating Library
+-----------------------
+
+Or you're writing an HTML templating package to make it easier for Python
+programmers to generate HTML. You write Python code that deals with the
+mechanics of HTML, and then you write Pyke code to make a cooked version of
+this code for each HTML template.
+
+By taking this approach, your library will be an order of magnitude faster
+than competing HTML templating libraries because you've used Pyke to
+essentially compile custom code for each HTML template.
+
+The web_framework_ example demonstrates this approach. It uses the sqlgen_
+example to make a little web framework. The 2 HTML templates in this example
+were also done in `TurboGears 2`_ and then a siege_ benchmark test done on
+both:
+
+- TurboGears 2 ran 75.83 transactions/sec
+- The Pyke example ran 791.01 transactions/sec
+
+
+Linux Configuration Program
+---------------------------
+
+Or you're writing a new Linux configuration program. You write the Python
+code to query and set the various system configuration options, and then you
+write Pyke code to ask the user what he wants and build a cooked version of
+your code to make the necessary changes.
+
+In this case, you're not looking for performance. You use Pyke to handle the
+complicated decision making and use its plan_ facility to postpone making any
+configuration changes until your program is sure that it's "dotted all of the
+i's and crossed all the t's".
+
+
+
diff --git a/doc/sphinx/source/about_pyke/installing_pyke.rst b/doc/sphinx/source/about_pyke/installing_pyke.rst
new file mode 100644
index 0000000..aefcc12
--- /dev/null
+++ b/doc/sphinx/source/about_pyke/installing_pyke.rst
@@ -0,0 +1,186 @@
+.. $Id: installing_pyke.txt 70f7f9ee163a 2010-03-11 mtnyogi $
+..
+.. Copyright © 2007-2009 Bruce Frederiksen
+..
+.. Permission is hereby granted, free of charge, to any person obtaining a copy
+.. of this software and associated documentation files (the "Software"), to deal
+.. in the Software without restriction, including without limitation the rights
+.. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+.. copies of the Software, and to permit persons to whom the Software is
+.. furnished to do so, subject to the following conditions:
+..
+.. The above copyright notice and this permission notice shall be included in
+.. all copies or substantial portions of the Software.
+..
+.. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+.. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+.. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+.. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+.. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+.. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+.. THE SOFTWARE.
+
+===================================
+Installing Pyke
+===================================
+
+Index to This Page
+=======================
+
+* Licensing_
+* `System Requirements`_
+
+ * `Other Required Packages`_
+
+* Installation_
+* `Run the Examples`_
+* `Viewing the HTML Documentation`_
+* `Repository Directory Structure`_
+
+
+Licensing
+================
+
+This software is licensed under the MIT license::
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+
+
+System Requirements
+====================
+
+Pyke is 100% Python, so it should run on any platform supported by Python.
+So all you'll need is `Python`_ 2.5, 2.6 or 3.1.
+
+Other Required Packages
+-----------------------
+
+No other packages are required to develop, run and distribute an application
+using Pyke. But there are package requirements to do the following additional
+things:
+
+.. table::
+ :class: table-offset
+
+ +--------------------------------+------------------+------------------+
+ | If you want to | you also need | minimum version |
+ +================================+==================+==================+
+ | run the web_framework example | HTMLTemplate_ | 1.5 |
+ +--------------------------------+------------------+------------------+
+ | run the unit tests | `doctest-tools`_ | 1.0a3 |
+ +--------------------------------+------------------+------------------+
+ | rebuild the html documentation | rest2web_ | 0.5 |
+ + +------------------+------------------+
+ | | docutils_ | 0.4.1 |
+ +--------------------------------+------------------+------------------+
+
+If the docutils package is not part of your standard Python installation,
+there is probably a package for it in the package index for your Linux
+distribution.
+
+All of the other packages can be installed as the administrator using
+pip_ or easy_install_. For example::
+
+ # pip install HTMLTemplate
+
+
+Installation
+============
+
+The source code for the latest release can be found on the `Pyke project
+download page`_ as ``pyke-.zip`` (for Python2) and
+``pyke3-.zip`` (for Python3). After unzipping these, go into the
+directory and run::
+
+ $ python setup.py build
+
+And then as administrator, run::
+
+ # python setup.py install
+
+The sources include a complete copy of the project directory, including the
+documentation, unit tests, and examples.
+
+If you want to clone the source code repository to contribute to the project
+development, or to use the latest developer version, read `Modifying Pyke`_.
+
+Run the Examples
+================
+
+There are several examples that are contained in the source directory. Each
+example is in it's own subdirectory under the ``examples`` subdirectory, and
+each has it's own README.txt file that explains how to run it.
+
+The web_framework example requires the HTMLTemplate_ package, version 1.5 or
+later. This can be installed as administrator with pip or easy_install::
+
+ # pip install HTMLTemplate
+
+See also Examples_.
+
+Viewing the HTML Documentation
+==============================
+
+This HTML documentation may be viewed directly from your hard drive. The HTML
+files are in the ``doc/html`` directory. Start with ``doc/html/index.html``.
+
+
+Repository Directory Structure
+==============================
+
+You'll see the following directories.
+
+* ``doc``
+
+ - the ``html`` directory has all of the HTML documentation ready to browse
+ off of your hard drive. Start with doc/html/index.html.
+ - the ``source`` directory has all of the sources that were used to
+ generated the HTML documentation. See `Rebuilding the HTML Documentation`_.
+ - the ``examples`` directory just has a copy of the examples used by the
+ .txt files in the ``source`` directory so that the doctests will work on
+ the ``source`` directory. You should be able to skip this unless you
+ change an example in one of the ``source`` files.
+ - ``cheatsheets`` are a collection of text files with notes on various tools
+ used by Pyke, and processes used to maintain Pyke.
+
+* ``examples``
+
+ - There are several examples. Start with *family_relations*. Look at the
+ ``README.txt`` file for each example to see how to run it. See also,
+ Examples_.
+
+* ``experimental``
+
+ - This is a catch-all directory for various ideas that have been tried, but
+ that have not been incorporated into Pyke. You can safely skip over this
+ directory...
+
+* ``pyke``
+
+ - This is the top-level Python package directory for the Python sources.
+ This needs to be installed into a directory on your ``PYTHONPATH``.
+ The sources for the compilers are in the ``krb_compiler`` subdirectory,
+ which is expected to be a subpackage of ``pyke``.
+
+* ``Test``
+
+ - This is where the unit test scripts are stored. These use Python's
+ doctest_ package. Each test file has a .tst suffix.
+ - See `Running Unit Tests`_.
+
diff --git a/doc/sphinx/source/about_pyke/modifying_pyke.rst b/doc/sphinx/source/about_pyke/modifying_pyke.rst
new file mode 100644
index 0000000..f995d9c
--- /dev/null
+++ b/doc/sphinx/source/about_pyke/modifying_pyke.rst
@@ -0,0 +1,283 @@
+.. $Id: modifying_pyke.txt 70f7f9ee163a 2010-03-11 mtnyogi $
+..
+.. Copyright © 2009 Bruce Frederiksen
+..
+.. Permission is hereby granted, free of charge, to any person obtaining a copy
+.. of this software and associated documentation files (the "Software"), to deal
+.. in the Software without restriction, including without limitation the rights
+.. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+.. copies of the Software, and to permit persons to whom the Software is
+.. furnished to do so, subject to the following conditions:
+..
+.. The above copyright notice and this permission notice shall be included in
+.. all copies or substantial portions of the Software.
+..
+.. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+.. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+.. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+.. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+.. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+.. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+.. THE SOFTWARE.
+
+===================================
+Modifying Pyke
+===================================
+
+Index to This Page
+=======================
+
+* `Mercurial Repositories`_
+
+ * `Mercurial Keyword Extension`_
+ * `Which Repository Do I Use?`_
+
+* `Compiling PLY Tables Files`_
+* `Compiling the Compiler.krb File`_
+* `Running Unit Tests`_
+* `Rebuilding the HTML Documentation`_
+
+
+Mercurial Repositories
+======================
+
+With Mercurial_, you clone the entire repository locally on your computer.
+Then you can make changes and commit those changes to your local repository.
+If you think those changes might be interesting to everybody, make your local
+repository (or a clone of it) publicly available (either on your own server,
+or on one of the `Mercurial Hosting Sites`_) and send me an email. I will
+pull your changes, examine them, and push them to the master repository on
+sourceforge.
+
+Mercurial Keyword Extension
+---------------------------
+
+The Pyke sources use the Mercurial `Keyword Extension`_ as a holdover from
+when the repository used Subversion rather than Mercurial.
+
+The ``hgrc_keywords`` file has been provided to enable and configure this
+extension for Pyke use. You can append this file to either your personal
+.hgrc configuration file (which would then apply to all of your Mercurial
+projects) or the project .hg/hgrc file (see `hgrc`_ in the Mercurial wiki).
+
+If you use a ``post-clone`` `Mercurial hook`_, or append ``hgrc_keywords``
+manually after cloning, the keywords won't be expanded properly when the
+project is first cloned. But they will be expanded properly if the clone is
+done with the -U option and then an ``hg update`` done in the newly cloned
+repository (after the changes to .hg/hgrc have been made).
+
+The keyword expansions are only used by the tools that generate the html
+documentation (see `Rebuilding the HTML Documentation`_, below).
+
+Which Repository Do I Use?
+--------------------------
+
+Normally, you will clone one of the following four repositories locally to
+make a master copy of what's on sourceforge. Then you would clone your master
+copy (which is very fast) to make separate clones for each development task
+that you are working on for Pyke.
+
+So it is best to keep all of these clones together in a common directory.
+
+There are four repositories on sourceforge that you can start with:
+
+release_1
+ Use this for bug fixes, code and documentation cleanup, and anything else
+ that would go into a point release for release 1. I merge the changes made
+ here into all of the other repositories. So this code goes into both the
+ Python2.x and Python3.x versions of Pyke.
+
+pyke
+ Use this for major new features that would result in a major new release
+ (e.g., release 1.2). I merge the changes made in release_1 into the pyke
+ repository (but maybe not the other way around). And I merge the changes
+ made in the pyke repository into the pre_2to3 repository. So the code here
+ goes into both the Python2.x and Python3.x future versions of Pyke.
+
+pre_2to3_r1
+ Use this for bug fixes, code and documentation cleanup, and anything else
+ that would go into a point release for release 1, but only apply to the
+ Python3.x version of Pyke. I merge the changes made in release_1 into the
+ pre_2to3_r1 repository (but not the other way around). And I merge the
+ changes made in the pre_2to3_r1 repository into the pre_2to3 repository.
+ So changes here only go into the next point release of the Python3.x version
+ of Pyke.
+
+ .. warning::
+ This code is maintained in a state just prior to running Python's
+ 2to3_ tool on it. So you can't just run the code here directly.
+
+ The ``run_2to3`` script runs 2to3 on the current copy of the sources. Do
+ **not** run this in a repository clone that you still want to use to do
+ commits! Instead, commit all of your changes, then clone the repository
+ and do ``run_2to3`` in the clone. If anything doesn't work, go back to
+ the first repository to fix it, delete the clone, and repeat the whole
+ process. This was done to minimize merge conflicts caused by the 2to3
+ changes.
+
+ The ``run_pre_test`` script will:
+
+ * clone the current repository
+ * then in the clone do:
+
+ * ``run_2to3``
+ * ``testpyke`` -3.1
+ * python setup.py -q sdist --formats zip
+ * insert '3' after 'pyke' in the name of the source distribution zip
+ file.
+
+ ``Run_pre_test`` assumes that you either have the keywording options set
+ in your personal .hgrc file, or have clone hooks in place to copy these
+ into the .hg/hgrc file of all clones within your pyke work area. See
+ `Mercurial Keyword Extension`_, above.
+
+pre_2to3
+ Normally I merge changes from the pyke repository and the pre_2to3_r1
+ repository into pre_2to3 so that nothing needs to be done in this repository.
+ Most major new features would be developed in the ``pyke`` repository and
+ merged into pre_2to3. Making changes to pre_2to3 directly would only be
+ done when those changes are for major new features that only apply to the
+ Python3.x version of Pyke.
+
+So, for example, if you wanted to work on the ``release_1`` repository, you
+would::
+
+ $ mkdir pyke_repos
+ $ cd pyke_repos
+ $ hg clone -U http://pyke.hg.sourceforge.net:8000/hgroot/pyke/release_1 master
+ $ hg clone master task_1
+ $ cd task_1
+
+.. note::
+ This assumes that you've added the `hgrc_keywords`_ file to your ~/.hgrc
+ file. See `Mercurial Keyword Extension`_, above.
+
+
+Compiling PLY Tables Files
+==========================
+
+Pyke uses PLY_ (Python Lex and Yacc) as it's parser generator. PLY compiles
+the Pyke grammars into a set of three tables files:
+
+- kfbparser_tables.py (from kfbparser.py)
+- krbparser_tables.py (from krbparser.py)
+- scanner_tables.py (from scanner.py)
+
+A copy of PLY is included in the source directory (pyke/krb_compiler/ply) so
+that there there can be no version mismatch between the version of PLY used to
+compile these tables files and the version of PLY installed on your machine.
+
+To regenerate these tables files, at the top-level source directory::
+
+ $ python
+ >>> from pyke.krb_compiler import kfbparser, krbparser, scanner
+ >>> scanner.init(scanner, 0, True)
+ >>> krbparser.init(krbparser, True)
+ >>> kfbparser.init(kfbparser, True)
+
+or just run the "testall.py" program from the doctest-tools package::
+
+ $ cd pyke/krb_compiler
+ $ testall.py
+
+
+Compiling the Compiler.krb File
+===============================
+
+Pyke uses itself to compile your `rule base`_ sources (`.krb`_ files) into
+Python source (``.py``) files.
+
+The knowledge base file that Pyke uses for this is
+pyke/krb_compiler/compiler.krb. This gets compiled into compiler_bc.py, which
+is stored in the source code repository.
+
+.. this code is hidden and will create the pyke/krb_compiler/compiled_krb
+ directory, if needed, for the code section following:
+ >>> import os, os.path
+ >>> os.chdir('../../..')
+ >>> root='pyke/krb_compiler'
+ >>> dir=root + '/compiled_krb'
+ >>> os.path.isdir(root)
+ True
+ >>> if not os.path.isdir(dir): os.mkdir(dir)
+
+To recompile the compiler_bc.py file, from the top-level source directory::
+
+ $ mkdir pyke/krb_compiler/compiled_krb
+ $ python
+ >>> from pyke import krb_compiler
+ >>> krb_compiler.compile_krb('compiler', 'pyke.krb_compiler.compiled_krb',
+ ... 'pyke/krb_compiler/compiled_krb',
+ ... 'pyke/krb_compiler/compiler.krb')
+ ['compiler_bc.py']
+
+ $ mv pyke/krb_compiler/compiled_krb/compiler_bc.py pyke/krb_compiler
+
+.. this code is also hidden and deletes the
+ pyke/krb_compiler/compiled_krb/compiler_bc.py file and
+ pyke/krb_compiler/compiled_krb directory created above.
+ >>> os.path.isdir(root)
+ True
+ >>> os.remove(dir + '/compiler_bc.py')
+ >>> os.rmdir(dir)
+
+Running Unit Tests
+==================
+
+The `doctest-tools`_ package is required to run the unit tests (see
+`Other Required Packages`_ for more details).
+
+The ``testall.py`` and ``testdoc.py`` scripts from ``doctest-tools`` can be run
+anywhere.
+
+In addition, the top-level directory contains a ``testpyke`` script that will
+delete all of the compiled_krb directories, then run ``testall.py`` twice. The
+first run must recompile all of the `knowledge base`_ sources (`.krb`_,
+`.kfb`_ and `.kqb`_ files) into the compiled_krb directories in order to run
+the tests. The second run reuses the files compiled in the first run. This
+makes sure that all of the tests run properly whether they have to compile the
+knowledge base sources or not.
+
+
+Rebuilding the HTML Documentation
+=================================
+
+The ``doc/html`` directory contains all of the documents that you are reading
+now. These are ready to browse directly from your hard drive if you'd like.
+
+The documentation is generated using the rest2web_ package, which uses
+docutils_ (see `Other Required Packages`_ for more details).
+
+The sources for the documentation are in ``doc/source``. Each .txt file there
+is converted into an .html file in the doc/html directory by running::
+
+ $ cd doc/source
+ $ bin/gen_html
+
+This takes about 9 seconds. It:
+
+#. Temporarily appends hyperlink references onto all of the \*.txt files.
+#. Runs ``r2w`` to regenerate the files in ``doc/html``
+
+ - except for those in ``doc/html/stylesheets`` and ``doc/html/images``.
+
+#. Strips all of the hyperlink references from the \*.txt files.
+#. Creates a new sitemap.xml file with all of the dates that the files were
+ last modified.
+
+.. note::
+ This process uses the date information expanded by the Mercurial `Keyword
+ Extension`_. See `Mercurial Keyword Extension`_, above.
+
+I've gone ahead and placed the generated html files in the source repository
+so that you can browse the documentation locally without having to run
+``bin/gen_html``. So you only need these procedures if you change the
+documentation (i.e., change the .txt files in doc/source).
+
+To test all of the code examples in the documents, use the ``testall.py``
+command from the `doctest-tools`_ package::
+
+ $ cd doc/source
+ $ testall.py
+
+
diff --git a/doc/sphinx/source/about_pyke/steps_to_using_pyke.rst b/doc/sphinx/source/about_pyke/steps_to_using_pyke.rst
new file mode 100644
index 0000000..0b725c3
--- /dev/null
+++ b/doc/sphinx/source/about_pyke/steps_to_using_pyke.rst
@@ -0,0 +1,87 @@
+.. $Id: steps_to_using_pyke.txt a2119c07028f 2008-10-27 mtnyogi $
+..
+.. Copyright © 2007-2008 Bruce Frederiksen
+..
+.. Permission is hereby granted, free of charge, to any person obtaining a copy
+.. of this software and associated documentation files (the "Software"), to deal
+.. in the Software without restriction, including without limitation the rights
+.. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+.. copies of the Software, and to permit persons to whom the Software is
+.. furnished to do so, subject to the following conditions:
+..
+.. The above copyright notice and this permission notice shall be included in
+.. all copies or substantial portions of the Software.
+..
+.. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+.. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+.. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+.. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+.. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+.. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+.. THE SOFTWARE.
+
+====================
+Steps to Using Pyke
+====================
+
+#. You provide the following to Pyke's `knowledge engine`_:
+
+ - A set of universally true statements_.
+
+ - These statements are true for all time.
+
+ - The text for all questions_ that you might want Pyke to ask your end user.
+ - Multiple sets of rules_.
+
+ - Your rules may include both `forward-chaining`_ and
+ `backward-chaining`_ rules.
+
+#. Repeat for each specific use case:
+
+ #. You provide a set of statements_ describing this specific use case to
+ Pyke.
+
+ #. You select which set of rules apply to this use case.
+
+ #. Pyke automatically runs all of the selected forward-chaining rules that
+ apply to the statements that you've given to it to deduce new statements.
+
+ - Your forward-chaining rules may interactively ask your end user
+ `questions`_, or get information by executing `commands`_ (programs)
+ on the computer that it's running on to help in its decision
+ making.
+
+ #. You ask Pyke a question by having it prove_ a goal_ (which is just
+ another statement). This goal may include `pattern variables`_ that
+ allow you to ask "for what values is this statement true?".
+
+ - Pyke runs the selected backward-chaining rules against the statements
+ that it has in order to figure out the answer to your question.
+
+ - Your backward-chaining rules may also ask your end user questions_ and
+ run commands_.
+
+ - You may have written Python code at the end of some of your
+ backward-chaining rules. For each such rule, Pyke has compiled this
+ Python code into a Python function called a plan_ which it has attached
+ to the rule.
+
+ - Once Pyke finds an answer to your question, it gathers all of the plan
+ functions of the rules that it used to find your answer into a
+ complete function call graph. The plan functions are linked together
+ mirroring the way that the rules were linked together to find your
+ answer. In this way, you can write high-level compilers that assemble
+ together and configure a set of Python functions to solve specific
+ problems.
+
+ - Pyke returns the top Python function of this function call graph as a
+ standard Python function along with the answer to your question. You
+ may call this function as may times as you like. You may also pickle_
+ the function so that you can send it to another program or save it to
+ disk. You only need one small Pyke module to load and run these
+ pickles.
+
+ #. You reset_ Pyke to clear out all of these case specific statements and
+ prepare it for the next use case.
+
+
diff --git a/doc/sphinx/source/about_pyke/what_is_pyke.rst b/doc/sphinx/source/about_pyke/what_is_pyke.rst
new file mode 100644
index 0000000..b24d210
--- /dev/null
+++ b/doc/sphinx/source/about_pyke/what_is_pyke.rst
@@ -0,0 +1,99 @@
+.. $Id: what_is_pyke.txt a2119c07028f 2008-10-27 mtnyogi $
+..
+.. Copyright © 2007-2008 Bruce Frederiksen
+..
+.. Permission is hereby granted, free of charge, to any person obtaining a copy
+.. of this software and associated documentation files (the "Software"), to deal
+.. in the Software without restriction, including without limitation the rights
+.. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+.. copies of the Software, and to permit persons to whom the Software is
+.. furnished to do so, subject to the following conditions:
+..
+.. The above copyright notice and this permission notice shall be included in
+.. all copies or substantial portions of the Software.
+..
+.. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+.. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+.. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+.. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+.. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+.. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+.. THE SOFTWARE.
+
+=============================
+What is Pyke?
+=============================
+
+Pyke integrates a form of `Logic Programming`_ into Python by providing a
+knowledge engine that can:
+
+- Do both forward-chaining (data driven) and
+ backward-chaining (goal directed) inferencing.
+
+ - Pyke may be embedded into any Python program.
+
+- Automatically generate Python programs by assembling individual Python
+ functions into complete call graphs.
+
+ - This is done through a unique design where the individual Python
+ functions are attached to backward-chaining rules.
+ - Unlike other approaches to code reuse (e.g. Object-oriented programming,
+ Zope adapters, generic functions), this allows the inference engine to
+ ensure that all of the function's requirements are completely satisfied,
+ by examining the entire call graph down to the leaves, before **any** of
+ the functions are executed.
+ - This is an optional feature. You don't need to use it if you just
+ want the inferencing capability by itself.
+
+The Knowledge Engine Supports:
+========================================
+
+- Multiple *fact bases*, each with its own list of facts.
+- Both *forward-chaining* rules and *backward-chaining* rules.
+- Multiple *rule bases*, each with its own list of forward-chaining
+ and/or backward-chaining rules.
+- Rule base inheritance -- *activating* the derived rule base
+ includes the rules from the parent rule base.
+- The inference rules are compiled into Python functions, allowing
+ Python code snippets to be used within the rules.
+ This greatly enhances the expressiveness of the rules.
+
+Automatic Program Generation:
+========================================
+
+- Calls the generated Python programs *plans*.
+- Plans may be run multiple times without needing to rerun the inference
+ rules.
+- Plans may be pickled and cached to disk to be used by other programs or
+ in later runs of the same program.
+- Only one small Pyke module is required to run the plans.
+
+Potential Pyke Applications:
+========================================
+
+- Complicated decision making applications.
+- The back-end (code generation and optimization) of compilers.
+ Pyke is used as the back-end of its own
+ compiler that translates rules into Python code.
+- Automatic SQL statement generation.
+- Automatic HTML generation and automatic HTML template processing.
+- Automatic program builder to reuse a common set of functions for many
+ different specific situations. This could also easily
+ incorporate a new custom function into a much larger program, where the use
+ of the custom function might influence the choice of other standard
+ functions in other parts of the program.
+- The control module for a web framework tool.
+- A high-level planner to automatically distribute the
+ modules of a large system over several computers in a distributed system
+ to meet specific performance and capacity goals. This could be used to
+ automatically scale the same system code from a small one program,
+ one computer system
+ to much larger distributed systems to meet a wide range of performance
+ goals.
+- Diagnosis systems, including automated customer service systems.
+- Program or library customization for specific uses.
+- In addition to being able to build programs, Pyke can instantiate,
+ configure and interconnect a network of objects to meet a specific need
+ or situation.
+
+
diff --git a/doc/sphinx/source/conf.py b/doc/sphinx/source/conf.py
new file mode 100644
index 0000000..462b1e9
--- /dev/null
+++ b/doc/sphinx/source/conf.py
@@ -0,0 +1,75 @@
+# Configuration file for the Sphinx documentation builder.
+#
+# This file only contains a selection of the most common options. For a full
+# list see the documentation:
+# https://www.sphinx-doc.org/en/master/usage/configuration.html
+
+# -- Path setup --------------------------------------------------------------
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#
+import os
+# import sys
+# sys.path.insert(0, os.path.abspath('.'))
+
+
+# -- Project information -----------------------------------------------------
+
+project = 'PyKE'
+copyright = '2007-2021, Bruce Frederiksen'
+author = 'Bruce Frederiksen'
+
+
+# -- General configuration ---------------------------------------------------
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+extensions = [
+]
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+# This pattern also affects html_static_path and html_extra_path.
+exclude_patterns = ['_build', 'links.rst']
+
+
+# -- Options for HTML output -------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+#
+html_theme = 'sphinxdoc'
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# -- Custom behaviour
+
+
+def fix_ref(ref, html_dir):
+ """Fixes a reference prepending it with a relative path (if necessary)
+ """
+ # Is it either another link or an external page?
+ if ref.rstrip()[-1] == '_' or ref.startswith('http://'):
+ return ref
+ else:
+ return os.path.join(html_dir, ref)
+
+
+source_dir = os.path.dirname(os.path.relpath(__file__, 'pyke/doc/sphinx/'))
+html_dir = os.path.join(source_dir, '../build/html')
+
+# Example from https://stackoverflow.com/a/61694897
+rst_epilog = ""
+with open('links.rst') as f:
+ for line in f:
+ link, ref = line.split(':', 1)
+ rst_epilog += link + ": " + fix_ref(ref, html_dir)
diff --git a/doc/sphinx/source/copyright_license b/doc/sphinx/source/copyright_license
new file mode 100644
index 0000000..d1785c0
--- /dev/null
+++ b/doc/sphinx/source/copyright_license
@@ -0,0 +1,22 @@
+.. $Id: copyright_license 05a128b38e5d 2007-11-08 mtnyogi $
+..
+.. Copyright © 2007 Bruce Frederiksen
+..
+.. Permission is hereby granted, free of charge, to any person obtaining a copy
+.. of this software and associated documentation files (the "Software"), to deal
+.. in the Software without restriction, including without limitation the rights
+.. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+.. copies of the Software, and to permit persons to whom the Software is
+.. furnished to do so, subject to the following conditions:
+..
+.. The above copyright notice and this permission notice shall be included in
+.. all copies or substantial portions of the Software.
+..
+.. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+.. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+.. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+.. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+.. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+.. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+.. THE SOFTWARE.
+
diff --git a/doc/sphinx/source/examples.rst b/doc/sphinx/source/examples.rst
new file mode 100644
index 0000000..40ddf06
--- /dev/null
+++ b/doc/sphinx/source/examples.rst
@@ -0,0 +1,164 @@
+.. $Id: examples.txt 6de8ee4e7d2d 2010-03-29 mtnyogi $
+..
+.. Copyright © 2008 Bruce Frederiksen
+..
+.. Permission is hereby granted, free of charge, to any person obtaining a copy
+.. of this software and associated documentation files (the "Software"), to deal
+.. in the Software without restriction, including without limitation the rights
+.. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+.. copies of the Software, and to permit persons to whom the Software is
+.. furnished to do so, subject to the following conditions:
+..
+.. The above copyright notice and this permission notice shall be included in
+.. all copies or substantial portions of the Software.
+..
+.. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+.. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+.. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+.. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+.. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+.. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+.. THE SOFTWARE.
+
+
+========
+Examples
+========
+
+.. this code is hidden and will change to the root directory and add '' to
+ sys.path for the code section following:
+ >>> import sys
+ >>> if '' not in sys.path: sys.path.insert(0, '')
+ >>> import os
+ >>> os.chdir("../..") # get out of documents directory back to root dir
+ >>> os.chdir("examples/towers_of_hanoi")
+
+Several examples are included to help you become familiar with Pyke. These
+are all in an ``examples`` directory::
+
+ $ cd examples/towers_of_hanoi
+ $ python
+ >>> import driver
+ >>> driver.test(2)
+ got 1: ((0, 1), (0, 2), (1, 2))
+ got 2: ((0, 2), (0, 1), (2, 0), (1, 2), (0, 2))
+
+Each example is in its own sub-directory and has a README.txt file to get you
+started. They all have `.krb files`_ and a Python module to run the example
+that also demonstrates `how to call Pyke`_ from your Python program.
+
+
+Family_relations
+================
+
+This is a very good basic example to start with.
+
+The family_relations example takes an initial set of facts_ about people
+(stated in a `.kfb file`_)::
+
+ son_of(david_r2, david_r, sarah_r)
+ daughter_of(shirley, david_r, sarah_r)
+
+And figures out how any two people are related::
+
+ david_r2, shirley are ('brother', 'sister')
+
+This same problem is solved in four different ways so that you can compare
+them:
+
+- Forward-chaining_ only
+- Backward-chaining_ only
+- Backward-chaining only with a few rule optimizations that make the rules
+ run 100 times faster!
+- A mix of forward-chaining and backward-chaining with some use of plans_ added
+ too.
+
+The driver.py program also demonstrates how to use krb_traceback_ and the
+print_stats_ function.
+
+
+Knapsack
+========
+
+At the `PyCon 2008`_ conference, somebody asked about the `knapsack problem`_.
+We found a solution in Prolog here__ (starting on page 19), and rewrote it in
+Pyke. This is a quick simple little example.
+
+.. __: http://www.ise.gmu.edu/~duminda/classes/fall03/set3.ppt
+
+
+Sqlgen
+======
+
+Pyke was originally developed as the control component for a web framework.
+This example shows how Pyke can automatically generate SQL SELECT statements,
+given a set of tables that the calling program has keys to and a tuple of the
+desired column names. Column names specified at the top-level in this tuple
+are expected to have a single value each. Nested tuples are used when
+multiple rows are expected. The column names in nested tuples make up the
+columns in the result rows.
+
+The top-level goal returns a plan_ that takes the key values for the initial
+set of tables given to the goal and returns an immutable dictionary mapping
+the column names to the values retrieved from the database. The plan may be
+used repeatedly without re-running the rules each time to figure out the
+SELECT statements. Thus, this acts like a SELECT statement compiler resulting
+in queries with virtually no extra overhead. It is *not*, however, an Object
+Relational Mapper (ORM).
+
+The data model used for the requested columns is that tables inherit the
+columns from tables they link to. So if there is a 1-many relationship
+between tables A and B (1 A row has many B rows), the B table inherits the
+columns from the A table through it's link to table A. The Pyke rules will
+automatically figure out the table joins for this.
+
+The program automatically introspects the schema information. For this
+example, it assumes that ``id`` is the primary key for each table, and that
+when one table links to another, it uses the target table name suffixed with
+``_id`` as the column name.
+
+This example was originally done using MySQL_ and includes the .sql files to
+create the database, tables, and example data. The example has since been
+converted to use the Sqlite3 database to make it easier to run, as Sqlite3
+does not require any setup (the Sqlite3 database file is included in the
+example).
+
+Sqlgen lacks more general capabilities that would be required for real use,
+but may serve as a starting point for another project that's more complete.
+
+This example also has much more elaborate rules than the prior two examples
+and is a very real example of generating plans_.
+
+
+Web_framework
+=============
+
+This example completes the Python web framework demo by adding rules to
+automatically generate code to render HTML templates from the HTMLTemplate_
+package (you can run ``pip install HTMLTemplate`` or ``easy_install
+HTMLTemplate`` to install the HTMLTemplate package). This example uses the
+sqlgen_ example, above, to generate the SQL statements.
+
+An HTMLTemplate does not include anything resembling program code in it, so
+that your graphics designers can completely own the html files without the
+developers having to modify them in any way.
+
+Note that the code generated here is fully cooked_ code, custom built for
+that specific schema and HTML template. This runs extremely fast because
+there is nothing left at run-time concerning parsing and figuring out the
+HTML template, or constructing the SQL statements.
+
+A test was done comparing this web framework example to the same example
+done in `TurboGears 2`_ running against the same MySQL database. The results
+of the siege_ benchmark tests show that Pyke is just over 10 times faster than
+TurboGears 2::
+
+- Pyke: 791 trans/sec
+- TurboGears 2: 76 trans/sec
+
+The demo is packaged as a WSGI_ application. It also demonstrates the use of
+multiple `rule bases`_ by using the sqlgen example above, as well as the
+caching and reuse of plans_ to achieve the order of magnitude improvement in
+performance over current practice.
+
+
diff --git a/doc/sphinx/source/images/PyCon2008/bc_rules2.png b/doc/sphinx/source/images/PyCon2008/bc_rules2.png
new file mode 100644
index 0000000..787494c
Binary files /dev/null and b/doc/sphinx/source/images/PyCon2008/bc_rules2.png differ
diff --git a/doc/sphinx/source/images/PyCon2008/bc_rules5.png b/doc/sphinx/source/images/PyCon2008/bc_rules5.png
new file mode 100644
index 0000000..88ee096
Binary files /dev/null and b/doc/sphinx/source/images/PyCon2008/bc_rules5.png differ
diff --git a/doc/sphinx/source/images/PyCon2008/bc_rules8.png b/doc/sphinx/source/images/PyCon2008/bc_rules8.png
new file mode 100644
index 0000000..2706ff0
Binary files /dev/null and b/doc/sphinx/source/images/PyCon2008/bc_rules8.png differ
diff --git a/doc/sphinx/source/images/PyCon2008/bc_rules9.png b/doc/sphinx/source/images/PyCon2008/bc_rules9.png
new file mode 100644
index 0000000..32e30c0
Binary files /dev/null and b/doc/sphinx/source/images/PyCon2008/bc_rules9.png differ
diff --git a/doc/sphinx/source/images/PyCon2008/client1.png b/doc/sphinx/source/images/PyCon2008/client1.png
new file mode 100644
index 0000000..7cbd169
Binary files /dev/null and b/doc/sphinx/source/images/PyCon2008/client1.png differ
diff --git a/doc/sphinx/source/images/PyCon2008/client2b.png b/doc/sphinx/source/images/PyCon2008/client2b.png
new file mode 100644
index 0000000..405d9f8
Binary files /dev/null and b/doc/sphinx/source/images/PyCon2008/client2b.png differ
diff --git a/doc/sphinx/source/images/PyCon2008/client2d.png b/doc/sphinx/source/images/PyCon2008/client2d.png
new file mode 100644
index 0000000..27c4f52
Binary files /dev/null and b/doc/sphinx/source/images/PyCon2008/client2d.png differ
diff --git a/doc/sphinx/source/images/PyCon2008/client3d.png b/doc/sphinx/source/images/PyCon2008/client3d.png
new file mode 100644
index 0000000..4d0d0f5
Binary files /dev/null and b/doc/sphinx/source/images/PyCon2008/client3d.png differ
diff --git a/doc/sphinx/source/images/PyCon2008/client3e.png b/doc/sphinx/source/images/PyCon2008/client3e.png
new file mode 100644
index 0000000..95228e0
Binary files /dev/null and b/doc/sphinx/source/images/PyCon2008/client3e.png differ
diff --git a/doc/sphinx/source/images/PyCon2008/client3f2.png b/doc/sphinx/source/images/PyCon2008/client3f2.png
new file mode 100644
index 0000000..a846cdf
Binary files /dev/null and b/doc/sphinx/source/images/PyCon2008/client3f2.png differ
diff --git a/doc/sphinx/source/images/PyCon2008/client3g.png b/doc/sphinx/source/images/PyCon2008/client3g.png
new file mode 100644
index 0000000..b690ac5
Binary files /dev/null and b/doc/sphinx/source/images/PyCon2008/client3g.png differ
diff --git a/doc/sphinx/source/images/PyCon2008/client3h.png b/doc/sphinx/source/images/PyCon2008/client3h.png
new file mode 100644
index 0000000..a37e65e
Binary files /dev/null and b/doc/sphinx/source/images/PyCon2008/client3h.png differ
diff --git a/doc/sphinx/source/images/backtracking.dia b/doc/sphinx/source/images/backtracking.dia
new file mode 100644
index 0000000..dcb439c
Binary files /dev/null and b/doc/sphinx/source/images/backtracking.dia differ
diff --git a/doc/sphinx/source/images/backtracking.png b/doc/sphinx/source/images/backtracking.png
new file mode 100644
index 0000000..410b3df
Binary files /dev/null and b/doc/sphinx/source/images/backtracking.png differ
diff --git a/doc/sphinx/source/images/bc_backtracking.dia b/doc/sphinx/source/images/bc_backtracking.dia
new file mode 100644
index 0000000..1c78bbe
Binary files /dev/null and b/doc/sphinx/source/images/bc_backtracking.dia differ
diff --git a/doc/sphinx/source/images/bc_backtracking.png b/doc/sphinx/source/images/bc_backtracking.png
new file mode 100644
index 0000000..de55603
Binary files /dev/null and b/doc/sphinx/source/images/bc_backtracking.png differ
diff --git a/doc/sphinx/source/images/bc_rules.dia b/doc/sphinx/source/images/bc_rules.dia
new file mode 100644
index 0000000..c3928ce
Binary files /dev/null and b/doc/sphinx/source/images/bc_rules.dia differ
diff --git a/doc/sphinx/source/images/bc_rules.png b/doc/sphinx/source/images/bc_rules.png
new file mode 100644
index 0000000..ded9412
Binary files /dev/null and b/doc/sphinx/source/images/bc_rules.png differ
diff --git a/doc/sphinx/source/images/header.gif b/doc/sphinx/source/images/header.gif
new file mode 100644
index 0000000..38eebbf
Binary files /dev/null and b/doc/sphinx/source/images/header.gif differ
diff --git a/doc/sphinx/source/images/plan1.dia b/doc/sphinx/source/images/plan1.dia
new file mode 100644
index 0000000..c3038f2
Binary files /dev/null and b/doc/sphinx/source/images/plan1.dia differ
diff --git a/doc/sphinx/source/images/plan1.png b/doc/sphinx/source/images/plan1.png
new file mode 100644
index 0000000..1ee9ea6
Binary files /dev/null and b/doc/sphinx/source/images/plan1.png differ
diff --git a/doc/sphinx/source/images/plan2.dia b/doc/sphinx/source/images/plan2.dia
new file mode 100644
index 0000000..4179f3b
Binary files /dev/null and b/doc/sphinx/source/images/plan2.dia differ
diff --git a/doc/sphinx/source/images/plan2.png b/doc/sphinx/source/images/plan2.png
new file mode 100644
index 0000000..23001ae
Binary files /dev/null and b/doc/sphinx/source/images/plan2.png differ
diff --git a/doc/sphinx/source/images/plan3.dia b/doc/sphinx/source/images/plan3.dia
new file mode 100644
index 0000000..6077389
Binary files /dev/null and b/doc/sphinx/source/images/plan3.dia differ
diff --git a/doc/sphinx/source/images/plan3.png b/doc/sphinx/source/images/plan3.png
new file mode 100644
index 0000000..d668243
Binary files /dev/null and b/doc/sphinx/source/images/plan3.png differ
diff --git a/doc/sphinx/source/images/rule_base_categories.dia b/doc/sphinx/source/images/rule_base_categories.dia
new file mode 100644
index 0000000..bfae3bc
Binary files /dev/null and b/doc/sphinx/source/images/rule_base_categories.dia differ
diff --git a/doc/sphinx/source/images/rule_base_categories.png b/doc/sphinx/source/images/rule_base_categories.png
new file mode 100644
index 0000000..8a2704f
Binary files /dev/null and b/doc/sphinx/source/images/rule_base_categories.png differ
diff --git a/doc/sphinx/source/index.rst b/doc/sphinx/source/index.rst
new file mode 100644
index 0000000..9be6569
--- /dev/null
+++ b/doc/sphinx/source/index.rst
@@ -0,0 +1,100 @@
+.. $Id: index.txt 7e7a566ccb5b 2010-03-04 mtnyogi $
+..
+.. Copyright © 2007-2009 Bruce Frederiksen
+..
+.. Permission is hereby granted, free of charge, to any person obtaining a copy
+.. of this software and associated documentation files (the "Software"), to deal
+.. in the Software without restriction, including without limitation the rights
+.. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+.. copies of the Software, and to permit persons to whom the Software is
+.. furnished to do so, subject to the following conditions:
+..
+.. The above copyright notice and this permission notice shall be included in
+.. all copies or substantial portions of the Software.
+..
+.. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+.. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+.. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+.. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+.. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+.. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+.. THE SOFTWARE.
+
+.. toctree::
+ :maxdepth: 1
+ :hidden:
+ :titlesonly:
+
+ about_pyke/index
+ logic_programming/index
+ knowledge_bases/index
+ pyke_syntax/index
+ using_pyke/index
+ examples
+ PyCon2008-paper
+
+=============================
+Welcome to Pyke
+=============================
+-----------------------------
+Release 1.1
+-----------------------------
+
+Pyke introduces a form of `Logic Programming`_ (inspired by Prolog_) to the
+Python community by providing a knowledge-based inference engine (expert
+system) written in 100% Python.
+
+Unlike Prolog, Pyke integrates with Python allowing you to invoke Pyke from
+Python and intermingle Python statements and expressions within your expert
+system rules.
+
+Pyke was developed to significantly raise the bar on code reuse. Here's how
+it works:
+
+#. You write a set of Python functions, and a set of Pyke rules__ to direct the
+ configuration and combination of these functions.
+#. These functions refer to Pyke `pattern variables`_ within the function body.
+#. Pyke may instantiate each of your functions multiple times, providing a
+ different set of constant values for each of the pattern variables used
+ within the function body. Each of these instances appears as a different
+ function.
+#. Pyke then automatically assembles these customized functions into a
+ complete program (function call graph) to meet a specific need or use case.
+ Pyke calls this function call graph a plan_.
+
+.. __: `backward-chaining rule lp`_
+
+In this way, Pyke provides a way to radically customize and adapt your Python
+code for a specific purpose or use case.
+
+Doing this essentially makes Pyke a very high-level compiler. And taking
+this approach also produces dramatic increases in performance.
+
+And Pyke is very successful at this, providing order of magnitude improvements
+in:
+
+- Code adaptability (or customization),
+- Code reuse and
+- Performance
+
+Pyke does not replace Python, nor is meant to compete with Python. Python is
+an excellent general purpose programming language, that allows you to "program
+in the small".
+
+Pyke builds upon Python by also giving you tools to directly `program in the
+large`_.
+
+Oh, and Pyke uses Logic Programming to do all of this. So if you're interested
+in Logic Programming or Expert Systems, well Pyke has that too...
+
+Pyke on Google Groups
+=====================
+
+Please join Pyke_ on Google Groups for questions and discussion!
+
+FAQ
+===
+
+There is also an FAQ_ list on the sourceforge wiki_, to make it easy to
+contribute.
+
diff --git a/doc/sphinx/source/knowledge_bases/fact_bases.rst b/doc/sphinx/source/knowledge_bases/fact_bases.rst
new file mode 100644
index 0000000..180f85f
--- /dev/null
+++ b/doc/sphinx/source/knowledge_bases/fact_bases.rst
@@ -0,0 +1,78 @@
+.. $Id: fact_bases.txt a2119c07028f 2008-10-27 mtnyogi $
+..
+.. Copyright © 2007-2008 Bruce Frederiksen
+..
+.. Permission is hereby granted, free of charge, to any person obtaining a copy
+.. of this software and associated documentation files (the "Software"), to deal
+.. in the Software without restriction, including without limitation the rights
+.. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+.. copies of the Software, and to permit persons to whom the Software is
+.. furnished to do so, subject to the following conditions:
+..
+.. The above copyright notice and this permission notice shall be included in
+.. all copies or substantial portions of the Software.
+..
+.. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+.. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+.. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+.. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+.. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+.. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+.. THE SOFTWARE.
+
+==========
+Fact Bases
+==========
+
+When statements of fact are stored in Pyke, they are stored in *fact bases*.
+Pyke allows you to have as many fact bases as you like to help you organize
+your facts. The fact bases are created automatically, as needed, as new facts
+are asserted.
+
+Facts
+=====
+
+Think of a fact as a simple statement_. It has a name and a set of
+arguments. The arguments may be:
+
+- strings
+
+ - proper identifiers don't need quotes: ``Fred`` is the same as ``'Fred'``
+
+- numbers
+- None, True or False
+- tuples of any of these (including nested tuples)
+
+ - singleton tuples don't require a comma: ``(1)`` is the same as ``(1,)``
+
+Duplicate facts are not allowed. An attempt to assert a fact that already
+exists is silently ignored. But note that to be a duplicate, *all* of the
+arguments must be the same!
+
+Currently facts are thought to be immutable, meaning that they may not be
+changed or retracted. That's why dictionaries, lists and user-defined
+objects are not recommended as arguments.
+
+Case Specific Facts
+---------------------
+
+Most facts are *case specific* facts. This means that they will be deleted
+when an engine_ reset_ is done to prepare for another run of the inference
+engine. Case specific facts are asserted through either::
+
+ some_engine.assert_(kb_name, fact_name, arguments)
+ some_engine.add_case_specific_fact(kb_name, fact_name, arguments)
+
+They may also be asserted by forward-chaining_ rules.
+
+Universal Facts
+---------------------
+
+Universal facts are never deleted (specifically, when a reset_ is done). You
+can specify universal facts in a `.kfb file`_, or add universal facts by
+calling::
+
+ some_engine.add_universal_fact(kb_name, fact_name, arguments)
+
+Typically, all universal facts are added once at `program startup`_.
+
diff --git a/doc/sphinx/source/knowledge_bases/index.rst b/doc/sphinx/source/knowledge_bases/index.rst
new file mode 100644
index 0000000..451c193
--- /dev/null
+++ b/doc/sphinx/source/knowledge_bases/index.rst
@@ -0,0 +1,105 @@
+.. $Id: index.txt a2119c07028f 2008-10-27 mtnyogi $
+..
+.. Copyright © 2007-2008 Bruce Frederiksen
+..
+.. Permission is hereby granted, free of charge, to any person obtaining a copy
+.. of this software and associated documentation files (the "Software"), to deal
+.. in the Software without restriction, including without limitation the rights
+.. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+.. copies of the Software, and to permit persons to whom the Software is
+.. furnished to do so, subject to the following conditions:
+..
+.. The above copyright notice and this permission notice shall be included in
+.. all copies or substantial portions of the Software.
+..
+.. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+.. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+.. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+.. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+.. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+.. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+.. THE SOFTWARE.
+
+.. toctree::
+ :maxdepth: 1
+ :hidden:
+
+ fact_bases
+ rule_bases
+ question_bases
+ special
+
+====================
+Knowledge Bases
+====================
+
+Knowledge is organized into named repositories called *knowledge bases*.
+A knowledge base is like a directory for files on disk, except that knowledge
+bases may not be nested. Therefore, the *entities* within a knowledge base
+always have a two-level name: *knowledge_base_name.knowledge_entity_name*.
+
+Here are some examples of facts you might see in a web server application::
+
+ header.cookie('session=123456789;remember=the_alamo')
+ cookie.session(123456789)
+ cookie.remember(the_alamo)
+ header.accept_encoding(gzip)
+ header.accept_encoding(deflate)
+ request.path('/my/site.html')
+ request.path_segment(0, my)
+ request.path_segment(1, 'site.html')
+ request.path_segment(-2, my)
+ request.path_segment(-1, 'site.html')
+
+Note that three different knowledge bases (all `fact bases`_) are shown here
+named ``header``, ``cookie``, and ``request``; each with multiple facts.
+
+The second part of the two-part name is the name of the *knowledge entity*.
+You can think of knowledge entities as statement_ *types* or *topics*. So:
+
+ :request:
+ is the name of the *knowledge base*.
+ :request.path_segment:
+ is the name of the *knowledge entity*, or statement topic.
+ :request.path_segment(-1, 'site.html'):
+ is a specific statement about the topic of request.path_segments.
+
+What do Knowledge Bases Do?
+===========================
+
+Ultimately Pyke is interested in proving statements, or answering the question
+"Is statement X true"? There are several different types of knowledge bases.
+Each type of knowledge base represents a different way of doing this:
+
+- Those that contain simple lists of statements of fact (as you see in the
+ example above) are called `fact bases`_.
+
+ - These determine whether a statement is true by simply checking to see if
+ that statement is in their list of known facts.
+
+- Those that contain *if-then* rules_ are called `rule bases`__.
+
+ - These determine whether a statement is true by running their if-then rules
+ to try to construct a proof for that statement.
+ - Rule bases may include both forward-chaining_ and backward-chaining_ rules.
+
+- It is also possible to create other kinds of knowledge bases that determine
+ the truth of statements in other ways. Pyke provides two of these:
+
+ - The `question base`_ which just poses the statement to an end user as a
+ question.
+ - The special_ knowledge base which has several special one-off knowledge
+ entities to do different things like run a command_ on the underlying
+ system and examine its output and/or exit status.
+
+ - There is only has one instance of this knowledge base -- called
+ ``special``.
+
+.. __: rule_bases.html
+
+.. note::
+
+ All knowledge bases share the same name space. So no two of them,
+ regardless of their type, may have the same name.
+
+
diff --git a/doc/sphinx/source/knowledge_bases/question_bases.rst b/doc/sphinx/source/knowledge_bases/question_bases.rst
new file mode 100644
index 0000000..32bd588
--- /dev/null
+++ b/doc/sphinx/source/knowledge_bases/question_bases.rst
@@ -0,0 +1,130 @@
+.. $Id: question_bases.txt 4670da845e46 2010-03-05 mtnyogi $
+..
+.. Copyright © 2008 Bruce Frederiksen
+..
+.. Permission is hereby granted, free of charge, to any person obtaining a copy
+.. of this software and associated documentation files (the "Software"), to deal
+.. in the Software without restriction, including without limitation the rights
+.. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+.. copies of the Software, and to permit persons to whom the Software is
+.. furnished to do so, subject to the following conditions:
+..
+.. The above copyright notice and this permission notice shall be included in
+.. all copies or substantial portions of the Software.
+..
+.. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+.. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+.. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+.. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+.. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+.. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+.. THE SOFTWARE.
+
+=============================================
+Question Bases
+=============================================
+
+Question bases contain questions for end users. These questions can be of
+various types (e.g., yes/no, multiple_choice). The questions may be
+parametrized, with the parameter values substituted into the question text
+when the question is asked. In this case, different parameter values are
+treated as different question statements_.
+
+The answers to all questions are automatically remembered so that if multiple
+rules ask the same question, the end user only sees it once. These answers
+are erased when an `engine.reset`_ is done.
+
+Finally, questions may have *reviews* attached to them to automatically
+display different canned messages (with parameter substitution) depending on
+the end user's answer.
+
+
+KQB files
+==========
+
+Each question base is defined by a `.kqb file`_. The name of each question
+base is the filename of the .kqb file (with the ``.kqb`` suffix removed).
+This must be a legal Python identifier.
+
+These .kqb files are compiled and loaded automatically when you create your
+`knowledge_engine.engine`_ object.
+
+The .kqb file contains all of the information about the question needed to
+ask the question, validate the answer, and output the appropriate *review*
+text.
+
+The .kqb file also specifies which parameter contains the answer. All
+parameters, except this one, must be bound to values before testing the
+question.
+
+
+Example
+=======
+
+In writing a program to diagnose car problems, you might have a
+``user_question`` question base with questions like::
+
+ engine_starts($ans)
+ Can you start the engine?
+ ---
+ $ans = yn
+
+ mileage($ans)
+ How many miles are on the car?
+ ---
+ $ans = integer(1-999999)
+ 200000- ! Wow, that's a lot of miles!
+
+ noise_from($location, $ans)
+ Do you hear a noise from $location?
+ ---
+ $ans = yn
+
+These would look like the following statements_ within rules_::
+
+ user_question.engine_starts(True)
+ user_question.mileage($mileage)
+ user_question.noise_from('under the hood', False)
+
+Presenting Questions to Your End Users
+======================================
+
+Pyke provides two modules to actually present a question to your end user:
+
+- ask_tty
+
+ This presents the question on stdout and reads stdin for the answer.
+
+- ask_wx
+
+ This presents the question in a dialog box for use with wxpython_.
+
+You may write your own module to present questions to end users. Look at the
+modules provided by Pyke for guidance.
+
+To ask a question, Pyke looks for an ``ask_module`` attribute on:
+
+#. the question_base object, then
+#. the `knowledge_engine.engine`_ object
+
+If the `knowledge_engine.engine`_ object does not have an ``ask_module``
+attribute, ask_tty is imported (by default) and stored there.
+
+.. This code is hidden. It will add '' to sys.path, change to the doc.examples
+ directory and store the directory path in __file__ for the code section
+ following:
+ >>> import sys
+ >>> if '' not in sys.path: sys.path.insert(0, '')
+ >>> import os
+ >>> os.chdir("../../examples")
+ >>> __file__ = os.getcwd()
+
+Here's an example of setting this attribute::
+
+ >>> from pyke import knowledge_engine
+ >>> from pyke import ask_wx
+
+ >>> engine = knowledge_engine.engine(__file__)
+ >>> engine.ask_module = ask_wx
+
+
diff --git a/doc/sphinx/source/knowledge_bases/rule_bases.rst b/doc/sphinx/source/knowledge_bases/rule_bases.rst
new file mode 100644
index 0000000..7ba0b68
--- /dev/null
+++ b/doc/sphinx/source/knowledge_bases/rule_bases.rst
@@ -0,0 +1,243 @@
+.. $Id: rule_bases.txt a2119c07028f 2008-10-27 mtnyogi $
+..
+.. Copyright © 2007-2008 Bruce Frederiksen
+..
+.. Permission is hereby granted, free of charge, to any person obtaining a copy
+.. of this software and associated documentation files (the "Software"), to deal
+.. in the Software without restriction, including without limitation the rights
+.. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+.. copies of the Software, and to permit persons to whom the Software is
+.. furnished to do so, subject to the following conditions:
+..
+.. The above copyright notice and this permission notice shall be included in
+.. all copies or substantial portions of the Software.
+..
+.. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+.. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+.. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+.. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+.. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+.. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+.. THE SOFTWARE.
+
+==========
+Rule Bases
+==========
+
+Rule bases are collections of rules_. Rule bases are created by writing a
+*knowledge rule base* (`.krb`_) file with your favorite text editor.
+
+A single rule base may contain both forward-chaining_ and backward-chaining_
+rules.
+
+The forward-chaining rules are run automatically when the rule base is
+activated_ to assert new statements_ of fact_. Thus, forward-chaining rules
+are not directly used to determine whether any particular statement_ is true.
+
+But backward-chaining rules *are* directly used to determine whether a
+particular statement is true. Thus, when a rule base name (or, more properly,
+a `rule base category`_ name, explained below) is used as the
+*knowledge base name* in a statement, it refers to the backward-chaining
+rules within that rule base.
+
+.. note::
+
+ Pyke runs all forward-chaining rules before running any backward-chaining
+ rules.
+
+ Thus, using rule base names as the *knowledge base name* in statements
+ within a forward-chaining rule is prohibited, as this would cause
+ backward-chaining rules to run in order to process the forward-chaining
+ rule.
+
+Why Multiple Rule Bases?
+========================
+
+There are two reasons to have more than one rule base (i.e., more than one
+`.krb file`_):
+
+#. To divide a large set of rules into human manageable units.
+
+ In this case, you want Pyke to use all of the rule bases combined.
+
+ For example, you may have rules governing the automatic generation of SQL
+ statements, and other rules governing the generation of HTML documents.
+ You want to keep these rules in different rule bases to make them more
+ manageable.
+
+#. To enable your Python program to choose between different rule bases
+ that are tailored to different specific situations.
+
+ For example, some of the rules governing the automatic generation of SQL
+ statements may vary depending upon the target database (e.g., ``mysql``,
+ ``postgresql``, ``oracle``).
+
+ In this case, you want to be able to tell Pyke which of several rule bases
+ to use on each invocation, depending upon which target database you will
+ be accessing. You would never use more than one of these rule bases at
+ the same time, so these rule bases are mutually exclusive.
+
+These two goals are met by three capabilities:
+
+- `Rule Base Categories`_
+- `Rule Base Inheritance`_
+- `Rule Base Activation`_
+
+Rule Base Categories
+====================
+
+All rule bases are grouped into categories. Each rule base category only gets
+to have **one** active_ rule base.
+
+Thus, you place rule bases that you want to have active simultaneously into
+*different* rule base categories; and place rule bases that are mutually
+exclusive with each other (e.g., the ``mysql``, ``postgresql`` and ``oracle``
+rule bases) into the *same* rule base category.
+
+Each rule base category has a unique name. In the example above you would
+want two rule base categories: ``database`` and ``html_generation``.
+
+The rule base category name is used as the *knowledge base name* for
+statements within rules of one rule base category that want to refer to
+rules within another rule base category. For example, rule bases in the
+``html_generation`` category would need to use ``database.insert(...)`` to
+refer to the ``insert`` rules in the ``database`` category.
+
+Rule Base Inheritance
+=====================
+
+The rule bases within the same category_ share rules amongst themselves
+through rule base inheritance.
+
+Rule bases use single inheritance to inherit the rules_ from one other rule
+base. This can go on to any depth. Both forward-chaining_ and
+backward-chaining_ rules_ are inherited.
+
+This allows mutually exclusive rule bases to share common rules in a parent
+rule base without having to duplicate these rules amongst themselves.
+
+Here is the definition, then, of a `rule base category`_:
+
+ Each *root* rule base (through rule base inheritance) defines a unique
+ rule base category. All rule bases derived (directly or indirectly)
+ from that root rule base are in the same rule base category.
+
+ The name of the rule base category is simply the name of its root
+ rule base.
+
+So, our ``database`` and ``html_generation`` example would look like this:
+
+.. figure:: ../images/rule_base_categories.png
+ :width: 450
+ :height: 424
+ :scale: 100
+ :align: center
+
+ Rule Base Categories
+
+We have one root rule base called ``database`` and it has derived rule bases
+called ``mysql``, ``postgresql`` and ``oracle``. And a second root rule base
+called ``html_generation`` with ``firefox`` and ``internet_explorer``.
+
+The two root rule bases define two rule base categories:
+
+- database, which includes:
+
+ - database
+ - mysql
+ - postgresql
+ - oracle
+
+- html_generation, which includes:
+
+ - html_generation
+ - firefox
+ - internet_explorer
+
+.. note::
+
+ The `.krb files`_ for these rule bases may be placed anywhere you want
+ them within your Pyke source directory structure -- in other words, your
+ directory structure is not required to match your rule base inheritance
+ structure.
+
+Only one rule base from each rule base category may be active_ at any point in
+time.
+
+Within each of these rule bases, if the knowledge base name is omitted from a
+statement within a `backward-chaining rule`_, it defaults to the
+`rule base category`_ of that rule base, *not* the rule base itself.
+Thus, ``insert(...)`` within ``postgresql`` would mean
+``database.insert(...)``, and ``make_tag(...)`` within ``firefox`` would mean
+``html_generation.make_tag(...)``.
+
+.. important::
+
+ Note that referring to a rule base category (either explicitly or
+ implicitly) *always* refers to the active_ rule base within that category.
+ This may not be the rule base with that name (the root rule base), or even
+ the rule base making implicit use of the rule base category. For example,
+ ``insert(...)`` within ``postgresql`` will end up referring to ``insert``
+ rules within the ``oracle`` rule base when ``oracle`` is the active rule
+ base.
+
+All rules referring to foreign `rule base categories`_ must explicitly use the
+rule base category name. For example, to refer to the ``insert`` rule for
+databases, within the ``html_generation`` category, you would have to say
+``database.insert(...)``.
+
+In this way, all of the rules will work no matter which rule base is active
+within each rule base category.
+
+Rule Inheritance
+----------------
+
+There is an important difference between how backward-chaining_ rule
+inheritance works within Pyke rule bases and how method inheritance works
+within Python classes:
+
+* When a derived class in Python defines a method by the same name as a
+ method in its parent class, the derived method *overrides* the parent
+ method. I.e., only the derived method is used when a call is made
+ to it.
+
+* In contrast, when a derived rule base in Pyke defines
+ `backward-chaining rules`_ for a goal that also has backward-chaining rules
+ defined for it in the parent rule base, the derived rule *extends* the
+ set of rules that may be used to try to prove this goal_kb_. All of the
+ derived rules will be tried first. If all of these fail, then the parent
+ rules are tried.
+
+ If you don't want the parent rules to be used for a particular goal_kb_,
+ you must list that goal name in the ``without`` clause of the extending_
+ statement at the beginning of the derived rule base.
+
+.. note::
+
+ All `forward-chaining rules`_ in the parent rule base are always included
+ in the derived rule base. The ``without`` clause only applies to
+ backward-chaining rules.
+
+Rule Base Activation
+=====================
+
+Loading_ rule bases only makes them available for use. It does not
+automatically activate_ any of them. This must be done explicitly by your
+Python program. Your program may decide to activate different rule bases
+in different situations.
+
+Additionally, `forward-chaining rules`_ may be used to activate more specific
+rule bases, based upon their inferencing. But once a rule base has been
+activated for a `rule base category`_, only children of the currently active
+rule base may be activated from that point on. Because these children
+inherit_ the rules of the currently active rule base; activating child
+rule bases only adds new rules, and doesn't take any away. Thus, any
+forward-chaining rule run during the activation of the first rule base
+are not invalidated by activating the second rule base.
+
+In our database example, your program could activate the root ``database``
+rule base and let the forward-chaining rules within the ``database`` rule
+base figure out which derived rule base to activate depending on the
+particular database in use at the time the program is run.
+
+
diff --git a/doc/sphinx/source/knowledge_bases/special.rst b/doc/sphinx/source/knowledge_bases/special.rst
new file mode 100644
index 0000000..38ce193
--- /dev/null
+++ b/doc/sphinx/source/knowledge_bases/special.rst
@@ -0,0 +1,250 @@
+.. $Id: special.txt 4dca5ad0f397 2010-03-10 mtnyogi $
+..
+.. Copyright © 2007-2008 Bruce Frederiksen
+..
+.. Permission is hereby granted, free of charge, to any person obtaining a copy
+.. of this software and associated documentation files (the "Software"), to deal
+.. in the Software without restriction, including without limitation the rights
+.. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+.. copies of the Software, and to permit persons to whom the Software is
+.. furnished to do so, subject to the following conditions:
+..
+.. The above copyright notice and this permission notice shall be included in
+.. all copies or substantial portions of the Software.
+..
+.. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+.. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+.. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+.. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+.. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+.. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+.. THE SOFTWARE.
+
+=======
+Special
+=======
+
+There is only one instance of this 'special' knowledge base, called
+``special``.
+
+The ``special`` knowledge base is a collection of miscellaneous helper
+*knowledge entities* that determine whether a statement is true or not in
+various interesting ways.
+
+Thus, each entity in this `knowledge base`_ is a Python function that does
+something "special" when run.
+
+The ``special`` functions are:
+
+ - claim_goal_
+ - check_command_
+ - command_
+ - general_command_
+
+Claim_goal
+==========
+
+The ``claim_goal`` function has no arguments::
+
+ special.claim_goal()
+
+This acts like the Prolog_ `cut operator`_.
+
+In general there are multiple rules_ that might be used to try to prove_ any
+goal_kb_. They are each tried in the order that they appear in the `.krb file`_.
+If one rule fails, the next rule is tried. The goal itself doesn't fail
+until all of the rules for it have failed.
+
+Example
+-------
+
+Suppose I want to translate a number, N, into the phrase "N dogs". I could
+use the following rules::
+
+ one_dog
+ use n_dogs(1, '1 dog')
+
+ n_dogs
+ use n_dogs($n, $phrase)
+ when
+ $phrase = "%d dogs" % $n
+
+The problem here is that both rules might be used when ``n`` is 1, but the
+second rule isn't appropriate in this case. ``Special.claim_goal()`` may
+be used to fix this, as follows::
+
+ one_dog
+ use n_dogs(1, '1 dog')
+ when
+ special.claim_goal()
+
+ n_dogs
+ use n_dogs($n, $phrase)
+ when
+ $phrase = "%d dogs" % $n
+
+The ``special.claim_goal()`` prevents the second rule from being used when
+``n`` is 1.
+
+Explanation
+-----------
+
+When a rule_ executes ``special.claim_goal()`` in its ``when``
+clause, none of the rest of the rules will be tried for that goal_kb_.
+Thus, when ``special.claim_goal()`` is backtracked_ over, the goal fails
+immediately without trying any more rules for it.
+
+This ends up acting like an "else". You place it in the ``when`` clause
+after the premises_ that show that this rule **must** be the correct one
+to use. Then the subsequent rules will only be tried if these premises
+fail, such that ``special.claim_goal()`` is never executed.
+
+This means that you don't need to add extra premises in each subsequent rule
+to make sure that these premises have **not** occurred.
+
+Without the ``special.claim_goal()`` in the prior example, you would have to
+write::
+
+ one_dog
+ use n_dogs(1, '1 dog')
+
+ n_dogs
+ use n_dogs($n, $phrase)
+ when
+ check $n != 1
+ $phrase = "%d dogs" % $n
+
+This is a simple example where it is easy to add the check in the second
+rule. But in general, it can be difficult to check for prior conditions,
+especially when many rules are involved that each has its own condition.
+
+Running Commands
+================
+
+The remaining three functions deal with running programs (commands) on the
+host computer that is running your Pyke program. Their difference is in what
+kind of output they provide from the command.
+
+These functions all use the `subprocess.Popen`_ function from the standard
+Python library.
+
+Thus, each of these functions accept these three parameters that are passed
+on to subprocess.Popen:
+
+ - The ``$command`` parameter (required).
+
+ - This is a tuple indicating the program to run along with its command
+ line arguments, such as ``(ls, '-l')``.
+
+ - The ``$cwd`` parameter (optional).
+
+ - This specifies the *current working directory* to run the command in.
+ - If omitted or ``None`` the current working directory is not changed.
+
+ - The ``$stdin`` parameter (optional).
+
+ - This is a string that is fed to the command as its stdin.
+
+ - If the command expects multiple lines of input, this string must
+ include embedded newlines (e.g., ``'line 1\nline 2\n'``).
+
+ - If omitted or ``None``, no stdin is provided to the command.
+
+All of these functions fail on backtracking_.
+
+Check_command
+-------------
+
+::
+
+ special.check_command($command [, $cwd [, $stdin]])
+
+Succeeds if the command returns a zero exit status. Fails otherwise. Any
+output from the command to stdout or stderr is unavailable.
+
+ >>> from pyke import knowledge_engine
+ >>> engine = knowledge_engine.engine()
+ >>> engine.prove_1_goal('special.check_command((true))')
+ ({}, None)
+ >>> engine.prove_1_goal('special.check_command((false))')
+ Traceback (most recent call last):
+ ...
+ pyke.knowledge_engine.CanNotProve: Can not prove special.check_command((false))
+
+Command
+-------
+
+::
+
+ special.command($stdout, $command [, $cwd [, $stdin]])
+
+This just looks at the stdout of the command. Any output from the command
+to stderr is unavailable.
+
+The ``$stdout`` is a tuple of lines with the trailing newlines removed.
+
+This raises `subprocess.CalledProcessError`_ if the command returns a non-zero
+exit status.
+
+ >>> from __future__ import with_statement
+ >>> from pyke import pattern, contexts
+ >>> def run_command(entity, command, cwd=None, stdin=None):
+ ... with engine.prove_goal(
+ ... 'special.%s($output, $command, $cwd, $stdin)' % entity,
+ ... command=command,
+ ... cwd=cwd,
+ ... stdin=stdin) \
+ ... as gen:
+ ... for vars, no_plan in gen:
+ ... print(vars['output'])
+ >>> run_command('command', ('echo', 'hi', 'mom'))
+ ('hi mom',)
+ >>> run_command('command', ('ls',)) # doctest: +NORMALIZE_WHITESPACE
+ ('fact_bases.txt', 'index.txt', 'links', 'question_bases.txt',
+ 'rule_bases.txt', 'special.txt')
+ >>> run_command('command', ('ls', '-l', 'links.rst')) # doctest: +ELLIPSIS
+ ('-rw-r--r-- 1 ... links',)
+ >>> run_command('command', ('tail', '-n', '5', 'template.txt', '-'),
+ ... '..', # cwd (doc/source)
+ ... 'stdin: line 1\nstdin: line 2\nstdin: line 3\n')
+ ... # doctest: +NORMALIZE_WHITESPACE
+ ('==> template.txt <==',
+ ' } catch(err) {}',
+ ' ',
+ '