Commits

Gines Martinez  committed 094e67a Draft

version 0.3.0

  • Participants

Comments (0)

Files changed (128)

+syntax:regexp
+^build/
+^dist/
+^docs/_build/
+^.*\.svn/
+^\.tox/
+\.coverage
+\.pyc$
+\.orig$
+\.class$
+\.so$
+\.*,cover
+test.cfg
+push.sh
+\.egg$
+\.egg-info$
+coverage.xml
+nosetests.xml
+.*.tar.gz
+0.1.0 (2012-03-06)
+==================
+
+First release.
+
+0.1.1 (2012-03-07)
+==================
+
+Improve api doc from c_*.py modules.
+
+0.1.2 (2012-03-30)
+==================
+
+Added c_wsgi_server.py, a experimental wsgi server based in waitress and ginsfsm
+
+0.3.0 (2012-06-30)
+==================
+
+Refactoring doc, examples, ... all.

File CONTRIBUTORS.txt

+ ArtGins Project Contributor Agreement
+======================================
+
+The submitter agrees by adding his or her name within the section below named
+"Contributors" and submitting the resulting modified document to the
+canonical shared repository location for this software project (whether
+directly, as a user with "direct commit access", or via a "pull request"), he
+or she is signing a contract electronically.  The submitter becomes a
+Contributor after a) he or she signs this document by adding their name
+beneath the "Contributors" section below, and b) the resulting document is
+accepted into the canonical version control repository.
+
+Treatment of Account
+---------------------
+
+Contributor will not allow anyone other than the Contributor to use his or
+her username or source repository login to submit code to a ArtGins Project
+source repository. Should Contributor become aware of any such use,
+Contributor will immediately by notifying ArtGins.
+Notification must be performed by sending an email to
+webmaster@artgins.com.  Until such notice is received, Contributor will be
+presumed to have taken all actions made through Contributor's account. If the
+Contributor has direct commit access, ArtGins will have
+complete control and discretion over capabilities assigned to Contributor's
+account, and may disable Contributor's account for any reason at any time.
+
+Legal Effect of Contribution
+----------------------------
+
+Upon submitting a change or new work to a ArtGins Project source Repository (a
+"Contribution"), you agree to assign, and hereby do assign, a one-half
+interest of all right, title and interest in and to copyright and other
+intellectual property rights with respect to your new and original portions
+of the Contribution to ArtGins. You and ArtGins
+each agree that the other shall be free to exercise any and all exclusive
+rights in and to the Contribution, without accounting to one another,
+including without limitation, the right to license the Contribution to others
+under the Repoze Public License. This agreement shall run with title to the
+Contribution. ArtGins does not convey to you any right, title
+or interest in or to the Program or such portions of the Contribution that
+were taken from the Program. Your transmission of a submission to the ArtGins
+Project source Repository and marks of identification concerning the
+Contribution itself constitute your intent to contribute and your assignment
+of the work in accordance with the provisions of this Agreement.
+
+License Terms
+-------------
+
+Code committed to the ArtGins Project source repository (Committed Code) must
+be governed by the Repoze Public License (http://repoze.org/LICENSE.txt, aka
+"the RPL") or another license acceptable to ArtGins.  Until
+ArtGins declares in writing an acceptable license other than
+the RPL, only the RPL shall be used.  A list of exceptions is detailed within
+the "Licensing Exceptions" section of this document, if one exists.
+
+Representations, Warranty, and Indemnification
+----------------------------------------------
+
+Contributor represents and warrants that the Committed Code does not violate
+the rights of any person or entity, and that the Contributor has legal
+authority to enter into this Agreement and legal authority over Contributed
+Code. Further, Contributor indemnifies ArtGins against
+violations.
+
+Cryptography
+------------
+
+Contributor understands that cryptographic code may be subject to government
+regulations with which ArtGins and/or entities using Committed
+Code must comply. Any code which contains any of the items listed below must
+not be checked-in until ArtGins staff has been notified and has
+approved such contribution in writing.
+
+- Cryptographic capabilities or features
+
+- Calls to cryptographic features
+
+- User interface elements which provide context relating to cryptography
+
+- Code which may, under casual inspection, appear to be cryptographic.
+
+Notices
+-------
+
+Contributor confirms that any notices required will be included in any
+Committed Code.
+
+Licensing Exceptions
+====================
+
+Code committed within the ``docs/`` subdirectory of the GinsFSM source
+control repository and "docstrings" which appear in the documentation
+generated by running "make" within this directory is licensed under the
+Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States
+License (http://creativecommons.org/licenses/by-nc-sa/3.0/us/).
+
+List of Contributors
+====================
+
+The below-signed are contributors to a code repository that is part of the
+project named "GinsFSM".  Each below-signed contributor has read, understand
+and agrees to the terms above in the section within this document entitled
+"ArtGins Project Contributor Agreement" as of the date beside his or her name.
+
+Contributors
+------------
+
+- Ginés Martínez Sánchez, 2012/01/01
+

File COPYRIGHT.txt

+Copyright (c) 2012, Ginés Martínez Sánchez.
+Copyright (c) 2012 ArtGins and Contributors.
+(http://www.artgins.com), All Rights Reserved
+
+The compat.py module is copyright from (c) Agendaless Consulting and Contributors (http://www.agendaless.com).
+
+The c_sockt.py module  is inspired in Tornado (ioloop.py) and Python (asyncore.py,asynchat) with copyrights from:
+    - (c) Sam Rushing <rushing@nightmare.com>
+    - (c) Tornado (http://www.tornadoweb.org/)
+    - (c) Facebook (http://www.facebook.com/)
+
+Hacking on GinsFSM
+==================
+
+Here are some guidelines about hacking on GinsFSM.
+
+Using a Development Checkout
+----------------------------
+
+Below is a quick start on creating a development environment using a GinsFSM
+checkout.
+
+TODO
+
+Adding Features
+---------------
+
+In order to add a feature to GinsFSM:
+
+- The feature must be documented in both the API and narrative
+  documentation (in ``docs/``).
+
+- The feature must work fully on the following CPython versions: 2.6,
+  2.7, and 3.2 on both UNIX and Windows.
+
+- The feature must work on the latest version of PyPy.
+
+- The feature must not cause installation or runtime failure on App Engine.
+  If it doesn't cause installation or runtime failure, but doesn't actually
+  *work* on these platforms, that caveat should be spelled out in the
+  documentation.
+
+- The feature must not depend on any particular persistence layer
+  (filesystem, SQL, etc).
+
+- The feature must not add unnecessary dependencies (where
+  "unnecessary" is of course subjective, but new dependencies should
+  be discussed).
+
+The above requirements are relaxed for scaffolding dependencies.  If a
+scaffold has an install-time dependency on something that doesn't work on a
+particular platform, that caveat should be spelled out clearly in *its*
+documentation (within its ``docs/`` directory).
+
+Coding Style
+------------
+
+- PEP8 compliance.  Whitespace rules are relaxed: not necessary to put
+  2 newlines between classes.  But 80-column lines, in particular, are
+  mandatory.
+
+Running Tests
+--------------
+
+- To run tests for GinsFSM on a single Python version, run ``python setup.py
+  test`` against the using the Python interpreter from virtualenv into which
+  you've ``setup.py develop``-ed GinsFSM.
+
+- To run the full set of GinsFSM tests on all platforms, install ``tox``
+  (http://codespeak.net/~hpk/tox/) into a system Python.  The ``tox`` console
+  script will be installed into the scripts location for that Python.  While
+  ``cd``'ed to the GinsFSM checkout root directory (it contains ``tox.ini``),
+  invoke the ``tox`` console script.  This will read the ``tox.ini`` file and
+  execute the tests on multiple Python versions and platforms; while it runs,
+  it creates a virtualenv for each version/platform combination.  For
+  example::
+
+   $ /usr/bin/easy_install tox
+   $ cd ~/hack-on-ginsfsm/ginsfsm
+   $ /usr/bin/tox
+
+Test Coverage
+-------------
+
+- The codebase *must* have 100% test statement coverage after each commit.
+  You can test coverage by installing ``nose`` and ``coverage``
+  into your virtualenv, and running ``setup.py nosetests --with-coverage``.
+
+Documentation Coverage
+----------------------
+
+- If you fix a bug, and the bug requires an API or behavior
+  modification, all documentation in this package which references
+  that API or behavior must change to reflect the bug fix, ideally in
+  the same commit that fixes the bug or adds the feature.
+
+- To build and review docs:
+
+  1. Install ``tests_require`` dependencies from GinsFSM's setup.py into your
+     virtualenv.
+
+  2. From the ``docs`` directory of the GinsFSM checkout run ``make html
+     SPHINXBUILD=/path/to/your/virtualenv/bin/sphinx-build``.
+
+  3.  Open the _build/html/index.html file to see the resulting rendering.
+
+Change Log
+----------
+
+- Feature additions and bugfixes must be added to the ``CHANGES.txt``
+  file in the prevailing style.  Changelog entries should be long and
+  descriptive, not cryptic.  Other developers should be able to know
+  what your changelog entry means.
+GinsFSM is released under terms of The MIT
+License <http://www.opensource.org/licenses/mit-license>
+
+Copyright (c) 2012, Ginés Martínez Sánchez.
+
+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.
+
+
+Portions of the code marked as "stolen from Pyramid and waitress" are provided
+under the following license:
+  Zope Public License (ZPL) Version 2.1
+  Copyright Zope Foundation and Contributors
+  Copyright (c) 2008-2011 Agendaless Consulting and Contributors.
+
+  Portions (c) Zope Foundation and contributors (http://www.zope.org/).
+
+  Portions (c) Edgewall Software (http://edgewall.org)
+
+  Portions (c) Ian Bicking.
+
+
+Portions of the code marked as "Code inspired in asyncore.py and tornado"
+are provided under the following license:
+
+  Code from tornado ioloop.py:
+
+    Copyright 2009 Facebook
+    Licensed under the Apache License, Version 2.0
+
+  Code from asyncore.py:
+    Copyright 1996 by Sam Rushing
+prune .hg
+exclude push.sh
+GinsFSM
+=======
+
+GinsFSM is a python library to develop systems based in finite-state machines
+(http://en.wikipedia.org/wiki/Finite-state_machine).
+This model is really useful when writing networking and communication
+applications.
+
+The idea is very simple:
+
+    * All objects, called `gobj`, are instances of a derived
+      `ginsfsm.gobj.GObj` class.
+    * The `GObj` has an inside `simple-machine`
+      that defines its behavior.
+    * The communication between `gobj`'s happens via `event`'s.
+
+Thus, the nature of this system is fully asynchronous and event-driven.
+
+The interface is simple and common to all objects; you just have to change the
+name of the event and the data they carry.
+
+Support and Documentation
+-------------------------
+
+See the <http://ginsfsm.org/> to view documentation.
+
+Code available in <https://bitbucket.org/artgins/ginsfsm>
+
+License
+-------
+
+Copyright (c) 2012, Ginés Martínez Sánchez.
+
+GinsFSM is released under terms of The MIT
+License <http://www.opensource.org/licenses/mit-license>
+
+GinsFSM TODO
+============
+
+- Incorporate multiple wsgi applications, as paste.urlmap, but dinamically!
+- Create scaffold templates.

File docs/DejaVuSans.ttf

Binary file added.

File docs/Makefile

+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS    =
+SPHINXBUILD   = sphinx-build
+PAPER         =
+BUILDDIR      = _build
+
+# Internal variables.
+PAPEROPT_a4     = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+# the i18n builder cannot share the environment and doctrees with the others
+I18NSPHINXOPTS  = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
+
+help:
+	@echo "Please use \`make <target>' where <target> is one of"
+	@echo "  html       to make standalone HTML files"
+	@echo "  dirhtml    to make HTML files named index.html in directories"
+	@echo "  singlehtml to make a single large HTML file"
+	@echo "  pickle     to make pickle files"
+	@echo "  json       to make JSON files"
+	@echo "  htmlhelp   to make HTML files and a HTML help project"
+	@echo "  qthelp     to make HTML files and a qthelp project"
+	@echo "  devhelp    to make HTML files and a Devhelp project"
+	@echo "  epub       to make an epub"
+	@echo "  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+	@echo "  latexpdf   to make LaTeX files and run them through pdflatex"
+	@echo "  text       to make text files"
+	@echo "  man        to make manual pages"
+	@echo "  texinfo    to make Texinfo files"
+	@echo "  info       to make Texinfo files and run them through makeinfo"
+	@echo "  gettext    to make PO message catalogs"
+	@echo "  changes    to make an overview of all changed/added/deprecated items"
+	@echo "  linkcheck  to check all external links for integrity"
+	@echo "  doctest    to run all doctests embedded in the documentation (if enabled)"
+
+clean:
+	-rm -rf $(BUILDDIR)/*
+
+html:
+	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+	@echo $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+	@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml:
+	$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+	@echo
+	@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+singlehtml:
+	$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+	@echo
+	@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+pickle:
+	$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+	@echo
+	@echo "Build finished; now you can process the pickle files."
+
+json:
+	$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+	@echo
+	@echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+	$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+	@echo
+	@echo "Build finished; now you can run HTML Help Workshop with the" \
+	      ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+qthelp:
+	$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+	@echo
+	@echo "Build finished; now you can run "qcollectiongenerator" with the" \
+	      ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+	@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/GinsFSM.qhcp"
+	@echo "To view the help file:"
+	@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/GinsFSM.qhc"
+
+devhelp:
+	$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
+	@echo
+	@echo "Build finished."
+	@echo "To view the help file:"
+	@echo "# mkdir -p $$HOME/.local/share/devhelp/GinsFSM"
+	@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/GinsFSM"
+	@echo "# devhelp"
+
+epub:
+	$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+	@echo
+	@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+latex:
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+	@echo
+	@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+	@echo "Run \`make' in that directory to run these through (pdf)latex" \
+	      "(use \`make latexpdf' here to do that automatically)."
+
+latexpdf:
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+	@echo "Running LaTeX files through pdflatex..."
+	$(MAKE) -C $(BUILDDIR)/latex all-pdf
+	@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+text:
+	$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+	@echo
+	@echo "Build finished. The text files are in $(BUILDDIR)/text."
+
+man:
+	$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+	@echo
+	@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+
+texinfo:
+	$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+	@echo
+	@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
+	@echo "Run \`make' in that directory to run these through makeinfo" \
+	      "(use \`make info' here to do that automatically)."
+
+info:
+	$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+	@echo "Running Texinfo files through makeinfo..."
+	make -C $(BUILDDIR)/texinfo info
+	@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
+
+gettext:
+	$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
+	@echo
+	@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
+
+changes:
+	$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+	@echo
+	@echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+	$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+	@echo
+	@echo "Link check complete; look for any errors in the above output " \
+	      "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+	$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+	@echo "Testing of doctests in the sources finished, look at the " \
+	      "results in $(BUILDDIR)/doctest/output.txt."

File docs/_static/CONNEX_FSM.svg

Added
New image

File docs/_static/CONNEX_FSM.svg.png

Added
New image

File docs/_static/DejaVuSans.ttf

Binary file added.

File docs/_static/TIMER_FSM.svg

Added
New image

File docs/_static/TIMER_FSM.svg.png

Added
New image

File docs/_static/latex-note.png

Added
New image

File docs/_static/latex-warning.png

Added
New image

File docs/_static/layout.png

Added
New image

File docs/_static/sample.png

Added
New image

File docs/_static/sample.svg

Added
New image

File docs/_static/test.py

+#! /home/gines/env_ginsfsm/bin/python
+
+from ginsfsm.fsmdraw.fsm2image import fsm2image
+#from ginsfsm.c_timer import TIMER_FSM  # , TIMER_GCONFIG
+from ginsfsm.c_connex import CONNEX_FSM  # , TIMER_GCONFIG
+
+
+if __name__ == '__main__':
+    svgfile = 'xxx'
+    fsm2image('./', svgfile, CONNEX_FSM, 'svg',
+              font_name='./DejaVuSans.ttf', font_size=14)

File docs/_static/test.svg

Added
New image

File docs/_static/xxx.svg

Added
New image

File docs/_static/xxx.svg.png

Added
New image

File docs/_themes/artgins/layout.html

+{% extends "sphinxdoc/layout.html" %}
+
+{#
+{% block header %}
+
+<div style="background-color: white; text-align: left; padding: 10px 10px 15px 15px">
+<img class="logo" src="{{ pathto('_static/pyramid.png', 1)}}" alt="Logo"/>
+</div>
+{% endblock %}
+#}
+{%- block sidebarsourcelink %}{%- endblock %}

File docs/_themes/artgins/static/pyramid.ico

Added
New image

File docs/_themes/artgins/static/pyramid.png

Added
New image

File docs/_themes/artgins/theme.conf

+[theme]
+inherit = sphinxdoc
+
+[options]
+logo = pyramid.png
+favicon = pyramid.ico

File docs/api.rst

+API Documentation
+=================
+
+Reference material for public API.
+
+Core classes
+------------
+
+.. toctree::
+    :maxdepth: 1
+
+    src/api/gaplic
+    src/api/gobj
+    src/api/smachine
+    src/api/gconfig
+
+Essential GObjs.
+----------------
+
+.. toctree::
+    :maxdepth: 1
+
+    src/api/c_timer
+    src/api/c_sock
+    src/api/c_srv_sock
+    src/api/c_connex
+    src/api/c_wsgi_server

File docs/conf.py

+# -*- coding: utf-8 -*-
+#
+# GinsFSM documentation build configuration file, created by
+# sphinx-quickstart on Sun Oct 23 20:50:35 2011.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys
+import os
+
+# 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.
+#sys.path.insert(0, os.path.abspath('..'))
+parent = os.path.dirname(os.path.dirname(__file__))
+sys.path.append(os.path.abspath(parent))
+
+# -- General configuration -----------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode', 'ginsfsm.sphinxext']
+
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'GinsFSM'
+copyright = u'2012, Ginés Martínez Sánchez alias "ginsmar"'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+from ginsfsm import __version__ as version
+# The full version, including alpha/beta/rc tags.
+release = version
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ['_build']
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+
+# -- 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 = 'artgins'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further.  For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+sys.path.append(os.path.abspath('_themes'))
+html_theme_path = ['_themes']
+
+# The name for this set of Sphinx documents.  If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar.  Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# 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']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it.  The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'GinsFSMdoc'
+
+
+# -- Options for LaTeX output --------------------------------------------------
+
+latex_elements = {
+# The paper size ('letterpaper' or 'a4paper').
+#'papersize': 'letterpaper',
+
+# The font size ('10pt', '11pt' or '12pt').
+#'pointsize': '10pt',
+
+# Additional stuff for the LaTeX preamble.
+#'preamble': '',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+  ('index', 'GinsFSM.tex', u'GinsFSM Documentation',
+   u'GMS', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output --------------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+    ('index', 'ginsfsm', u'GinsFSM Documentation',
+     [u'GMS'], 1)
+]
+
+# If true, show URL addresses after external links.
+#man_show_urls = False
+
+
+# -- Options for Texinfo output ------------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+#  dir menu entry, description, category)
+texinfo_documents = [
+  ('index', 'GinsFSM', u'GinsFSM Documentation', u'GMS',
+   'GinsFSM', 'One line description of project.', 'Miscellaneous'),
+]
+
+# Documents to append as an appendix to all manuals.
+#texinfo_appendices = []
+
+# If false, no module index is generated.
+#texinfo_domain_indices = True
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#texinfo_show_urls = 'footnote'

File docs/examples.rst

+Examples
+========
+
+Several examples.
+
+.. toctree::
+    :maxdepth: 1
+
+    src/examples/ontimer
+    src/examples/ongsock
+    src/examples/ongconnex
+    src/examples/stress_connections
+    src/examples/stress_client_echo
+    src/examples/stress_server_echo
+    src/examples/wsgi_server

File docs/ginsfsm-classes.png

Added
New image

File docs/glossary.rst

+.. _glossary:
+
+Glossary
+========
+
+.. glossary::
+    :sorted:
+
+    simple-machine
+        The `simple-machine` is the argument to
+        the :class:`ginsfsm.smachine.SMachine` class.
+
+        It's a simple implementation of an Finite State Machines
+        (`FSM <http://en.wikipedia.org/wiki/Finite-state_machine>`_)
+        using a *python dictionary with three keys*.
+
+        This is an example from :mod:`ginsfsm.examples.ontimer`::
+
+            ONTIMER_FSM = {
+                'event_list': ('EV_TIMEOUT',),
+                'state_list': ('ST_STATE',),
+                'machine': {
+                    'ST_STATE':
+                    (
+                        ('EV_TIMEOUT', ac_task, 'ST_STATE'),
+                    ),
+                }
+            }
+
+        See :mod:`ginsfsm.smachine` for more details.
+
+    gconfig-template
+        The `gconfig-template` is the argument to
+        the :class:`ginsfsm.gconfig.GConfig` class.
+
+        It's a *python dictionary*.
+
+        The key is the *parameter name*, and the value is a list describing
+        the parameter:
+
+            ``[type, default value, and description]``
+
+        This is an example from :mod:`ginsfsm.examples.ontimer`::
+
+            ONTIMER_GCONFIG = {  # type, default_value, flag, validate_function, desc
+                'seconds': [int, 2, 0, None, "Seconds to repeat the command."],
+                'verbose': [int, 0, 0, None, "Increase output verbosity."],
+                'command': [str, 'ls', 0, None, "Command to execute."],
+            }
+
+        See :mod:`ginsfsm.gconfig` for more details.
+
+    gobj
+        An instance of :class:`ginsfsm.gobj.GObj` class or derived.
+
+    gaplic
+        An instance of :class:`ginsfsm.gaplic.GAplic` class or derived.
+
+        It's the root, the grandfather,
+
+        the container of all :term:`gobj`'s' running in the same thread or
+        subprocess.
+
+    event
+        It's a :term:`event-name` or any object with a ``event_name`` attribute
+        that feeds a :term:`simple-machine`.
+
+        This is how :term:`gobj` communicate with each other: using *events*.
+
+    event-name
+        String defining the name of an event.
+
+
+    create_gobj
+        Factory function to create :term:`gobj`'s.
+        See :meth:`ginsfsm.gaplic.GAplic.create_gobj`.
+
+    principal
+        Any :term:`gobj` created without parent.
+
+    unnamed-gobj
+        Unnamed :term:`gobj`.
+
+    named-gobj
+        Named :term:`gobj`.
+
+    start_up
+        The pseudo **"__init__"** method of the `GObj` class.
+        Method of :class:`ginsfsm.gobj.GObj` class to be overried.
+
+    machine
+        Value of ``machine`` key of :term:`simple-machine` that is another
+        dictionary describing the machine :mod:`ginsfsm.smachine`.
+
+
+    input-event
+        Events that a :term:`gobj` receive from other :term:`gobj`'s,
+        or send to itself.
+
+    output-event
+        Events that are sent to another :term:`gobj`'s.
+
+    event-filter
+        Function for filtering events being broadcasting.
+
+    event-list
+        List or tuple of all :term:`input-event`'s event names used in
+        the :term:`machine`.
+
+    state-list
+        List of state names of the :term:`machine`. No matter the order,
+        but it is important the first state, because it is the default state
+        when the machine starts.
+
+    action
+        Function to be executed when a :term:`machine` receives an :term:`event`.
+
+    next-state
+        Name of next state to set in a :term:`machine` when it receives an event.
+
+    state
+        State name of a machine's state. We don't difference between `state`
+        and `state-name`, as opposite as :term:`event`/:term:`event-name`,
+        because there is no a visible `state instance`.

File docs/index.rst

+.. GinsFSM documentation master file, created by
+   sphinx-quickstart on Sun Oct 23 20:50:35 2011.
+   You can adapt this file completely to your liking, but it should at least
+   contain the root `toctree` directive.
+
+Wellcome
+========
+
+GinsFSM is a python library to develop systems based in finite-state machines
+(`FSM <http://en.wikipedia.org/wiki/Finite-state_machine>`_).
+
+This model is really useful when writing networking and communication
+applications.
+It has been my programming style over 20 years of C language development,
+and now that I’m moving to python,
+I want to continue with that approach.
+I’m from Madrid (Spain). My English is very bad,
+so I would appreciate you telling any mistake you see.
+
+
+Installation
+============
+
+You can install the library with ``easy_install``::
+
+    easy_install ginsfsm
+
+or with ``pip``::
+
+    pip install ginsfsm
+
+Documentation in http://ginsfsm.org/.
+
+Code available in https://bitbucket.org/artgins/ginsfsm
+
+
+Basic Idea
+==========
+
+Main classes:
+
+.. image:: ginsfsm-classes.png
+
+
+Briefly:
+
+* :class:`ginsfsm.gconfig.GConfig`:
+
+  Implements a flexible global configuration system,
+  defining a :term:`gconfig-template`.
+
+* :class:`ginsfsm.smachine.SMachine`:
+
+  Implements a simple Finite State Machine,
+  defining a :term:`simple-machine`.
+
+* :class:`ginsfsm.gobj.GObj`:
+
+  Well, yes, I'm a very simple brain. Only a machine.
+
+  But you write a good FSM, and I never fail you:
+
+  * derive me,
+  * write my :term:`simple-machine` FSM,
+  * tell the world how they can parameterize me with a :term:`gconfig-template`,
+  * and let me run.
+
+  Now I can feed my machine receiving external events,
+  and me too can communicate with others :term:`gobj`'s sending them events.
+
+* :class:`ginsfsm.gaplic.GAplic`:
+
+  Me? Well, I'm too a :term:`gobj`. I'm the root, the grandfather, and I can:
+
+  * supply the main loop in a thread o subprocess context.
+  * house all the child :term:`gobj`'s who want.
+  * serve as a bridge to other :term:`gaplic` for send/receive events.
+  * and more...
+
+The communication between :term:`gobj`'s happens via :term:`event`'s.
+
+The nature of this system is **fully asynchronous** and **event-driven**.
+
+The interface is simple and common to all objects; you just have to change the
+name of the event and the data they carry.
+
+
+Documentation
+=============
+
+.. toctree::
+    :maxdepth: 1
+
+    api
+    examples
+
+License
+=======
+
+    Copyright (c) 2012, Ginés Martínez Sánchez.
+
+    GinsFSM is released under terms of The MIT
+    License <http://www.opensource.org/licenses/mit-license>
+
+
+Index and Glossary
+==================
+
+* :ref:`glossary`
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
+
+.. add glossary, foreword, and latexindex in a hidden toc to avoid warnings
+
+.. toctree::
+   :hidden:
+
+   glossary

File docs/src/api/c_connex.rst

+:mod:`ginsfsm.c_connex`
+=======================
+
+.. automodule:: ginsfsm.c_connex

File docs/src/api/c_sock.rst

+:mod:`ginsfsm.c_sock`
+=====================
+
+.. automodule:: ginsfsm.c_sock

File docs/src/api/c_srv_sock.rst

+:mod:`ginsfsm.c_srv_sock`
+=========================
+
+.. automodule:: ginsfsm.c_srv_sock

File docs/src/api/c_timer.rst

+:mod:`ginsfsm.c_timer`
+======================
+
+.. automodule:: ginsfsm.c_timer

File docs/src/api/c_wsgi_server.rst

+:mod:`ginsfsm.wsgi.c_wsgi_server`
+=================================
+
+.. automodule:: ginsfsm.wsgi.c_wsgi_server

File docs/src/api/gaplic.rst

+:mod:`ginsfsm.gaplic`
+=====================
+
+.. automodule:: ginsfsm.gaplic

File docs/src/api/gconfig.rst

+:mod:`ginsfsm.gconfig`
+======================
+
+.. automodule:: ginsfsm.gconfig

File docs/src/api/gobj.rst

+:mod:`ginsfsm.gobj`
+===================
+
+.. automodule:: ginsfsm.gobj
+

File docs/src/api/smachine.rst

+:mod:`ginsfsm.smachine`
+=======================
+
+.. automodule:: ginsfsm.smachine
+

File docs/src/core/between.rst.TODO

+Communication between GObjs, through processes and threads.
+===========================================================
+
+All gobjs can communicate (send and receive events) between them.
+All gobjs belong to a gaplic, and one mission of the gaplic, is
+proportionate a communicate system between them.
+
+Communication between processes
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+GAplic can be synonymous of `process`.
+GAplic, like any process, can have running inside one o more threads,
+which are GAplics too.
+
+GinsFSM provides a communication system between all gaplics,
+whether they are in the same or different machine.
+
+.. graphviz::
+
+    graph gaplics_threads_gobjs {
+        graph [splines=true overlap=false];
+        size="5.0"
+        node [shape="box3d" penwidth=2 style=filled fillcolor="lightgray"];
+        subgraph cluster_machine1 {
+            label = "machine1";
+            "GAplic1" [label="GAplic1 process\n\n\n"];
+            "GAplic2" [label="GAplic2 process\n\n\n"];
+        }
+        subgraph cluster_machine2 {
+            label = "machine2";
+            "GAplic3" [label="GAplic3 process\n\n\n"];
+        }
+        "GAplic1" -- "GAplic2" [label="(comm between gaplics)" penwidth=3];
+        "GAplic2" -- "GAplic3" [label="(comm between gaplics)" penwidth=3];
+        "GAplic1" -- "GAplic3" [label="(comm between gaplics)" penwidth=3];
+        }
+
+
+Communication between threads
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+A GAplic process can have one o several threads.
+Each thread has their own one main gaplic object.
+
+GinsFSM provides a communication system between all gaplics,
+whether they are in the same or different `thread`.
+
+.. graphviz::
+
+    graph GAplic {
+        size="6.0"
+        //graph [fontsize=30 labelloc="t" label="" splines=true overlap=false rankdir="LR"];
+        graph [splines=true overlap=false];
+        node [shape="box3d" penwidth=2 style=filled fillcolor="lightgray"];
+        label="GAplic Process";
+        subgraph cluster_thread_main {
+            subgraph cluster_main_thread3 {
+                graph [style="filled" splines=true overlap=true];
+                label="Thread3";
+                gaplic3 -- obj31;
+                gaplic3 -- obj32;
+                obj31 -- obj33;
+            }
+            subgraph cluster_main_thread2 {
+                graph [style="filled" splines=true overlap=true];
+                label="Thread2";
+                gaplic2 -- obj21;
+                gaplic2 -- obj22;
+                obj21 -- obj23;
+            }
+            subgraph cluster_main_thread {
+                graph [style="filled" splines=true overlap=true];
+                label="Main Thread";
+                gaplic1 -- obj11;
+                gaplic1 -- obj12;
+                obj11 -- obj13;
+            }
+        }
+        gaplic1  -- gaplic2 [label="(comm between gaplics)" penwidth=3];
+        gaplic1  -- gaplic3 [label="(comm between gaplics)" penwidth=3];
+        gaplic2  -- gaplic3 [label="(comm between gaplics)" penwidth=3];
+    }
+
+
+Communication between gobjs
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+A gobj can be anonymous or named.
+You can communicate with other anonymous gobjs of the same gaplic.
+To communicate with gobjs from other gaplics (from other processes or threads),
+these must be `named` gobjs.
+
+Each main gaplic has a register of their own `named` gobjs.
+When two gaplics connected them, they interchange their `named` gobjs.
+Also, there are a specialized gaplic process, that acts as a DNS,
+recollecting all `named` gobjs from all gaplics. This process listen
+in a fixed range of ports, so all gaplics can search and find it, to register
+their `named` gobjs, and search for another gobjs.

File docs/src/core/core.rst.TODO

+==============
+Inside GinsFSM
+==============
+
+Core
+=====
+
+Core GinsFSM is building with three main modules:
+
+* :mod:`ginsfsm.gaplic`.
+* :mod:`ginsfsm.gobj`.
+* :mod:`ginsfsm.smachine`.
+
+and three main classes:
+
+* :class:`ginsfsm.gaplic.GAplic`.
+* :class:`ginsfsm.gobj.GObj`.
+* :class:`ginsfsm.smachine.SMachine`.
+
+The :class:`ginsfsm.gaplic.GAplic` class is derived
+from :class:`ginsfsm.gobj.GObj` class,
+and the :class:`ginsfsm.gobj.GObj` class
+is derived from :class:`ginsfsm.smachine.SMachine` class:
+
+.. graphviz::
+
+    digraph core_objects {
+        graph [fontsize=30 labelloc="t" label="" splines=true overlap=false];
+        size="7.0"
+        node [shape="tab" penwidth=2 style=filled fillcolor="lightgray"];
+        rankdir=TB;
+        "GObj" [URL="http://xx\N"];
+        "GAplic" [];
+        "SMachine" [];
+        "GObj" -> "GAplic";
+        "SMachine" -> "GObj";
+        }
+
+The :mod:`ginsfsm.gaplic` module supplies support for:
+
+* create :term:`gaplic` objects and running them as process or threads:
+    * :ref:`running-as-thread`.
+    * :ref:`running-as-main-process`.
+    * :ref:`running-as-child-process`.
+
+The :class:`ginsfsm.gaplic.GAplic` class supplies support for:
+
+* create :term:`gobj` objects under his domain: :ref:`creating-gobj`.
+* queues for exchange :term:`event`'s between :term:`gobj` objects.
+* :ref:`infinite-loop` to run the process or thread.
+
+The :mod:`ginsfsm.gobj` module supplies support for:
+
+* :ref:`creating-gclass`.
+* :ref:`creating-event`.
+
+The :class:`ginsfsm.gobj.GObj` class supplies support for:
+
+* :ref:`sending-events`:
+
+    * sending events by direct delivery: :ref:`send-event`.
+    * sending events by queues: :ref:`post-event`.
+    * sending events to subscribers: :ref:`broadcast-event`.
+
+* :ref:`receiving-events`:
+
+    * directly from another :term:`gobj`'s who knows you.
+    * subscribe to events from other :term:`gobj`'s: :ref:`subscription`.
+
+Using gaplic
+============
+
+GAplic is the container of :term:`gobj`'s running under his domain:
+
+.. graphviz::
+
+    graph GAplic {
+        size="6.0"
+        graph [splines=true overlap=false];
+        node [penwidth=2 style=filled fillcolor="lightgray"];
+        subgraph cluster_thread_main {
+            graph [style="filled" splines=true overlap=true];
+            label="GAplic";
+            "Principal gobj" -- "child1 gobj";
+            "Principal gobj" -- "child2 gobj";
+            "child2 gobj" -- "child2-1 gobj";
+            "child2 gobj" -- "child2-2 gobj";
+            "child1 gobj" -- "child1-1 gobj";
+            "child2-1 gobj" -- "child2-1-1 gobj";
+        }
+    }
+
+You can run a :term:`gaplic` as a simple process, a thread or
+a child daemon process.
+
+The :mod:`ginsfsm.gaplic` module build two classes with the same interface, to
+run a :term:`gaplic` like a thread or process:
+
+* :class:`ginsfsm.gaplic.GAplicProcessWorker`
+* :class:`ginsfsm.gaplic.GAplicThreadWorker`
+
+.. _running-as-main-process:
+
+Running as main process
+------------------------
+
+For running as main process::
+
+    if __name__ == "__main__":
+        ga = GAplic()
+        ga.create_gobj('test', GPrincipal, None)
+        ga.mt_process()
+
+.. _running-as-thread:
+
+Running as thread
+------------------
+
+You can too run the :term:`gaplic` as a **thread** using
+the :func:`ginsfsm.gaplic.start_gaplic_thread` function::
+
+    if __name__ == "__main__":
+        # run server gaplic as thread
+        ga_srv = GAplic('ServerWorker')
+        ga_srv.create_gobj('server', GServerPrincipal, None)
+        srv_worker = start_gaplic_thread(ga_srv)
+
+        # run client gaplic as main process
+        ga_cli = GAplic('ClientWorker')
+        ga_cli.create_gobj('client', GClientPrincipal, None)
+
+        try:
+            ga_cli.mt_process()
+        except KeyboardInterrupt:
+            srv_worker.shutdown()
+            srv_worker.join()
+            print('Program stopped')
+
+.. _running-as-child-process:
+
+Running as child process
+------------------------
+
+And you can too run the :term:`gaplic` as a **child daemon process** using
+the :func:`ginsfsm.gaplic.start_gaplic_process` function::
+
+    if __name__ == "__main__":
+        # run server gaplic as child daemon process
+        ga_srv = GAplic('ServerProcess')
+        ga_srv.create_gobj('server', GServerPrincipal, None)
+        srv_worker = start_gaplic_process(ga_srv)
+
+        # run client gaplic as main process
+        ga_cli = GAplic('ClientProcess')
+        ga_cli.create_gobj('client', GClientPrincipal, None)
+
+        try:
+            ga_cli.mt_process()
+        except KeyboardInterrupt:
+            srv_worker.shutdown()
+            srv_worker.join()
+            print('Program stopped')
+
+.. _infinite-loop:
+
+Infinite loop
+-------------
+After create and initialize the :term:`gaplic`, you must call to
+the :meth:`ginsfsm.gaplic.GAplic.mt_process` function.
+It's the infinite loop where events, timers, etc are processed.
+
+Extra work in the main loop
+---------------------------
+
+You can subclass :class:`ginsfsm.gaplic.GAplic` and override
+the :meth:`ginsfsm.gaplic.GAplic.mt_subprocess` function to do extra work
+in the infinite loop.
+
+Using GObjs
+===========
+
+.. _creating-gclass:
+
+Creating new gclass types
+-------------------------
+
+To create a new :term:`gclass` type:
+
+#. Write a :term:`simple-machine`.
+#. Subclass the :class:`ginsfsm.gobj.GObj` class.
+#. Override the :meth:`ginsfsm.gobj.GObj.start_up` method.
+
+See :mod:`ginsfsm.smachine` module to learn how to build
+a :term:`simple-machine`::
+
+    class MyGClass(GObj):
+        def __init__(self):
+            super(MyGClass, self).__init__(SAMPLE_FSM)
+
+        def start_up(self):
+            """ Create gobj childs, initialize something...
+            """
+
+.. _creating-gobj:
+
+Creating gobjs
+--------------
+
+Creating :term:`gobj`'s must be done by
+the :meth:`ginsfsm.gaplic.GAplic.create_gobj` factory function
+of :class:`ginsfsm.gaplic.GAplic` class, because all :term:`gobj`'s belongs
+to a :term:`gaplic`'s domain:
+
+The communication between :term:`gobj`'s are through :term:`event`'s.
+The :term:`event`'s are sent from one :term:`gobj` to another :term:`gobj` using
+one of these functions:
+
+    * sending events by direct delivery: :ref:`send-event`.
+    * sending events by queues: :ref:`post-event`.
+    * sending events to subscribers: :ref:`broadcast-event`.
+
+.. _creating-event:
+
+Creating events
+---------------
+
+An :term:`event` can be:
+
+* any string name defined in the :term:`simple-machine`'s :term:`event-list`:
+
+    * Used in :ref:`send-event` method.
+
+* any instance of :class:`ginsfsm.gobj.Event` class.
+  This class is nothing more than a collection of event attributes:
+
+    * Used in :ref:`post-event` and :ref:`broadcast-event` methods.
+      You can to use the :func:`ginsfsm.gobj.event_factory` factory function to
+      create :term:`event`'s:
+
+.. _sending-events:
+
+Sending events
+--------------
+
+There are three ways to send an event:
+
+* :ref:`send-event`.
+* :ref:`post-event`.
+* :ref:`broadcast-event`.
+
+.. _send-event:
+
+send_event
+^^^^^^^^^^
+
+Send **right now** the :term:`event-name` to the destination gobj,
+with associated data.
+
+This event has only one :term:`gobj` destination.
+
+The returned value is the return value from the executed action.
+
+See :meth:`ginsfsm.gobj.GObj.send_event`.
+
+.. _post-event:
+
+post_event
+^^^^^^^^^^
+
+Send an :term:`event` in the **next cycle** of the :term:`gaplic` infinite loop.
+
+This event has only one :term:`gobj` destination.
+
+See :meth:`ginsfsm.gobj.GObj.post_event`.
+
+.. _broadcast-event:
+
+broadcast_event
+^^^^^^^^^^^^^^^
+
+Broadcast the :term:`event` to all subscribers.
+
+This is a more general function than send_event or post_event.
+It's useful when you don't have a direct relation with the :term:`gobj` to whom
+send the event.
+
+See :meth:`ginsfsm.gobj.GObj.broadcast_event`.
+
+.. _receiving-events:
+
+Receving events
+---------------
+
+You can receive events directy from gobj childs, or from any gobj by
+subscription mode.
+
+.. _subscription:
+
+Subcription
+^^^^^^^^^^^
+
+You can receive the events of an :term:`gobj` by subscribing them using
+the function :meth:`ginsfsm.gobj.GObj.subscribe_event`:
+
+.. _filtering-events:
+
+Filtering events
+^^^^^^^^^^^^^^^^
+
+You can set a filter function
+with :meth:`ginsfsm.gobj.GObj.set_owned_event_filter` method to check is
+some subscriptor wants to own the event.
+
+The function will be used to check the returned value of an :term:`action`.
+If the returned value by owned_event_filter function is ``True``,
+the :func:`ginsfsm.gobj.GObj.broadcast_event` function doesn't continue
+sending the event to other subscribers.

File docs/src/examples/ongconnex.rst

+:mod:`ginsfsm.examples.ongconnex`
+=================================
+
+.. automodule:: ginsfsm.examples.ongconnex

File docs/src/examples/ongsock.rst

+:mod:`ginsfsm.examples.ongsock`
+===============================
+
+.. automodule:: ginsfsm.examples.ongsock

File docs/src/examples/ontimer.rst

+:mod:`ginsfsm.examples.ontimer`
+===============================
+
+.. automodule:: ginsfsm.examples.ontimer

File docs/src/examples/stress_client_echo.rst

+:mod:`ginsfsm.examples.stress_client_echo`
+==========================================
+
+.. automodule:: ginsfsm.examples.stress_client_echo

File docs/src/examples/stress_connections.rst

+:mod:`ginsfsm.examples.stress_connections`
+==========================================
+
+.. automodule:: ginsfsm.examples.stress_connections

File docs/src/examples/stress_server_echo.rst

+:mod:`ginsfsm.examples.stress_server_echo`
+==========================================
+
+.. automodule:: ginsfsm.examples.stress_server_echo

File docs/src/examples/wsgi_server.rst

+:mod:`ginsfsm.examples.wsgi_server`
+===================================
+
+.. automodule:: ginsfsm.examples.wsgi_server

File docs/watch.sh

+# watch the sources and build automatically the doc when they change
+# Dependencies: watchdog
+
+make html
+watchmedo shell-command \
+    --patterns="*.py;*.rst" \
+    --recursive \
+    --command='make html' \
+    . ../ginsfsm

File ginsfsm/__init__.py

+# -*- encoding: utf-8 -*-
+"""
+A python library to do development based in Finite State Machines.
+"""
+__version__ = '0.3.0'
+__author__ = 'Ginés Martínez Sánchez',
+__author_email__ = 'ginsmar at artgins.com',

File ginsfsm/buffers.py

+##############################################################################
+#
+# Copyright (c) 2001-2004 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Buffers
+"""
+from io import BytesIO
+
+# copy_bytes controls the size of temp. strings for shuffling data around.
+COPY_BYTES = 1 << 18  # 256K
+
+# The maximum number of bytes to buffer in a simple string.
+STRBUF_LIMIT = 8192
+
+
+class FileBasedBuffer(object):
+    remain = 0
+
+    def __init__(self, file, from_buffer=None):
+        self.file = file
+        if from_buffer is not None:
+            from_file = from_buffer.getfile()
+            read_pos = from_file.tell()
+            from_file.seek(0)
+            while 1:
+                data = from_file.read(COPY_BYTES)
+                if not data:
+                    break
+                file.write(data)
+            self.remain = int(file.tell() - read_pos)
+            from_file.seek(read_pos)
+            file.seek(read_pos)
+
+    def __len__(self):
+        return self.remain
+
+    def __nonzero__(self):
+        return self.remain > 0
+
+    __bool__ = __nonzero__  # py3
+
+    def append(self, s):
+        file = self.file
+        read_pos = file.tell()
+        file.seek(0, 2)
+        file.write(s)
+        file.seek(read_pos)
+        self.remain = self.remain + len(s)
+
+    def get(self, numbytes=-1, skip=False):
+        file = self.file
+        if not skip:
+            read_pos = file.tell()
+        if numbytes < 0:
+            # Read all
+            res = file.read()
+        else:
+            res = file.read(numbytes)
+        if skip:
+            self.remain -= len(res)
+        else:
+            file.seek(read_pos)
+        return res
+
+    def skip(self, numbytes, allow_prune=0):
+        if self.remain < numbytes:
+            raise ValueError("Can't skip %d bytes in buffer of %d bytes" % (
+                numbytes, self.remain)
+                )
+        self.file.seek(numbytes, 1)
+        self.remain = self.remain - numbytes
+
+    def newfile(self):
+        raise NotImplementedError()
+
+    def prune(self):
+        file = self.file
+        if self.remain == 0:
+            read_pos = file.tell()
+            file.seek(0, 2)
+            sz = file.tell()
+            file.seek(read_pos)
+            if sz == 0:
+                # Nothing to prune.
+                return
+        nf = self.newfile()
+        while 1:
+            data = file.read(COPY_BYTES)
+            if not data:
+                break
+            nf.write(data)
+        self.file = nf
+
+    def getfile(self):
+        return self.file
+
+    def _close(self):
+        # named _close because ReadOnlyFileBasedBuffer is used as
+        # wsgi file.wrapper, and its protocol reserves "close"
+        if hasattr(self.file, 'close'):
+            self.file.close()
+        self.remain = 0
+
+
+class TempfileBasedBuffer(FileBasedBuffer):
+
+    def __init__(self, from_buffer=None):
+        FileBasedBuffer.__init__(self, self.newfile(), from_buffer)
+
+    def newfile(self):
+        from tempfile import TemporaryFile
+        return TemporaryFile('w+b')
+
+
+class BytesIOBasedBuffer(FileBasedBuffer):
+
+    def __init__(self, from_buffer=None):
+        if from_buffer is not None:
+            FileBasedBuffer.__init__(self, BytesIO(), from_buffer)
+        else:
+            # Shortcut. :-)
+            self.file = BytesIO()
+
+    def newfile(self):
+        return BytesIO()
+
+
+class ReadOnlyFileBasedBuffer(FileBasedBuffer):
+    # used as wsgi.file_wrapper
+    def __init__(self, file, block_size=32768):
+        self.file = file
+        self.block_size = block_size  # for __iter__
+
+    def prepare(self, size=None):
+        if (hasattr(self.file, 'seek') and
+             hasattr(self.file, 'tell')):
+            start_pos = self.file.tell()
+            self.file.seek(0, 2)
+            end_pos = self.file.tell()
+            self.file.seek(start_pos)
+            fsize = end_pos - start_pos
+            if size is None:
+                self.remain = fsize
+            else:
+                self.remain = min(fsize, size)
+        elif hasattr(self.file, 'close'):
+            # called by task if self.filelike has no seek/tell
+            self.close = self.file.close
+        return self.remain
+
+    def get(self, numbytes=-1, skip=False):
+        # never read more than self.remain (it can be user-specified)
+        if numbytes == -1 or numbytes > self.remain:
+            numbytes = self.remain
+        file = self.file
+        if not skip:
+            read_pos = file.tell()
+        res = file.read(numbytes)
+        if skip:
+            self.remain -= len(res)
+        else:
+            file.seek(read_pos)
+        return res
+
+    def __iter__(self):  # called by task if self.filelike has no seek/tell
+        return self
+
+    def next(self):
+        val = self.file.read(self.block_size)
+        if not val:
+            raise StopIteration
+        return val
+
+    __next__ = next  # py3
+
+    def append(self, s):
+        raise NotImplementedError
+
+
+class OverflowableBuffer(object):
+    """
+    This buffer implementation has four stages:
+    - No data
+    - String-based buffer
+    - StringIO-based buffer
+    - Temporary file storage
+    The first two stages are fastest for simple transfers.
+    """
+
+    overflowed = False
+    buf = None
+    strbuf = b''  # Bytes-based buffer.
+
+    def __init__(self, overflow):
+        # overflow is the maximum to be stored in a StringIO buffer.
+        self.overflow = overflow
+
+    def __len__(self):
+        buf = self.buf
+        if buf is not None:
+            return len(buf)
+        else:
+            return len(self.strbuf)
+
+    def __nonzero__(self):
+        return bool(len(self))
+
+    __bool__ = __nonzero__  # py3
+
+    def _create_buffer(self):
+        strbuf = self.strbuf
+        if len(strbuf) >= self.overflow:
+            self._set_large_buffer()
+        else:
+            self._set_small_buffer()
+        buf = self.buf
+        if strbuf:
+            buf.append(self.strbuf)
+            self.strbuf = b''
+        return buf
+
+    def _set_small_buffer(self):
+        self.buf = BytesIOBasedBuffer(self.buf)
+        self.overflowed = False
+
+    def _set_large_buffer(self):
+        self.buf = TempfileBasedBuffer(self.buf)
+        self.overflowed = True
+
+    def append(self, s):
+        buf = self.buf
+        if buf is None:
+            strbuf = self.strbuf
+            if len(strbuf) + len(s) < STRBUF_LIMIT:
+                self.strbuf = strbuf + s
+                return
+            buf = self._create_buffer()
+        buf.append(s)
+        sz = len(buf)
+        if not self.overflowed:
+            if sz >= self.overflow:
+                self._set_large_buffer()
+
+    def get(self, numbytes=-1, skip=False):
+        buf = self.buf
+        if buf is None:
+            strbuf = self.strbuf
+            if not skip:
+                return strbuf
+            buf = self._create_buffer()
+        return buf.get(numbytes, skip)
+
+    def skip(self, numbytes, allow_prune=False):
+        buf = self.buf
+        if buf is None:
+            if allow_prune and numbytes == len(self.strbuf):
+                # We could slice instead of converting to
+                # a buffer, but that would eat up memory in
+                # large transfers.