summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorjason kirtland <jek@discorporate.us>2010-02-15 16:35:48 -0800
committerjason kirtland <jek@discorporate.us>2010-02-15 16:35:48 -0800
commit73e7d1d2dfff8a6103faad7ee608083231c28be6 (patch)
tree81f38a8ae017339451601922566f1eb6d241f94c /docs
parentc4579f81ac5490a5722678c01c0fc9e0589a4d5b (diff)
downloadblinker-73e7d1d2dfff8a6103faad7ee608083231c28be6.tar.gz
Sphinx documentation.
Diffstat (limited to 'docs')
-rw-r--r--docs/source/Makefile45
-rw-r--r--docs/source/api.rst39
-rw-r--r--docs/source/conf.py206
-rw-r--r--docs/source/index.rst42
-rw-r--r--docs/source/signals.rst233
5 files changed, 565 insertions, 0 deletions
diff --git a/docs/source/Makefile b/docs/source/Makefile
new file mode 100644
index 0000000..d524eb7
--- /dev/null
+++ b/docs/source/Makefile
@@ -0,0 +1,45 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS =
+SPHINXBUILD = sphinx-build
+
+# Internal variables.
+ALLSPHINXOPTS = -d ../doctrees $(SPHINXOPTS) .
+
+help:
+ @echo "Please use \`make <target>' where <target> is one of"
+ @echo " html to make standalone HTML files"
+ @echo " text to make standalone text files"
+ @echo " sdist to build documentation for release"
+ @echo " doctest to run doctests"
+ @echo " pickles to build pickles"
+ @echo " clean to remove generated artifacts"
+
+sdist: clean text html
+
+clean:
+ for i in doctrees html text doctest pickles; do \
+ rm -rf ../$$i; \
+ done
+
+html:
+ mkdir -p ../html ../doctrees _static _template
+ $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) ../html
+ @echo
+ @echo "Build finished. The HTML pages are in ../html."
+
+text:
+ mkdir -p ../text ../doctrees
+ $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) ../text
+ @echo
+ @echo "Build finished. The text pages are in ../text."
+
+doctest:
+ mkdir -p ../doctrees ../doctest
+ $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) ../doctest
+
+pickles:
+ mkdir -p ../pickles ../doctest
+ $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) ../pickles
diff --git a/docs/source/api.rst b/docs/source/api.rst
new file mode 100644
index 0000000..e80684d
--- /dev/null
+++ b/docs/source/api.rst
@@ -0,0 +1,39 @@
+.. _api:
+
+API Documentation
+=================
+
+All public API members can (and should) be imported from ``blinker``::
+
+ from blinker import ANY, signal
+
+.. currentmodule:: blinker.base
+
+Basic Signals
+-------------
+
+.. autoattribute:: blinker.base.ANY
+
+.. autoattribute:: blinker.base.receiver_connected
+
+.. autoclass:: Signal
+ :members:
+ :undoc-members:
+
+Named Signals
+-------------
+
+.. function:: signal(name, doc=None)
+
+ Return the :class:`NamedSignal` *name*, creating it if required.
+
+ Repeated calls to this function will return the same signal object.
+ Signals are created in a global :class:`Namespace`.
+
+.. autoclass:: NamedSignal
+ :show-inheritance:
+ :members:
+
+.. autoclass:: Namespace
+ :show-inheritance:
+ :members: signal
diff --git a/docs/source/conf.py b/docs/source/conf.py
new file mode 100644
index 0000000..c4adb72
--- /dev/null
+++ b/docs/source/conf.py
@@ -0,0 +1,206 @@
+# -*- coding: utf-8 -*-
+#
+# Blinker documentation build configuration file, created by
+# sphinx-quickstart on Mon Feb 15 10:54:13 2010.
+#
+# This file is execfile()d with the current directory set to its containing
+# dir.
+
+import os
+import sys
+
+# 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.append(os.path.abspath('../../'))
+
+# -- 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 = ['sphinx.ext.autodoc',
+ 'sphinx.ext.doctest',
+ 'sphinx.ext.coverage']
+
+# 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'Blinker'
+copyright = u'2010, Jason Kirtland'
+
+# 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.
+version = '0.9'
+# The full version, including alpha/beta/rc tags.
+release = '0.9dev'
+
+# 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 documents that shouldn't be included in the build.
+#unused_docs = []
+
+# List of directories, relative to source directory, that shouldn't be searched
+# for source files.
+exclude_trees = []
+
+autoclass_content = "both"
+autodoc_member_order = "groupwise"
+import sphinx.ext.autodoc
+sphinx.ext.autodoc.AttributeDocumenter.member_order = 25
+sphinx.ext.autodoc.InstanceAttributeDocumenter.member_order = 26
+
+
+# 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. Major themes that come with
+# Sphinx are currently 'default' and 'sphinxdoc'.
+html_theme = 'default'
+
+# 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.
+#html_theme_path = []
+
+# 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_use_modindex = 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 = ''
+
+# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = ''
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'Blinkerdoc'
+
+
+# -- Options for LaTeX output --------------------------------------------------
+
+# The paper size ('letter' or 'a4').
+#latex_paper_size = 'letter'
+
+# The font size ('10pt', '11pt' or '12pt').
+#latex_font_size = '10pt'
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+ ('index', 'Blinker.tex', u'Blinker Documentation',
+ u'Jason Kirtland', '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
+
+# Additional stuff for the LaTeX preamble.
+#latex_preamble = ''
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_use_modindex = True
diff --git a/docs/source/index.rst b/docs/source/index.rst
new file mode 100644
index 0000000..8a594bc
--- /dev/null
+++ b/docs/source/index.rst
@@ -0,0 +1,42 @@
+Blinker Documentation
+=====================
+
+Blinker provides fast & simple object-to-object and broadcast
+signaling for Python objects.
+
+The core of Blinker is quite small but provides powerful features:
+
+ - a global registry of named signals
+ - anonymous signals
+ - custom name registries
+ - permanently or temporarily connected receivers
+ - automatically disconnected receivers via weak referencing
+ - sending arbitrary data payloads
+ - collecting return values from signal receivers
+
+
+Requirements
+------------
+
+Python 2.4 or later. No other modules are required.
+
+As of Blinker 0.8, Python 3.1 passes all tests except for weakly
+binding to instance methods.
+
+
+License
+-------
+
+Blinker is provided under the MIT License.
+
+
+Contents
+--------
+
+.. toctree::
+ :maxdepth: 2
+
+ signals
+ api
+
+
diff --git a/docs/source/signals.rst b/docs/source/signals.rst
new file mode 100644
index 0000000..8bb967a
--- /dev/null
+++ b/docs/source/signals.rst
@@ -0,0 +1,233 @@
+=======
+Signals
+=======
+
+.. currentmodule:: blinker.base
+
+Decoupling With Named Signals
+-----------------------------
+
+Named signals are created with :func:`signal`:
+
+.. doctest::
+
+ >>> from blinker import signal
+ >>> initialized = signal('initialized')
+ >>> initialized is signal('initialized')
+ True
+
+Every call to ``signal('name')`` returns the same signal object,
+allowing unconnected parts of code (different modules, plugins,
+anything) to all use the same signal without requiring any code
+sharing or special imports.
+
+
+Subscribing to Signals
+----------------------
+
+:meth:`Signal.connect` registers a function to be invoked each time
+the signal is emitted. Connected functions are always passed the
+object that caused the signal to be emitted.
+
+.. doctest::
+
+ >>> def subscriber(sender):
+ ... print("Got a signal sent by %r" % sender)
+ ...
+ >>> ready = signal('ready')
+ >>> ready.connect(subscriber)
+ <function subscriber at 0x...>
+
+
+Emitting Signals
+----------------
+
+Code producing events of interest can :meth:`Signal.send`
+notifications to all connected receivers.
+
+Below, a simple ``Processor`` class emits a ``ready`` signal when it's
+about to process something, and ``complete`` when it is done. It
+passes ``self`` to the :meth:`~Signal.send` method, signifying that
+that particular instance was responsible for emitting the signal.
+
+.. doctest::
+
+ >>> class Processor:
+ ... def __init__(self, name):
+ ... self.name = name
+ ...
+ ... def go(self):
+ ... ready = signal('ready')
+ ... ready.send(self)
+ ... print("Processing.")
+ ... complete = signal('complete')
+ ... complete.send(self)
+ ...
+ ... def __repr__(self):
+ ... return '<Processor %s>' % self.name
+ ...
+ >>> processor_a = Processor('a')
+ >>> processor_a.go()
+ Got a signal sent by <Processor a>
+ Processing.
+
+Notice the ``complete`` signal in ``go()``? No receivers have
+connected to ``complete`` yet, and that's a-ok. Calling
+:meth:`~Signal.send` on a signal with no receivers will result in no
+notifications being sent, and these no-op sends are optimized to be as
+inexpensive as possible.
+
+
+Subscribing to Specific Senders
+-------------------------------
+
+The default connection to a signal invokes the receiver function when
+any sender emits it. The :meth:`Signal.connect` function accepts an
+optional argument to restrict the subscription to one specific sending
+object:
+
+.. doctest::
+
+ >>> def b_subscriber(sender):
+ ... print("Caught signal from processor_b.")
+ ... assert sender.name == 'b'
+ ...
+ >>> processor_b = Processor('b')
+ >>> ready.connect(b_subscriber, sender=processor_b)
+ <function b_subscriber at 0x...>
+
+This function has been subscribed to ``ready`` but only when sent by
+``processor_b``:
+
+.. doctest::
+
+ >>> processor_a.go()
+ Got a signal sent by <Processor a>
+ Processing.
+ >>> processor_b.go()
+ Got a signal sent by <Processor b>
+ Caught signal from processor_b.
+ Processing.
+
+
+Sending and Receiving Data Through Signals
+------------------------------------------
+
+Additional keyword arguments can be passed to :meth:`~Signal.send`.
+These will in turn be passed to the connected functions:
+
+.. doctest::
+
+ >>> send_data = signal('send-data')
+ >>> @send_data.connect
+ ... def receive_data(sender, **kw):
+ ... print("Caught signal from %r, data %r" % (sender, kw))
+ ... return 'received!'
+ ...
+ >>> result = send_data.send('anonymous', abc=123)
+ Caught signal from 'anonymous', data {'abc': 123}
+
+The return value of :meth:`~Signal.send` collects the return values of
+each connected function as a list of (``receiver function``, ``return
+value``) pairs:
+
+.. doctest::
+
+ >>> result
+ [(<function receive_data at 0x...>, 'received!')]
+
+
+Anonymous Signals
+-----------------
+
+Signals need not be named. The :class:`Signal` constructor creates a
+unique signal each time it is invoked. For example, an alternative
+implementation of the Processor from above might provide the
+processing signals as class attributes:
+
+.. doctest::
+
+ >>> from blinker import Signal
+ >>> class AltProcessor:
+ ... on_ready = Signal()
+ ... on_complete = Signal()
+ ...
+ ... def __init__(self, name):
+ ... self.name = name
+ ...
+ ... def go(self):
+ ... self.on_ready.send(self)
+ ... print("Alternate processing.")
+ ... self.on_complete.send(self)
+ ...
+ ... def __repr__(self):
+ ... return '<AltProcessor %s>' % self.name
+ ...
+
+``connect`` as a Decorator
+--------------------------
+
+You may have noticed the return value of :meth:`~Signal.connect` in
+the console output in the sections above. This allows ``connect`` to
+be used as a decorator on functions:
+
+.. doctest::
+
+ >>> apc = AltProcessor('c')
+ >>> @apc.on_complete.connect
+ ... def completed(sender):
+ ... print "AltProcessor %s completed!" % sender.name
+ ...
+ >>> apc.go()
+ Alternate processing.
+ AltProcessor c completed!
+
+While convenient, this form unfortunately does not allow the
+``sender`` or ``weak`` arguments to be customized for the connected
+function.
+
+
+Optimizing Signal Sending
+-------------------------
+
+Signals are optimized to send very quickly, whether receivers are
+connected or not. If the data to be sent down a signal is very
+expensive, it can be more efficient to check to see if any receivers
+are connected first by testing the :attr:`~Signal.receivers` property:
+
+.. doctest::
+
+ >>> bool(signal('ready').receivers)
+ True
+ >>> bool(signal('complete').receivers)
+ False
+ >>> bool(AltProcessor.on_complete.receivers)
+ True
+
+Checking for a receiver listening for a particular sender is also
+possible:
+
+.. doctest::
+
+ >>> signal('ready').has_receivers_for(processor_a)
+ True
+
+Documenting Signals
+-------------------
+
+Both named and anonymous signals can be passed a ``doc`` argument at
+construction to set the pydoc help text for the signal. This
+documentation will be picked up by most documentation generators (such
+as sphinx) and is nice for documenting any additional data parameters
+that will be sent down with the signal.
+
+See the documentation of the :obj:`receiver_connected` built-in signal
+for an example.
+
+More
+----
+
+Disconnecting receivers from signals, introspection of connected
+receivers, private namespaces for named signals and more are discussed
+in the :ref:`api`.
+