PROTON-2086: Changed API documentation from epydoc to Sphinx

PROTON-2086: Fixed some issues in cmake as pointed out by astitcher, removed unneeded makefile and removed a trailing comma in a list.

PROTON-2086: Final modifications to docs as part of a PR. Incorporated feedback from PR.
diff --git a/c/include/proton/codec.h b/c/include/proton/codec.h
index 1755f53..cc2e2f2 100644
--- a/c/include/proton/codec.h
+++ b/c/include/proton/codec.h
@@ -91,12 +91,12 @@
   PN_CHAR = 9,
 
   /**
-   * The ulong AMQP type. An unsigned 32 bit integer.
+   * The ulong AMQP type. An unsigned 64 bit integer.
    */
   PN_ULONG = 10,
 
   /**
-   * The long AMQP type. A signed 32 bit integer.
+   * The long AMQP type. A signed 64 bit integer.
    */
   PN_LONG = 11,
 
@@ -1104,7 +1104,7 @@
 PN_EXTERN pn_timestamp_t pn_data_get_timestamp(pn_data_t *data);
 
 /**
- * If the current node is a float, returns its value, raises 0
+ * If the current node is a float, returns its value, returns 0
  * otherwise.
  *
  * @param data a pn_data_t object
diff --git a/c/include/proton/event.h b/c/include/proton/event.h
index 611b65c..8d62d6b 100644
--- a/c/include/proton/event.h
+++ b/c/include/proton/event.h
@@ -163,7 +163,7 @@
 
   /**
    * The local session endpoint has been opened. Events of this type
-   * point ot the relevant session.
+   * point to the relevant session.
    */
   PN_SESSION_LOCAL_OPEN,
 
@@ -212,7 +212,7 @@
 
   /**
    * The local link endpoint has been closed. Events of this type
-   * point ot the relevant link.
+   * point to the relevant link.
    */
   PN_LINK_LOCAL_CLOSE,
 
diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt
index 1423a37..ffac0e5 100644
--- a/python/CMakeLists.txt
+++ b/python/CMakeLists.txt
@@ -118,35 +118,26 @@
 py_compile(${CMAKE_CURRENT_BINARY_DIR} ${pysrc-generated} CPROTON_ARTIFACTS)
 py_compile(${CMAKE_CURRENT_SOURCE_DIR} "${pysrc}" PROTON_ARTIFACTS)
 
-find_program(EPYDOC_EXE epydoc)
-mark_as_advanced (EPYDOC_EXE)
-if (EPYDOC_EXE)
-   foreach (py_src_doc ${pysrc})
-     list(APPEND PY_DOC_FILES "${CMAKE_CURRENT_SOURCE_DIR}/${py_src_doc}")
-   endforeach(py_src_doc)
-   add_custom_target(docs-py
-     COMMAND ${PN_ENV_SCRIPT} -- PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}:${CMAKE_CURRENT_SOURCE_DIR}
-             ${EPYDOC_EXE} -v --no-private --html -o ${CMAKE_CURRENT_BINARY_DIR}/html ${PY_DOC_FILES}
-     DEPENDS ${SWIG_MODULE_${cproton}_REAL_NAME})
-   add_dependencies(docs docs-py)
-   install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/html/"
-           DESTINATION "${PROTON_SHARE}/docs/api-py"
-           COMPONENT documentation
-           OPTIONAL)
-endif (EPYDOC_EXE)
-
-find_program(SPHINX_EXE sphinx-build)
-mark_as_advanced (SPHINX_EXE)
-if (SPHINX_EXE)
-   add_custom_target(tutorial-py
-     COMMAND ${PN_ENV_SCRIPT} -- PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}:${CMAKE_CURRENT_SOURCE_DIR}
-     ${SPHINX_EXE} -b html ${CMAKE_CURRENT_SOURCE_DIR}/docs ${CMAKE_CURRENT_BINARY_DIR}/tutorial)
-   add_dependencies(docs tutorial-py)
-   install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/tutorial/"
-           DESTINATION "${PROTON_SHARE}/docs/tutorial-py"
-           COMPONENT documentation
-           OPTIONAL)
-endif (SPHINX_EXE)
+# Sphinx documentation
+check_python_module("sphinx" SPHINX_MODULE_FOUND)
+if (SPHINX_MODULE_FOUND)
+    message(STATUS "Python Sphinx module found - doc generation enabled.")
+    add_custom_target(docs-py
+        COMMAND ${PN_ENV_SCRIPT} --
+        PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}:${CMAKE_CURRENT_SOURCE_DIR}
+        LD_LIBRARY_PATH="${CMAKE_CURRENT_BINARY_DIR}/c"
+        ${PYTHON_EXECUTABLE} -m sphinx "${CMAKE_CURRENT_SOURCE_DIR}/docs" "${CMAKE_CURRENT_BINARY_DIR}/docs")
+    add_dependencies(docs docs-py)
+    install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/docs/"
+            DESTINATION "${PROTON_SHARE}/docs/api-py"
+            COMPONENT documentation
+            OPTIONAL)
+else ()
+    execute_process(COMMAND ${PYTHON_EXECUTABLE} --version
+                    ERROR_VARIABLE PYTHYON_VERSION_ERR)
+    string(STRIP ${PYTHYON_VERSION_ERR} PYTHON_VERSION_STR)
+    message(WARNING "Sphinx module NOT found for ${PYTHON_VERSION_STR} - doc generation disabled.")
+endif ()
 
 install(FILES ${CPROTON_ARTIFACTS}
         DESTINATION ${PYTHON_SITEARCH_PACKAGES}
@@ -162,7 +153,7 @@
         COMPONENT Python
         USE_SOURCE_PERMISSIONS)
 
-set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "html;tutorial")
+set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES docs)
 
 #
 # Set up the directory 'dist' for building the python native package
diff --git a/python/docs/conf.py b/python/docs/conf.py
index 891fd54..edd613e 100644
--- a/python/docs/conf.py
+++ b/python/docs/conf.py
@@ -1,242 +1,194 @@
 # -*- coding: utf-8 -*-
 #
-# Apache Qpid Proton documentation build configuration file, created by
-# sphinx-quickstart on Mon Feb 16 14:13:09 2015.
+# Configuration file for the Sphinx documentation builder.
 #
-# 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.
+# This file does only contain a selection of the most common options. For a
+# full list see the documentation:
+# http://www.sphinx-doc.org/en/master/config
 
-import sys, os
+# -- 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.
-#sys.path.insert(0, os.path.abspath('.'))
 
-# -- General configuration -----------------------------------------------------
+import os
+import sys
+sys.path.insert(0, os.path.abspath('../python'))
+
+# -- Project information -----------------------------------------------------
+
+project = 'Qpid Proton Python API'
+copyright = '2019, Apache Qpid Contributors'
+author = 'Apache Qpid Contributors'
+
+# The short X.Y version
+version = '0.0'
+# The full version, including alpha/beta/rc tags
+release = '0.0'
+# Read version from VERSION.txt file in Proton top level directory
+try:
+    ver_file_path = os.path.abspath('../../VERSION.txt')
+    with open(ver_file_path, 'r') as ver_file:
+        ver_str = ver_file.read().replace('\n', '')
+        if '-' in ver_str:
+            version = ver_str.split("-")[0] # Strip '-SNAPSHOT' from end of string
+        else:
+            version = ver_str;
+        release = version
+    print('Proton version: %s' % version)
+except IOError:
+    print('WARNING: Proton version file %s not found.' % ver_file_path)
+
+
+# -- General configuration ---------------------------------------------------
 
 # If your documentation needs a minimal Sphinx version, state it here.
-#needs_sphinx = '1.0'
+#
+# 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.todo']
+# 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_automodapi.automodapi', # needed for the module summaries (.. autosummary::)
+    'sphinx.ext.autodoc',
+    'sphinx.ext.viewcode',
+]
 
 # Add any paths that contain templates here, relative to this directory.
-#templates_path = ['_templates']
+templates_path = ['_templates']
 
-# The suffix of source filenames.
+# The suffix(es) of source filenames.
+# You can specify multiple suffix as a list of string:
+#
+# source_suffix = ['.rst', '.md']
 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'Apache Qpid Proton'
-copyright = u'2015-2019, Apache Qpid'
-
-# 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.30.0'
-# The full version, including alpha/beta/rc tags.
-release = '0.30.0-SNAPSHOT'
-
 # 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'
+#
+# This is also used if you do content translation via gettext catalogs.
+# Usually you set "language" from the command line for these cases.
+language = None
 
 # List of patterns, relative to source directory, that match files and
 # directories to ignore when looking for source files.
-exclude_patterns = []
-
-# 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
+# This pattern also affects html_static_path and html_extra_path .
+exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
 
 # 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 ---------------------------------------------------
+# -- 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'
 
 # 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
+#
+# html_theme_options = {}
 
 # 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']
+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'
+# Custom sidebar templates, must be a dictionary that maps document names
+# to template names.
+#
+# The default sidebars (for documents that don't match any pattern) are
+# defined by theme itself.  Builtin themes are using these templates by
+# default: ``['localtoc.html', 'relations.html', 'sourcelink.html',
+# 'searchbox.html']``.
+#
+# html_sidebars = {}
 
-# 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
+# -- Options for HTMLHelp output ---------------------------------------------
 
 # Output file base name for HTML help builder.
-htmlhelp_basename = 'ApacheQpidProtondoc'
+htmlhelp_basename = 'QpidProtonPythonAPIdoc'
 
 
-# -- Options for LaTeX output --------------------------------------------------
+# -- Options for LaTeX output ------------------------------------------------
 
 latex_elements = {
-# The paper size ('letterpaper' or 'a4paper').
-#'papersize': 'letterpaper',
+    # The paper size ('letterpaper' or 'a4paper').
+    #
+    # 'papersize': 'letterpaper',
 
-# The font size ('10pt', '11pt' or '12pt').
-#'pointsize': '10pt',
+    # The font size ('10pt', '11pt' or '12pt').
+    #
+    # 'pointsize': '10pt',
 
-# Additional stuff for the LaTeX preamble.
-#'preamble': '',
+    # Additional stuff for the LaTeX preamble.
+    #
+    # 'preamble': '',
+
+    # Latex figure (float) alignment
+    #
+    # 'figure_align': 'htbp',
 }
 
 # Grouping the document tree into LaTeX files. List of tuples
-# (source start file, target name, title, author, documentclass [howto/manual]).
+# (source start file, target name, title,
+#  author, documentclass [howto, manual, or own class]).
 latex_documents = [
-  ('index', 'ApacheQpidProton.tex', u'Apache Qpid Proton Documentation',
-   u'The Apache Qpid Community', 'manual'),
+    (master_doc, 'QpidProtonPythonAPI.tex', 'Qpid Proton Python API Documentation',
+     'Apache Qpid Contributors', '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 --------------------------------------------
+# -- Options for manual page output ------------------------------------------
 
 # One entry per manual page. List of tuples
 # (source start file, name, description, authors, manual section).
 man_pages = [
-    ('index', 'apacheqpidproton', u'Apache Qpid Proton Documentation',
-     [u'The Apache Qpid Community'], 1)
+    (master_doc, 'qpidprotonpythonapi', 'Qpid Proton Python API Documentation',
+     [author], 1)
 ]
 
-# If true, show URL addresses after external links.
-#man_show_urls = False
 
-
-# -- Options for Texinfo output ------------------------------------------------
+# -- 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', 'ApacheQpidProton', u'Apache Qpid Proton Documentation',
-   u'The Apache Qpid Community', 'ApacheQpidProton', 'One line description of project.',
-   'Miscellaneous'),
+    (master_doc, 'QpidProtonPythonAPI', 'Qpid Proton Python API Documentation',
+     author, 'QpidProtonPythonAPI', '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
+# -- Options for Epub output -------------------------------------------------
 
-# How to display URL addresses: 'footnote', 'no', or 'inline'.
-#texinfo_show_urls = 'footnote'
+# Bibliographic Dublin Core info.
+epub_title = project
+epub_author = author
+epub_publisher = author
+epub_copyright = copyright
+
+# The unique identifier of the text. This can be a ISBN number
+# or the project homepage.
+#
+# epub_identifier = ''
+
+# A unique identification for the text.
+#
+# epub_uid = ''
+
+# A list of files that should not be packed into the epub file.
+epub_exclude_files = ['search.html']
+
+
+# -- Extension configuration -------------------------------------------------
diff --git a/python/docs/index.rst b/python/docs/index.rst
index 927762b..ad9fa48 100644
--- a/python/docs/index.rst
+++ b/python/docs/index.rst
@@ -1,11 +1,146 @@
-Apache Qpid Proton: python documentation
-========================================
+####################################
+Qpid Proton Python API Documentation
+####################################
 
-Contents:
+The Proton module provides a Python 2.7 and 3.x API for Qpid Proton. It enables a developer to write Python applications
+that send and receive AMQP messages.
 
+*******
+Modules
+*******
 .. toctree::
    :maxdepth: 2
 
-   tutorial
-   overview
+   proton
+   proton.handlers
+   proton.reactor
+   proton.utils
 
+*****************************************
+About AMQP and the Qpid Proton Python API
+*****************************************
+
+.. toctree::
+   :maxdepth: 1
+
+   overview
+   tutorial
+
+Key API Features
+================
+
+ * Event-driven API
+ * SSL/TLS secured communication
+ * SASL authentication
+ * Automatic reconnect and failover
+ * Seamless conversion between AMQP and Python data types
+ * AMQP 1.0
+
+Basic API Concepts
+==================
+
+The Qpid Python client API and library allows applications to send and receive AMQP messages. See :ref:`overview`
+for a more detailed explanation.
+
+Containers
+----------
+
+Messages are transferred between connected peers (or nodes) using **senders** and **receivers**. Each sender
+or receiver is established over a **connection**. Each connection is established between two unique **containers**,
+the entry point for the API. The container class :class:`proton.reactor.Container` is found in the ``proton.reactor``
+module.
+
+Connections
+-----------
+
+A **connection** object tracks the status of an AMQP connection. For applications which *don't* require either
+authorization or encryption, these may be automatically created by convenience methods
+:meth:`proton.reactor.Container.create_sender` and/or :meth:`proton.reactor.Container.create_receiver`.
+However, for applications which *do* require either of these services, a connection object should be created
+using the convenience method :meth:`proton.reactor.Container.connect`, providing the required parameters.
+This object should then be passed to the convenience methods :meth:`proton.reactor.Container.create_sender`
+and/or :meth:`proton.reactor.Container.create_receiver` as needed. The connection class may be found at
+:class:`proton.Connection`.
+
+Senders
+-------
+
+The peer that sends messages uses a **sender** to send messages, which includes the target queue or topic which is
+to receive the messages. The sender may be found at :class:`proton.Sender`. Note that senders are most commonly
+obtained by using the convenience method :meth:`proton.reactor.Container.create_sender`.
+
+Receivers
+---------
+
+The peer that receives messages uses a **receiver** to receive messages, and includes a source queue or topic from
+which to receive messages. The receiver may be found at :class:`proton.Receiver`. Note that senders are most commonly
+obtained by using the convenience method :meth:`proton.reactor.Container.create_receiver`.
+
+Message Delivery
+----------------
+
+The process of sending a message is known as **delivery**. Each sent message has a delivery object which tracks the
+status of the message as it is sent from the sender to the receiver. This also includes actions such as settling the
+delivery (ie causing the delivery status to be forgotten when it is no longer needed). The delivery class may be found
+at :class:`proton.Delivery`. The delivery object is most commonly obtained
+when a message-related event occurs through the event object. See `Event Handlers`_ below.
+
+Event Handlers
+--------------
+
+A **handler** is a class that handles events associated with the sending and receiving of messages. This includes
+callbacks for events such as the arrival of a new message, error conditions that might arise, and the closing
+of the connection over which messages are sent. An application developer must handle some key events to
+successfully send and receive messages. When an event handler callback is called by the library, an Event object is
+passed to it which contains an object associated with the event. For example,
+when a message is received, the event object will have the property ``event.message`` by which the message itself may
+be obtained. See :class:`proton.Event` for more details.
+
+The following are some of the important event callbacks that may be implemented by a developer:
+
+* **on_start()**: This indicates that the event loop in the container has started, and that a new sender and/or
+    receiver may now be created.
+
+To send a message, the following events may need to be handled:
+
+* **on_sendable()**: This callback indicates that send credit has now been set by the receiver, and that a message may
+    now be sent.
+* **on_accepted()**: This callback indicates that a message has been received and accepted by the receiving peer.
+
+To receive a message, the following event may need to be handled:
+
+* **on_message()**: This callback indicates that a message has been received. The message and its delivery object may
+    be retreived, and if needed, the message can be either accepted or rejected.
+
+Many other events exist for the handling of transactions and other message events and errors, and if present in
+your handler will be called as the corresponding events arise. See the :ref:`tutorial` for examples of handling
+some other events.
+
+Several event handlers are provided which provide default behavior for most events. These may be found in the
+``proton.handlers`` module. The :class:`proton.handlers.MessagingHandler` is the most commonly used handler for
+non-transactional applications. Developers would typically directly inherit from this handler to provide the
+application's event behavior, and override callbacks as needed to provide additional behavior they may require.
+
+Examples
+--------
+
+Several examples may be found in the
+`Apache Qpid Proton Examples <https://qpid.apache.org/releases/qpid-proton-0.28.0/proton/python/examples/index.html>`_
+whcih illustrate the techniques and concepts of sending messages. They are also present in the source. These make
+an excellent starting point for developers new to this API. Make sure to read the README file, which gives
+instructions on how to run them and a brief explanation of each example.
+
+Tutorial
+--------
+
+See this :ref:`tutorial` on using the API.
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`search`
+
+.. * :ref:`modindex`
+    Can't get this to generate, so commenting out. Also, not that useful in this case, as modules are listed
+    in the contents above in full.
diff --git a/python/docs/overview.rst b/python/docs/overview.rst
index b11e163..66f5b24 100644
--- a/python/docs/overview.rst
+++ b/python/docs/overview.rst
@@ -1,3 +1,5 @@
+.. _overview:
+
 ############
 API Overview
 ############
@@ -56,6 +58,7 @@
     :show-inheritance: proton.reactor.Reactor
     :members: connect, create_receiver, create_sender, run, schedule
     :undoc-members:
+    :noindex:
 
     .. py:attribute:: container_id
 
@@ -74,22 +77,26 @@
     :members: open, close, state, session, hostname, container,
               remote_container, remote_desired_capabilities, remote_hostname, remote_offered_capabilities , remote_properties
     :undoc-members:
+    :noindex:
 
 .. autoclass:: proton.Receiver
     :show-inheritance: proton.Link
     :members: flow, recv, drain, draining
     :undoc-members:
+    :noindex:
 
 .. autoclass:: proton.Sender
     :show-inheritance: proton.Link
     :members: offered, send
     :undoc-members:
+    :noindex:
 
 .. autoclass:: proton.Link
     :members: name, state, is_sender, is_receiver,
               credit, queued, session, connection,
               source, target, remote_source, remote_target
     :undoc-members:
+    :noindex:
 
     The :py:meth:`~proton.Link.source()`,
     :py:meth:`~proton.Link.target()`,
@@ -102,6 +109,7 @@
     :members: update, settle, settled, remote_state, local_state, partial, readable, writable,
               link, session, connection
     :undoc-members:
+    :noindex:
 
 .. autoclass:: proton.handlers.MessagingHandler
     :members: on_start, on_reactor_init,
@@ -116,10 +124,12 @@
               on_disconnected,
               accept, reject, release, settle
     :undoc-members:
+    :noindex:
 
 .. autoclass:: proton.Event
     :members: delivery, link, receiver, sender, session, connection, reactor, context
     :undoc-members:
+    :noindex:
 
 .. autoclass:: proton.Message
     :members: address, id, priority, subject, ttl, reply_to, correlation_id, durable, user_id,
@@ -127,10 +137,12 @@
               group_id, group_sequence, reply_to_group_id,
               send, recv, encode, decode
     :undoc-members:
+    :noindex:
 
 .. autoclass:: proton.Terminus
     :members: address, dynamic, properties, capabilities, filter
     :undoc-members:
+    :noindex:
 
 .. _delivery-guarantees:
 
diff --git a/python/docs/proton.handlers.rst b/python/docs/proton.handlers.rst
new file mode 100644
index 0000000..662eb23
--- /dev/null
+++ b/python/docs/proton.handlers.rst
@@ -0,0 +1,76 @@
+##########################
+Module ``proton.handlers``
+##########################
+
+.. currentmodule:: proton.handlers
+
+Module Summary
+##############
+
+|
+
+.. autosummary::
+
+    MessagingHandler
+    TransactionHandler
+    TransactionalClientHandler
+
+|
+
+Exceptions
+==========
+
+|
+
+.. autosummary::
+
+    Reject
+    Release
+
+|
+
+Module Detail
+#############
+
+|
+
+.. autoclass:: proton.handlers.MessagingHandler
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+    :exclude-members: handlers, add
+
+------------
+
+.. autoclass:: proton.handlers.TransactionHandler
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+
+------------
+
+.. autoclass:: proton.handlers.TransactionalClientHandler
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+    :exclude-members: handlers, add
+
+------------
+
+.. autoclass:: proton.handlers.Reject
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+
+------------
+
+.. autoclass:: proton.handlers.Release
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+
diff --git a/python/docs/proton.reactor.rst b/python/docs/proton.reactor.rst
new file mode 100644
index 0000000..750f042
--- /dev/null
+++ b/python/docs/proton.reactor.rst
@@ -0,0 +1,186 @@
+#########################
+Module ``proton.reactor``
+#########################
+
+.. currentmodule:: proton.reactor
+
+Module Summary
+##############
+
+|
+
+.. autosummary::
+    Container
+    ApplicationEvent
+    EventInjector
+    Backoff
+    Transaction
+
+|
+
+Link Options
+============
+
+|
+
+The methods :meth:`Container.create_receiver` and :meth:`Container.create_sender` take one or more link options to allow the details of the links to be customized.
+
+.. autosummary::
+    LinkOption
+    ReceiverOption
+    SenderOption
+    AtLeastOnce
+    AtMostOnce
+    DynamicNodeProperties
+    Filter
+    Selector
+    DurableSubscription
+    Copy
+    Move
+
+|
+
+Module Detail
+#############
+
+|
+
+.. autoclass:: proton.reactor.ApplicationEvent
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+    :exclude-members: handler
+
+------------
+
+.. autoclass:: proton.reactor.AtLeastOnce
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+    :exclude-members: test
+
+------------
+
+.. autoclass:: proton.reactor.AtMostOnce
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+    :exclude-members: test
+
+------------
+
+.. autoclass:: proton.reactor.Backoff
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+
+------------
+
+.. autoclass:: proton.reactor.Container
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+    :exclude-members: on_error, global_handler, timeout, yield_, mark, now, handler, wakeup, start, quiesced, process, stop, stop_events, timer_tick, timer_deadline, acceptor, connection, connection_to_host, set_connection_host, get_connection_address, update, push_event
+
+------------
+
+.. autoclass:: proton.reactor.Copy
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+    :exclude-members: test
+
+------------
+
+.. autoclass:: proton.reactor.DurableSubscription
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+    :exclude-members: test
+
+------------
+
+.. autoclass:: proton.reactor.DynamicNodeProperties
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+    :exclude-members: test
+
+------------
+
+.. autoclass:: proton.reactor.EventInjector
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+
+------------
+
+.. autoclass:: proton.reactor.Filter
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+    :exclude-members: test
+
+------------
+
+.. autoclass:: proton.reactor.LinkOption
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+
+------------
+
+.. autoclass:: proton.reactor.Move
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+    :exclude-members: test
+
+------------
+
+.. autoclass:: proton.reactor.ReceiverOption
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+    :exclude-members: test
+
+------------
+
+.. autoclass:: proton.reactor.Selector
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+    :exclude-members: test
+
+------------
+
+.. autoclass:: proton.reactor.SenderOption
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+    :exclude-members: test
+
+------------
+
+.. autoclass:: proton.reactor.Transaction
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+    :exclude-members: declare, discharge, update, handle_outcome
+
diff --git a/python/docs/proton.rst b/python/docs/proton.rst
new file mode 100644
index 0000000..6d46099
--- /dev/null
+++ b/python/docs/proton.rst
@@ -0,0 +1,470 @@
+#################
+Module ``proton``
+#################
+
+.. currentmodule:: proton
+
+Module Summary
+##############
+
+|
+
+.. autosummary::
+
+    Condition
+    Connection
+    Data
+    Delivery
+    Disposition
+    Endpoint
+    Event
+    EventType
+    Link
+    Message
+    Receiver
+    SASL
+    Sender
+    Session
+    SSL
+    SSLDomain
+    SSLSessionDetails
+    Terminus
+    Transport
+    Url
+
+|
+
+Exceptions
+==========
+
+|
+
+.. autosummary::
+
+    ConnectionException
+    DataException
+    LinkException
+    MessageException
+    ProtonException
+    SessionException
+    SSLUnavailable
+    SSLException
+    Timeout
+    Interrupt
+    TransportException
+
+|
+
+AMQP Types
+==========
+
+|
+
+.. autosummary::
+    :nosignatures:
+
+    Array
+    byte
+    char
+    Described
+    decimal32
+    decimal64
+    decimal128
+    float32
+    int32
+    short
+    symbol
+    timestamp
+    ubyte
+    uint
+    ulong
+    ushort
+
+|
+
+Module Detail
+#############
+.. The following classes in the __all__ list are excluded (blacklisted):
+   * Collector
+
+|
+
+.. autoclass:: proton.Array
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+
+------------
+
+.. autoclass:: proton.Condition
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+
+------------
+
+.. autoclass:: proton.Connection
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+    :exclude-members: collect, wrap
+
+------------
+
+.. autoclass:: proton.ConnectionException
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+    :exclude-members: args
+
+------------
+
+.. autoclass:: proton.Data
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+    :exclude-members: get_mappings, lookup, put_mappings
+
+------------
+
+.. autoclass:: proton.DataException
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+    :exclude-members: args
+
+------------
+
+.. autoclass:: proton.Delivery
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+    :exclude-members: wrap
+
+------------
+
+.. autoclass:: proton.Disposition
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+
+------------
+
+.. autoclass:: proton.Described
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+
+------------
+
+.. autoclass:: proton.Endpoint
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+
+------------
+
+.. autoclass:: proton.Event
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+    :exclude-members: wrap
+
+------------
+
+.. autoclass:: proton.EventType
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+
+------------
+
+.. autoclass:: proton.Link
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+    :exclude-members: wrap
+
+------------
+
+.. autoclass:: proton.LinkException
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+    :exclude-members: args
+
+------------
+
+.. autoclass:: proton.Message
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+    :exclude-members: decode, encode
+
+------------
+
+.. autoclass:: proton.MessageException
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+    :exclude-members: args
+
+------------
+
+.. autoclass:: proton.ProtonException
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+    :exclude-members: args
+
+------------
+
+.. autoclass:: proton.Receiver
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+    :exclude-members: wrap
+
+------------
+
+.. autoclass:: proton.SASL
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+
+------------
+
+.. autoclass:: proton.Sender
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+    :exclude-members: wrap
+
+------------
+
+.. autoclass:: proton.Session
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+    :exclude-members: wrap
+
+------------
+
+.. autoclass:: proton.SessionException
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+    :exclude-members: args
+
+------------
+
+.. autoclass:: proton.SSL
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+
+------------
+
+.. autoclass:: proton.SSLDomain
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+
+------------
+
+.. autoclass:: proton.SSLSessionDetails
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+
+------------
+
+.. autoclass:: proton.SSLUnavailable
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+    :exclude-members: args
+
+------------
+
+.. autoclass:: proton.SSLException
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+    :exclude-members: args
+
+------------
+
+.. autoclass:: proton.Terminus
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+
+------------
+
+.. autoclass:: proton.Timeout
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+    :exclude-members: args
+
+------------
+
+.. autoclass:: proton.Interrupt
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+    :exclude-members: args
+
+------------
+
+.. autoclass:: proton.Transport
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+    :exclude-members: wrap
+
+------------
+
+.. autoclass:: proton.TransportException
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+    :exclude-members: args
+
+------------
+
+.. autoclass:: proton.Url
+    :members:
+    :show-inheritance:
+    :undoc-members:
+
+------------
+
+.. autoclass:: proton.byte
+    :members:
+    :show-inheritance:
+    :undoc-members:
+
+------------
+
+.. autoclass:: proton.char
+    :members:
+    :show-inheritance:
+    :undoc-members:
+
+------------
+
+.. autoclass:: proton.decimal32
+    :members:
+    :show-inheritance:
+    :undoc-members:
+
+------------
+
+.. autoclass:: proton.decimal64
+    :members:
+    :show-inheritance:
+    :undoc-members:
+
+------------
+
+.. autoclass:: proton.decimal128
+    :members:
+    :show-inheritance:
+    :undoc-members:
+
+------------
+
+.. autoclass:: proton.float32
+    :members:
+    :show-inheritance:
+    :undoc-members:
+
+------------
+
+.. autoclass:: proton.int32
+    :members:
+    :show-inheritance:
+    :undoc-members:
+
+------------
+
+.. autoclass:: proton.short
+    :members:
+    :show-inheritance:
+    :undoc-members:
+
+------------
+
+.. autoclass:: proton.symbol
+    :members:
+    :show-inheritance:
+    :undoc-members:
+
+------------
+
+.. autoclass:: proton.timestamp
+    :members:
+    :show-inheritance:
+    :undoc-members:
+
+------------
+
+.. autoclass:: proton.ubyte
+    :members:
+    :show-inheritance:
+    :undoc-members:
+
+------------
+
+.. autoclass:: proton.uint
+    :members:
+    :show-inheritance:
+    :undoc-members:
+
+------------
+
+.. autoclass:: proton.ulong
+    :members:
+    :show-inheritance:
+    :undoc-members:
+
+------------
+
+.. autoclass:: proton.ushort
+    :members:
+    :show-inheritance:
+    :undoc-members:
diff --git a/python/docs/proton.utils.rst b/python/docs/proton.utils.rst
new file mode 100644
index 0000000..8f2404d
--- /dev/null
+++ b/python/docs/proton.utils.rst
@@ -0,0 +1,93 @@
+#######################
+Module ``proton.utils``
+#######################
+
+.. currentmodule:: proton.utils
+
+Module Summary
+##############
+
+|
+
+.. autosummary::
+    BlockingConnection
+    BlockingSender
+    BlockingReceiver
+    SyncRequestResponse
+
+|
+
+Exceptions
+==========
+
+|
+
+.. autosummary::
+    SendException
+    LinkDetached
+    ConnectionClosed
+
+|
+
+Module Detail
+#############
+
+|
+
+.. autoclass:: proton.utils.BlockingConnection
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+    :exclude-members: on_transport_tail_closed, on_transport_head_closed, on_transport_closed
+
+------------
+
+.. autoclass:: proton.utils.BlockingSender
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+
+------------
+
+.. autoclass:: proton.utils.BlockingReceiver
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+
+------------
+
+.. autoclass:: proton.utils.ConnectionClosed
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+    :exclude-members: args, with_traceback
+
+------------
+
+.. autoclass:: proton.utils.LinkDetached
+    :members:
+    :show-inheritance:
+    :inherited-members:
+    :undoc-members:
+    :exclude-members: args, with_traceback
+
+------------
+
+.. autoclass:: proton.utils.SendException
+   :members:
+   :show-inheritance:
+   :inherited-members:
+   :undoc-members:
+   :exclude-members: args, with_traceback
+
+------------
+
+.. autoclass:: proton.utils.SyncRequestResponse
+   :members:
+   :show-inheritance:
+   :inherited-members:
+   :undoc-members:
diff --git a/python/docs/tutorial.rst b/python/docs/tutorial.rst
index 791cdd1..54334a0 100644
--- a/python/docs/tutorial.rst
+++ b/python/docs/tutorial.rst
@@ -1,3 +1,5 @@
+.. _tutorial:
+
 ########
 Tutorial
 ########
diff --git a/python/proton/__init__.py b/python/proton/__init__.py
index e40fac7..4e6b23f 100644
--- a/python/proton/__init__.py
+++ b/python/proton/__init__.py
@@ -23,10 +23,8 @@
 
 The proton APIs consist of the following classes:
 
- - L{Message}   -- A class for creating and/or accessing AMQP message content.
- - L{Data}      -- A class for creating and/or accessing arbitrary AMQP encoded
-                  data.
-
+ - :class:`Message`    -- A class for creating and/or accessing AMQP message content.
+ - :class:`Data`       -- A class for creating and/or accessing arbitrary AMQP encoded data.
 """
 from __future__ import absolute_import
 
diff --git a/python/proton/_condition.py b/python/proton/_condition.py
index e5dbde9..6916bee 100644
--- a/python/proton/_condition.py
+++ b/python/proton/_condition.py
@@ -26,6 +26,36 @@
 
 
 class Condition:
+    """
+    An AMQP Condition object. Conditions hold exception information
+    pertaining to the closing of an AMQP endpoint such as a :class:`Connection`,
+    :class:`Session`, or :class:`Link`. Conditions also hold similar information
+    pertaining to deliveries that have reached terminal states.
+    Connections, Sessions, Links, and Deliveries may all have local and
+    remote conditions associated with them.
+
+    The local condition may be modified by the local endpoint to signal
+    a particular condition to the remote peer. The remote condition may
+    be examined by the local endpoint to detect whatever condition the
+    remote peer may be signaling. Although often conditions are used to
+    indicate errors, not all conditions are errors *per/se*, e.g.
+    conditions may be used to redirect a connection from one host to
+    another.
+
+    Every condition has a short symbolic name, a longer description,
+    and an additional info map associated with it. The name identifies
+    the formally defined condition, and the map contains additional
+    information relevant to the identified condition.
+
+    :ivar ~.name: The name of the condition.
+    :vartype ~.name: ``str``
+    :ivar ~.description: A description of the condition.
+    :vartype ~.description: ``str``
+    :ivar ~.info: A data object that holds the additional information associated
+        with the condition. The data object may be used both to access and to
+        modify the additional information associated with the condition.
+    :vartype ~.info: :class:`Data`
+    """
 
     def __init__(self, name, description=None, info=None):
         self.name = name
diff --git a/python/proton/_data.py b/python/proton/_data.py
index b133d5a..75fce93 100644
--- a/python/proton/_data.py
+++ b/python/proton/_data.py
@@ -46,8 +46,8 @@
 #
 # The results are
 # |       |long|unicode|
-# |python2|long|unicode|
-# |python3| int|    str|
+# |Python2|long|unicode|
+# |Python3| int|    str|
 try:
     long()
 except NameError:
@@ -68,6 +68,11 @@
 
 
 class ulong(long):
+    """
+    The ulong AMQP type.
+    
+    An unsigned 64 bit integer in the range :math:`0` to :math:`2^{64} - 1` inclusive.
+    """
 
     def __init__(self, l):
         if (l < 0):
@@ -79,42 +84,80 @@
 
 
 class timestamp(long):
+    """
+    The timestamp AMQP type.
+    
+    An absolute point in time, represented by a signed 64 bit value measuring
+    milliseconds since the epoch. This value is encoded using the Unix ``time_t``
+    [IEEE1003] encoding of UTC, but with a precision of milliseconds. For
+    example, ``1311704463521`` represents the moment ``2011-07-26T18:21:03.521Z``.
+    """
 
     def __repr__(self):
         return "timestamp(%s)" % long.__repr__(self)
 
 
 class symbol(unicode):
+    """
+    The symbol AMQP type.
+    
+    Symbolic values from a constrained domain, represented by a sequence of ASCII characters.
+    """
 
     def __repr__(self):
         return "symbol(%s)" % unicode.__repr__(self)
 
 
 class char(unicode):
+    """
+    The char AMQP type.
+    
+    A 32 bit UTF-32BE encoded Unicode character.
+    """
 
     def __repr__(self):
         return "char(%s)" % unicode.__repr__(self)
 
 
 class byte(int):
+    """
+    The byte AMQP type.
+    
+    An 8 bit signed integer in the range :math:`-(2^7)` to :math:`2^7 - 1` inclusive.
+    """
 
     def __repr__(self):
         return "byte(%s)" % int.__repr__(self)
 
 
 class short(int):
+    """
+    The short AMQP type.
+    
+    A 16 bit signed integer in the range :math:`-(2^{15})` to :math:`2^{15} - 1` inclusive.
+    """
 
     def __repr__(self):
         return "short(%s)" % int.__repr__(self)
 
 
 class int32(int):
+    """
+    The signed int AMQP type.
+    
+    A 32 bit signed integer in the range :math:`-(2^{31})` to :math:`2^{31} - 1` inclusive.
+    """
 
     def __repr__(self):
         return "int32(%s)" % int.__repr__(self)
 
 
 class ubyte(int):
+    """
+    The unsigned byte AMQP type.
+    
+    An 8 bit unsigned integer in the range :math:`0` to :math:`2^8 - 1` inclusive.
+    """
 
     def __init__(self, i):
         if (i < 0):
@@ -126,6 +169,11 @@
 
 
 class ushort(int):
+    """
+    The unsigned short AMQP type.
+    
+    A 16 bit unsigned integer in the range :math:`0` to :math:`2^{16} - 1` inclusive.
+    """
 
     def __init__(self, i):
         if (i < 0):
@@ -137,6 +185,11 @@
 
 
 class uint(long):
+    """
+    The unsigned int AMQP type.
+    
+    A 32 bit unsigned integer in the range :math:`0` to :math:`2^{32} - 1` inclusive.
+    """
 
     def __init__(self, l):
         if (l < 0):
@@ -148,30 +201,58 @@
 
 
 class float32(float):
+    """
+    The float AMQP type.
+    
+    A 32 bit floating point number (IEEE 754-2008 binary32).
+    """
 
     def __repr__(self):
         return "float32(%s)" % float.__repr__(self)
 
 
 class decimal32(int):
+    """
+    The decimal32 AMQP type.
+    
+    A 32 bit decimal floating point  number (IEEE 754-2008 decimal32).
+    """
 
     def __repr__(self):
         return "decimal32(%s)" % int.__repr__(self)
 
 
 class decimal64(long):
+    """
+    The decimal64 AMQP type.
+    
+    A 64 bit decimal floating point number (IEEE 754-2008 decimal64).
+    """
 
     def __repr__(self):
         return "decimal64(%s)" % long.__repr__(self)
 
 
 class decimal128(bytes):
+    """
+    The decimal128 AMQP type.
+    
+    A 128-bit decimal floating-point number (IEEE 754-2008 decimal128).
+    """
 
     def __repr__(self):
         return "decimal128(%s)" % bytes.__repr__(self)
 
 
 class Described(object):
+    """
+    A described AMQP type.
+
+    :ivar descriptor: A symbol describing the value.
+    :vartype descriptor: :class:`symbol`
+    :ivar value: The described value
+    :vartype value: Any AMQP value
+    """
 
     def __init__(self, descriptor, value):
         self.descriptor = descriptor
@@ -191,6 +272,18 @@
 
 
 class Array(object):
+    """
+    An AMQP array, a sequence of AMQP values of a single type.
+
+    This class provides a convenient way to handle AMQP arrays when used with
+    convenience methods :func:`Data.get_py_array` and :func:`Data.put_py_array`.
+
+    :ivar descriptor: Optional descriptor if the array is to be described, otherwise ``None``
+    :ivar type: Array element type, as an integer. The :class:`Data` class has constants defined
+        for all the valid AMQP types. For example, for an array of double values, use
+        :const:`Data.DOUBLE`, which has integer value 14.
+    :ivar elements: A Python list of elements of the appropriate type.    
+    """
 
     def __init__(self, descriptor, type, *elements):
         self.descriptor = descriptor
@@ -217,54 +310,54 @@
 
 class Data:
     """
-    The L{Data} class provides an interface for decoding, extracting,
-    creating, and encoding arbitrary AMQP data. A L{Data} object
+    The :class:`Data` class provides an interface for decoding, extracting,
+    creating, and encoding arbitrary AMQP data. A :class:`Data` object
     contains a tree of AMQP values. Leaf nodes in this tree correspond
-    to scalars in the AMQP type system such as L{ints<INT>} or
-    L{strings<STRING>}. Non-leaf nodes in this tree correspond to
-    compound values in the AMQP type system such as L{lists<LIST>},
-    L{maps<MAP>}, L{arrays<ARRAY>}, or L{described values<DESCRIBED>}.
-    The root node of the tree is the L{Data} object itself and can have
+    to scalars in the AMQP type system such as :const:`ints <INT>` or
+    :const:`strings <STRING>`. Non-leaf nodes in this tree correspond to
+    compound values in the AMQP type system such as :const:`lists <LIST>`,
+    :const:`maps <MAP>`, :const:`arrays <ARRAY>`, or :const:`described values <DESCRIBED>`.
+    The root node of the tree is the :class:`Data` object itself and can have
     an arbitrary number of children.
 
-    A L{Data} object maintains the notion of the current sibling node
+    A :class:`Data` object maintains the notion of the current sibling node
     and a current parent node. Siblings are ordered within their parent.
-    Values are accessed and/or added by using the L{next}, L{prev},
-    L{enter}, and L{exit} methods to navigate to the desired location in
-    the tree and using the supplied variety of put_*/get_* methods to
+    Values are accessed and/or added by using the :meth:`next`, :meth:`prev`,
+    :meth:`enter`, and :meth:`exit` methods to navigate to the desired location in
+    the tree and using the supplied variety of ``put_*`` / ``get_*`` methods to
     access or add a value of the desired type.
 
-    The put_* methods will always add a value I{after} the current node
-    in the tree. If the current node has a next sibling the put_* method
+    The ``put_*`` methods will always add a value *after* the current node
+    in the tree. If the current node has a next sibling the ``put_*`` method
     will overwrite the value on this node. If there is no current node
     or the current node has no next sibling then one will be added. The
-    put_* methods always set the added/modified node to the current
-    node. The get_* methods read the value of the current node and do
+    ``put_*`` methods always set the added/modified node to the current
+    node. The ``get_*`` methods read the value of the current node and do
     not change which node is current.
 
     The following types of scalar values are supported:
 
-     - L{NULL}
-     - L{BOOL}
-     - L{UBYTE}
-     - L{USHORT}
-     - L{SHORT}
-     - L{UINT}
-     - L{INT}
-     - L{ULONG}
-     - L{LONG}
-     - L{FLOAT}
-     - L{DOUBLE}
-     - L{BINARY}
-     - L{STRING}
-     - L{SYMBOL}
+        * :const:`NULL`
+        * :const:`BOOL`
+        * :const:`UBYTE`
+        * :const:`USHORT`
+        * :const:`SHORT`
+        * :const:`UINT`
+        * :const:`INT`
+        * :const:`ULONG`
+        * :const:`LONG`
+        * :const:`FLOAT`
+        * :const:`DOUBLE`
+        * :const:`BINARY`
+        * :const:`STRING`
+        * :const:`SYMBOL`
 
     The following types of compound values are supported:
 
-     - L{DESCRIBED}
-     - L{ARRAY}
-     - L{LIST}
-     - L{MAP}
+        * :const:`DESCRIBED`
+        * :const:`ARRAY`
+        * :const:`LIST`
+        * :const:`MAP`
     """
 
     NULL = PN_NULL; "A null value."
@@ -320,10 +413,20 @@
         LIST: "list",
         MAP: "map"
     }
+    """
+    A map which uses the enumerated type as a key to get a text name for the type.
+    """
 
     @classmethod
-    def type_name(type):
-        return Data.type_names[type]
+    def type_name(amqptype):
+        """
+        Return a string name for an AMQP type.
+        
+        :param type: Numeric Proton AMQP type (`enum pn_type_t`)
+        :type type: integer
+        :rtype: String describing the AMQP type with numeric value `amqptype`
+        """
+        return Data.type_names[amqptype]
 
     def __init__(self, capacity=16):
         if isinstance(capacity, (int, long)):
@@ -364,7 +467,10 @@
         """
         Advances the current node to its next sibling and returns its
         type. If there is no next sibling the current node remains
-        unchanged and None is returned.
+        unchanged and ``None`` is returned.
+
+        :return: Node type or ``None``
+        :rtype: ``int`` or ``None``
         """
         found = pn_data_next(self._data)
         if found:
@@ -376,7 +482,10 @@
         """
         Advances the current node to its previous sibling and returns its
         type. If there is no previous sibling the current node remains
-        unchanged and None is returned.
+        unchanged and ``None`` is returned.
+
+        :return: Node type or ``None``
+        :rtype: ``int`` or ``None``
         """
         found = pn_data_prev(self._data)
         if found:
@@ -387,8 +496,12 @@
     def enter(self):
         """
         Sets the parent node to the current node and clears the current node.
-        Clearing the current node sets it _before_ the first child,
-        call next() advances to the first child.
+        Clearing the current node sets it *before* the first child,
+        call :meth:`next` to advance to the first child.
+
+        :return: ``True`` iff the pointers to the current/parent nodes are changed,
+            ``False`` otherwise.
+        :rtype: ``bool``
         """
         return pn_data_enter(self._data)
 
@@ -396,6 +509,10 @@
         """
         Sets the current node to the parent node and the parent node to
         its own parent.
+
+        :return: ``True`` iff the pointers to the current/parent nodes are changed,
+            ``False`` otherwise.
+        :rtype: ``bool``
         """
         return pn_data_exit(self._data)
 
@@ -403,14 +520,26 @@
         return pn_data_lookup(self._data, name)
 
     def narrow(self):
+        """
+        Modify this :class:`Data` object to behave as if the current node is the
+        root node of the tree. This impacts the behavior of :meth:`rewind`,
+        :meth:`next`, :meth:`prev`, and anything else that depends on the
+        navigational state of the :class:`Data` object. Use :meth:`widen`
+        to reverse the effect of this operation.
+        """
         pn_data_narrow(self._data)
 
     def widen(self):
+        """ Reverse the effect of :meth:`narrow`. """
         pn_data_widen(self._data)
 
     def type(self):
         """
-        Returns the type of the current node.
+        Returns the type of the current node. Returns `None` if there is no
+        current node.
+
+        :return: The current node type enumeration.
+        :rtype: ``int`` or ``None``
         """
         dtype = pn_data_type(self._data)
         if dtype == -1:
@@ -421,12 +550,19 @@
     def encoded_size(self):
         """
         Returns the size in bytes needed to encode the data in AMQP format.
+
+        :return: The size of the encoded data or an error code if data is invalid.
+        :rtype: ``int``
         """
         return pn_data_encoded_size(self._data)
 
     def encode(self):
         """
         Returns a representation of the data encoded in AMQP format.
+
+        :return: The size of the encoded data
+        :rtype: ``int``
+        :raise: :exc:`DataException` if there is a Proton error.
         """
         size = 1024
         while True:
@@ -443,8 +579,9 @@
         Decodes the first value from supplied AMQP data and returns the
         number of bytes consumed.
 
-        @type encoded: binary
-        @param encoded: AMQP encoded binary data
+        :type encoded: binary
+        :param encoded: AMQP encoded binary data
+        :raise: :exc:`DataException` if there is a Proton error.
         """
         return self._check(pn_data_decode(self._data, encoded))
 
@@ -453,13 +590,15 @@
         Puts a list value. Elements may be filled by entering the list
         node and putting element values.
 
-          >>> data = Data()
-          >>> data.put_list()
-          >>> data.enter()
-          >>> data.put_int(1)
-          >>> data.put_int(2)
-          >>> data.put_int(3)
-          >>> data.exit()
+            >>> data = Data()
+            >>> data.put_list()
+            >>> data.enter()
+            >>> data.put_int(1)
+            >>> data.put_int(2)
+            >>> data.put_int(3)
+            >>> data.exit()
+
+        :raise: :exc:`DataException` if there is a Proton error.
         """
         self._check(pn_data_put_list(self._data))
 
@@ -468,12 +607,14 @@
         Puts a map value. Elements may be filled by entering the map node
         and putting alternating key value pairs.
 
-          >>> data = Data()
-          >>> data.put_map()
-          >>> data.enter()
-          >>> data.put_string("key")
-          >>> data.put_string("value")
-          >>> data.exit()
+            >>> data = Data()
+            >>> data.put_map()
+            >>> data.enter()
+            >>> data.put_string("key")
+            >>> data.put_string("value")
+            >>> data.exit()
+
+        :raise: :exc:`DataException` if there is a Proton error.
         """
         self._check(pn_data_put_map(self._data))
 
@@ -485,27 +626,28 @@
         first child value of the array is the descriptor and may be of any
         type.
 
-          >>> data = Data()
-          >>>
-          >>> data.put_array(False, Data.INT)
-          >>> data.enter()
-          >>> data.put_int(1)
-          >>> data.put_int(2)
-          >>> data.put_int(3)
-          >>> data.exit()
-          >>>
-          >>> data.put_array(True, Data.DOUBLE)
-          >>> data.enter()
-          >>> data.put_symbol("array-descriptor")
-          >>> data.put_double(1.1)
-          >>> data.put_double(1.2)
-          >>> data.put_double(1.3)
-          >>> data.exit()
+            >>> data = Data()
+            >>>
+            >>> data.put_array(False, Data.INT)
+            >>> data.enter()
+            >>> data.put_int(1)
+            >>> data.put_int(2)
+            >>> data.put_int(3)
+            >>> data.exit()
+            >>>
+            >>> data.put_array(True, Data.DOUBLE)
+            >>> data.enter()
+            >>> data.put_symbol("array-descriptor")
+            >>> data.put_double(1.1)
+            >>> data.put_double(1.2)
+            >>> data.put_double(1.3)
+            >>> data.exit()
 
-        @type described: bool
-        @param described: specifies whether the array is described
-        @type element_type: int
-        @param element_type: the type of the array elements
+        :type described: bool
+        :param described: specifies whether the array is described
+        :type element_type: int
+        :param element_type: the type of the array elements
+        :raise: :exc:`DataException` if there is a Proton error.
         """
         self._check(pn_data_put_array(self._data, described, element_type))
 
@@ -515,18 +657,22 @@
         descriptor and the value. These are specified by entering the node
         and putting the desired values.
 
-          >>> data = Data()
-          >>> data.put_described()
-          >>> data.enter()
-          >>> data.put_symbol("value-descriptor")
-          >>> data.put_string("the value")
-          >>> data.exit()
+            >>> data = Data()
+            >>> data.put_described()
+            >>> data.enter()
+            >>> data.put_symbol("value-descriptor")
+            >>> data.put_string("the value")
+            >>> data.exit()
+
+        :raise: :exc:`DataException` if there is a Proton error.
         """
         self._check(pn_data_put_described(self._data))
 
     def put_null(self):
         """
         Puts a null value.
+
+        :raise: :exc:`DataException` if there is a Proton error.
         """
         self._check(pn_data_put_null(self._data))
 
@@ -534,7 +680,9 @@
         """
         Puts a boolean value.
 
-        @param b: a boolean value
+        :param b: a boolean value
+        :type b: ``bool`` or ``int``
+        :raise: :exc:`DataException` if there is a Proton error.
         """
         self._check(pn_data_put_bool(self._data, b))
 
@@ -542,7 +690,10 @@
         """
         Puts an unsigned byte value.
 
-        @param ub: an integral value
+        :param ub: an integral value in the range :math:`0` to :math:`2^8 - 1` inclusive
+        :type ub: ``int``, :class:`ubyte`
+        :raise: * ``AssertionError`` if parameter is out of the range :math:`0` to :math:`2^8 - 1` inclusive.
+                * :exc:`DataException` if there is a Proton error.
         """
         self._check(pn_data_put_ubyte(self._data, ub))
 
@@ -550,7 +701,10 @@
         """
         Puts a signed byte value.
 
-        @param b: an integral value
+        :param b: an integral value in the range :math:`-(2^7)` to :math:`2^7 - 1` inclusive.
+        :type b: ``int``, :class:`byte`
+        :raise: * ``AssertionError`` if parameter is out of the range :math:`-(2^7)` to :math:`2^7 - 1` inclusive.
+                * :exc:`DataException` if there is a Proton error.
         """
         self._check(pn_data_put_byte(self._data, b))
 
@@ -558,7 +712,10 @@
         """
         Puts an unsigned short value.
 
-        @param us: an integral value.
+        :param us: an integral value in the range :math:`0` to :math:`2^{16} - 1` inclusive.
+        :type us: ``int``, :class:`ushort`
+        :raise: * ``AssertionError`` if parameter is out of the range :math:`0` to :math:`2^{16} - 1` inclusive.
+                * :exc:`DataException` if there is a Proton error.
         """
         self._check(pn_data_put_ushort(self._data, us))
 
@@ -566,7 +723,10 @@
         """
         Puts a signed short value.
 
-        @param s: an integral value
+        :param s: an integral value in the range :math:`-(2^{15})` to :math:`2^{15} - 1` inclusive.
+        :type s: ``int``, :class:`short`
+        :raise: * ``AssertionError`` if parameter is out of the range :math:`-(2^{15})` to :math:`2^{15} - 1` inclusive.
+                * :exc:`DataException` if there is a Proton error.
         """
         self._check(pn_data_put_short(self._data, s))
 
@@ -574,7 +734,10 @@
         """
         Puts an unsigned int value.
 
-        @param ui: an integral value
+        :param ui: an integral value in the range :math:`0` to :math:`2^{32} - 1` inclusive.
+        :type ui: ``int``, :class:`uint`
+        :raise: * ``AssertionError`` if parameter is out of the range :math:`0` to :math:`2^{32} - 1` inclusive. 
+                * :exc:`DataException` if there is a Proton error.
         """
         self._check(pn_data_put_uint(self._data, ui))
 
@@ -582,7 +745,10 @@
         """
         Puts a signed int value.
 
-        @param i: an integral value
+        :param i: an integral value in the range :math:`-(2^{31})` to :math:`2^{31} - 1` inclusive.
+        :type i: ``int``, :class:`int32`
+        :raise: * ``AssertionError`` if parameter is out of the range :math:`-(2^{31})` to :math:`2^{31} - 1` inclusive.
+                * :exc:`DataException` if there is a Proton error.
         """
         self._check(pn_data_put_int(self._data, i))
 
@@ -590,7 +756,9 @@
         """
         Puts a char value.
 
-        @param c: a single character
+        :param c: a single character
+        :type c: ``str``, :class:`char`
+        :raise: :exc:`DataException` if there is a Proton error.
         """
         self._check(pn_data_put_char(self._data, ord(c)))
 
@@ -598,7 +766,10 @@
         """
         Puts an unsigned long value.
 
-        @param ul: an integral value
+        :param ul: an integral value in the range :math:`0` to :math:`2^{64} - 1` inclusive.
+        :type ul: ``int``, ``long``, :class:`ulong`
+        :raise: * ``AssertionError`` if parameter is out of the range :math:`0` to :math:`2^{64} - 1` inclusive.
+                * :exc:`DataException` if there is a Proton error.
         """
         self._check(pn_data_put_ulong(self._data, ul))
 
@@ -606,7 +777,10 @@
         """
         Puts a signed long value.
 
-        @param l: an integral value
+        :param l: an integral value in the range :math:`-(2^{63})` to :math:`2^{63} - 1` inclusive.
+        :type ul: ``int``, ``long``
+        :raise: * ``AssertionError`` if parameter is out of the range :math:`-(2^{63})` to :math:`2^{63} - 1` inclusive.
+                * :exc:`DataException` if there is a Proton error.
         """
         self._check(pn_data_put_long(self._data, l))
 
@@ -614,7 +788,10 @@
         """
         Puts a timestamp value.
 
-        @param t: an integral value
+        :param t: a positive integral value
+        :type t: ``int``, :class:`timestamp`
+        :raise: * ``AssertionError`` if parameter is negative.
+                * :exc:`DataException` if there is a Proton error.
         """
         self._check(pn_data_put_timestamp(self._data, t))
 
@@ -622,7 +799,9 @@
         """
         Puts a float value.
 
-        @param f: a floating point value
+        :param f: a floating point value
+        :type f: ``float``, :class:`float32`
+        :raise: :exc:`DataException` if there is a Proton error.
         """
         self._check(pn_data_put_float(self._data, f))
 
@@ -630,7 +809,9 @@
         """
         Puts a double value.
 
-        @param d: a floating point value.
+        :param d: a floating point value.
+        :type d: ``double``
+        :raise: :exc:`DataException` if there is a Proton error.
         """
         self._check(pn_data_put_double(self._data, d))
 
@@ -638,7 +819,9 @@
         """
         Puts a decimal32 value.
 
-        @param d: a decimal32 value
+        :param d: a decimal32 number encoded in an 32-bit integral value.
+        :type d: ``int``, :class:`decimal32`
+        :raise: :exc:`DataException` if there is a Proton error.
         """
         self._check(pn_data_put_decimal32(self._data, d))
 
@@ -646,7 +829,9 @@
         """
         Puts a decimal64 value.
 
-        @param d: a decimal64 value
+        :param d: a decimal64 number encoded in an 32-bit integral value.
+        :type d: ``int``, ``long``, :class:`decimal64`
+        :raise: :exc:`DataException` if there is a Proton error.
         """
         self._check(pn_data_put_decimal64(self._data, d))
 
@@ -654,7 +839,9 @@
         """
         Puts a decimal128 value.
 
-        @param d: a decimal128 value
+        :param d: a decimal128 value encoded in a 16-byte binary value.
+        :type d: ``bytes``, :class:`decimal128`
+        :raise: :exc:`DataException` if there is a Proton error.
         """
         self._check(pn_data_put_decimal128(self._data, d))
 
@@ -662,7 +849,9 @@
         """
         Puts a UUID value.
 
-        @param u: a uuid value
+        :param u: a uuid value.
+        :type u: ``uuid.UUID``
+        :raise: :exc:`DataException` if there is a Proton error.
         """
         self._check(pn_data_put_uuid(self._data, u.bytes))
 
@@ -670,25 +859,39 @@
         """
         Puts a binary value.
 
-        @type b: binary
-        @param b: a binary value
+        :param b: a binary value
+        :type b: ``bytes``
+        :raise: :exc:`DataException` if there is a Proton error.
         """
         self._check(pn_data_put_binary(self._data, b))
 
     def put_memoryview(self, mv):
-        """Put a python memoryview object as an AMQP binary value"""
+        """
+        Put a Python memoryview object as an AMQP binary value.
+
+        :param mv: A Python memoryview object
+        :type mv: ``memoryview``
+        :raise: :exc:`DataException` if there is a Proton error.
+        """
         self.put_binary(mv.tobytes())
 
     def put_buffer(self, buff):
-        """Put a python buffer object as an AMQP binary value"""
+        """
+        Put a Python buffer object as an AMQP binary value.
+
+        :param buff: A Python buffer object (**CHECK THIS**)
+        :type buff: Any object supporting the Python buffer interface.
+        :raise: :exc:`DataException` if there is a Proton error.
+        """
         self.put_binary(bytes(buff))
 
     def put_string(self, s):
         """
         Puts a unicode value.
 
-        @type s: unicode
-        @param s: a unicode value
+        :param s: a unicode string
+        :type s: ``str`` (Python 3.x) or ``unicode`` (Python 2.x)
+        :raise: :exc:`DataException` if there is a Proton error.
         """
         self._check(pn_data_put_string(self._data, s.encode("utf8")))
 
@@ -696,44 +899,51 @@
         """
         Puts a symbolic value.
 
-        @type s: string
-        @param s: the symbol name
+        :param s: the symbol name
+        :type s: string, :class:`symbol`
+        :raise: :exc:`DataException` if there is a Proton error.
         """
         self._check(pn_data_put_symbol(self._data, s.encode('ascii')))
 
     def get_list(self):
         """
         If the current node is a list, return the number of elements,
-        otherwise return zero. List elements can be accessed by entering
+        otherwise return 0. List elements can be accessed by entering
         the list.
 
-          >>> count = data.get_list()
-          >>> data.enter()
-          >>> for i in range(count):
-          ...   type = data.next()
-          ...   if type == Data.STRING:
-          ...     print data.get_string()
-          ...   elif type == ...:
-          ...     ...
-          >>> data.exit()
+            >>> count = data.get_list()
+            >>> data.enter()
+            >>> for i in range(count):
+            ...   type = data.next()
+            ...   if type == Data.STRING:
+            ...     print data.get_string()
+            ...   elif type == ...:
+            ...     ...
+            >>> data.exit()
+
+        :return: the number of child elements of a list node
+        :rtype: ``int``
         """
         return pn_data_get_list(self._data)
 
     def get_map(self):
         """
         If the current node is a map, return the number of child elements,
-        otherwise return zero. Key value pairs can be accessed by entering
+        otherwise return 0. Key value pairs can be accessed by entering
         the map.
 
-          >>> count = data.get_map()
-          >>> data.enter()
-          >>> for i in range(count/2):
-          ...   type = data.next()
-          ...   if type == Data.STRING:
-          ...     print data.get_string()
-          ...   elif type == ...:
-          ...     ...
-          >>> data.exit()
+            >>> count = data.get_map()
+            >>> data.enter()
+            >>> for i in range(count/2):
+            ...   type = data.next()
+            ...   if type == Data.STRING:
+            ...     print data.get_string()
+            ...   elif type == ...:
+            ...     ...
+            >>> data.exit()
+
+        :return: the number of child elements of a map node
+        :rtype: ``int``
         """
         return pn_data_get_map(self._data)
 
@@ -741,18 +951,22 @@
         """
         If the current node is an array, return a tuple of the element
         count, a boolean indicating whether the array is described, and
-        the type of each element, otherwise return (0, False, None). Array
+        the type of each element, otherwise return ``None``. Array
         data can be accessed by entering the array.
 
-          >>> # read an array of strings with a symbolic descriptor
-          >>> count, described, type = data.get_array()
-          >>> data.enter()
-          >>> data.next()
-          >>> print "Descriptor:", data.get_symbol()
-          >>> for i in range(count):
-          ...    data.next()
-          ...    print "Element:", data.get_string()
-          >>> data.exit()
+            >>> # read an array of strings with a symbolic descriptor
+            >>> count, described, type = data.get_array()
+            >>> data.enter()
+            >>> data.next()
+            >>> print "Descriptor:", data.get_symbol()
+            >>> for i in range(count):
+            ...    data.next()
+            ...    print "Element:", data.get_string()
+            >>> data.exit()
+
+        :return: A tuple containing the number of array elements, the descriptor
+            (or ``None`` if no descriptor) and the enumerated array element type. 
+        :rtype: ``tuple`` (``int``, ``str`` or ``None``, ``int``)
         """
         count = pn_data_get_array(self._data)
         described = pn_data_is_array_described(self._data)
@@ -766,142 +980,183 @@
         Checks if the current node is a described value. The descriptor
         and value may be accessed by entering the described value.
 
-          >>> # read a symbolically described string
-          >>> assert data.is_described() # will error if the current node is not described
-          >>> data.enter()
-          >>> data.next()
-          >>> print data.get_symbol()
-          >>> data.next()
-          >>> print data.get_string()
-          >>> data.exit()
+            >>> # read a symbolically described string
+            >>> assert data.is_described() # will error if the current node is not described
+            >>> data.enter()
+            >>> data.next()
+            >>> print data.get_symbol()
+            >>> data.next()
+            >>> print data.get_string()
+            >>> data.exit()
+
+        :return: ``True`` if the current node is a described type, ``False`` otherwise.
+        :rtype: ``bool``
         """
         return pn_data_is_described(self._data)
 
     def is_null(self):
         """
-        Checks if the current node is a null.
+        Checks if the current node is the AMQP null type.
+
+        :return: ``True`` if the current node is the AMQP null type, ``False`` otherwise.
+        :rtype: ``bool``
         """
         return pn_data_is_null(self._data)
 
     def get_bool(self):
         """
-        If the current node is a boolean, returns its value, returns False
-        otherwise.
+        Get the current node value as a ``bool``.
+
+        :return: If the current node is a boolean type, returns its value,
+            ``False`` otherwise.
+        :rtype: ``bool``
         """
         return pn_data_get_bool(self._data)
 
     def get_ubyte(self):
         """
-        If the current node is an unsigned byte, returns its value,
-        returns 0 otherwise.
+        Get the current node value as a :class:`ubyte`.
+
+        :return: If the current node is an unsigned byte, its value, 0 otherwise.
+        :rtype: :class:`ubyte`
         """
         return ubyte(pn_data_get_ubyte(self._data))
 
     def get_byte(self):
         """
-        If the current node is a signed byte, returns its value, returns 0
-        otherwise.
+        Get the current node value as a :class:`byte`.
+
+        :return: If the current node is a signed byte, its value, 0 otherwise.
+        :rtype: :class:`byte`
         """
         return byte(pn_data_get_byte(self._data))
 
     def get_ushort(self):
         """
-        If the current node is an unsigned short, returns its value,
-        returns 0 otherwise.
+        Get the current node value as a :class:`ushort`.
+
+        :return: If the current node is an unsigned short, its value, 0 otherwise.
+        :rtype: :class:`ushort`
         """
         return ushort(pn_data_get_ushort(self._data))
 
     def get_short(self):
         """
-        If the current node is a signed short, returns its value, returns
-        0 otherwise.
+        Get the current node value as a :class:`short`.
+
+        :return: If the current node is a signed short, its value, 0 otherwise.
+        :rtype: :class:`short`
         """
         return short(pn_data_get_short(self._data))
 
     def get_uint(self):
         """
-        If the current node is an unsigned int, returns its value, returns
-        0 otherwise.
+        Get the current node value as a :class:`uint`.
+
+        :return: If the current node is an unsigned int, its value, 0 otherwise.
+        :rtype: :class:`uint`
         """
         return uint(pn_data_get_uint(self._data))
 
     def get_int(self):
         """
-        If the current node is a signed int, returns its value, returns 0
-        otherwise.
+        Get the current node value as a :class:`int32`.
+
+        :return: If the current node is a signed int, its value, 0 otherwise.
+        :rtype: :class:`int32`
         """
         return int32(pn_data_get_int(self._data))
 
     def get_char(self):
         """
-        If the current node is a char, returns its value, returns 0
-        otherwise.
+        Get the current node value as a :class:`char`.
+
+        :return: If the current node is a char, its value, 0 otherwise.
+        :rtype: :class:`char`
         """
         return char(_compat.unichr(pn_data_get_char(self._data)))
 
     def get_ulong(self):
         """
-        If the current node is an unsigned long, returns its value,
-        returns 0 otherwise.
+        Get the current node value as a :class:`long`.
+
+        :return: If the current node is an unsigned long, its value, 0 otherwise.
+        :rtype: :class:`ulong`
         """
         return ulong(pn_data_get_ulong(self._data))
 
     def get_long(self):
         """
-        If the current node is an signed long, returns its value, returns
-        0 otherwise.
+        Get the current node value as a :class:`ulong`.
+
+        :return: If the current node is an signed long, its value, 0 otherwise.
+        :rtype: :class:`long`
         """
         return long(pn_data_get_long(self._data))
 
     def get_timestamp(self):
         """
-        If the current node is a timestamp, returns its value, returns 0
-        otherwise.
+        Get the current node value as a :class:`timestamp`.
+
+        :return: If the current node is a timestamp, its value, 0 otherwise.
+        :rtype: :class:`timestamp`
         """
         return timestamp(pn_data_get_timestamp(self._data))
 
     def get_float(self):
         """
-        If the current node is a float, returns its value, raises 0
-        otherwise.
+        Get the current node value as a :class:`float32`.
+
+        :return: If the current node is a float, its value, 0 otherwise.
+        :rtype: :class:`float32`
         """
         return float32(pn_data_get_float(self._data))
 
     def get_double(self):
         """
-        If the current node is a double, returns its value, returns 0
-        otherwise.
+        Get the current node value as a ``double``.
+
+        :return: If the current node is a double, its value, 0 otherwise.
+        :rtype: ``double``
         """
         return pn_data_get_double(self._data)
 
     # XXX: need to convert
     def get_decimal32(self):
         """
-        If the current node is a decimal32, returns its value, returns 0
-        otherwise.
+        Get the current node value as a :class:`decimal32`.
+
+        :return: If the current node is a decimal32, its value, 0 otherwise.
+        :rtype: :class:`decimal32`
         """
         return decimal32(pn_data_get_decimal32(self._data))
 
     # XXX: need to convert
     def get_decimal64(self):
         """
-        If the current node is a decimal64, returns its value, returns 0
-        otherwise.
+        Get the current node value as a :class:`decimal64`.
+
+        :return: If the current node is a decimal64, its value, 0 otherwise.
+        :rtype: :class:`decimal64`
         """
         return decimal64(pn_data_get_decimal64(self._data))
 
     # XXX: need to convert
     def get_decimal128(self):
         """
-        If the current node is a decimal128, returns its value, returns 0
-        otherwise.
+        Get the current node value as a :class:`decimal128`.
+
+        :return: If the current node is a decimal128, its value, 0 otherwise.
+        :rtype: :class:`decimal128`
         """
         return decimal128(pn_data_get_decimal128(self._data))
 
     def get_uuid(self):
         """
-        If the current node is a UUID, returns its value, returns None
-        otherwise.
+        Get the current node value as a ``uuid.UUID``.
+
+        :return: If the current node is a UUID, its value, ``None`` otherwise.
+        :rtype: ``uuid.UUID`` or ``None``
         """
         if pn_data_type(self._data) == Data.UUID:
             return uuid.UUID(bytes=pn_data_get_uuid(self._data))
@@ -910,29 +1165,50 @@
 
     def get_binary(self):
         """
-        If the current node is binary, returns its value, returns ""
-        otherwise.
+        Get the current node value as ``bytes``.
+
+        :return: If the current node is binary, its value, ``""`` otherwise.
+        :rtype: ``bytes``
         """
         return pn_data_get_binary(self._data)
 
     def get_string(self):
         """
-        If the current node is a string, returns its value, returns ""
-        otherwise.
+        Get the current node value as ``str``.
+
+        :return: If the current node is a string, its value, ``""`` otherwise.
+        :rtype: ``str``
         """
         return pn_data_get_string(self._data).decode("utf8")
 
     def get_symbol(self):
         """
-        If the current node is a symbol, returns its value, returns ""
-        otherwise.
+        Get the current node value as :class:`symbol`.
+
+        :return: If the current node is a symbol, its value, ``""`` otherwise.
+        :rtype: :class:`symbol`
         """
         return symbol(pn_data_get_symbol(self._data).decode('ascii'))
 
     def copy(self, src):
+        """
+        Copy the contents of another pn_data_t object. Any values in the
+        data object will be lost.
+        
+        :param src: The source object from which to copy
+        :type src: :class:`Data`
+        :raise: :exc:`DataException` if there is a Proton error.
+        """
         self._check(pn_data_copy(self._data, src._data))
 
     def format(self):
+        """
+        Formats the contents of this :class:`Data` object in a human readable way.
+
+        :return: A Formatted string containing contents of this :class:`Data` object.
+        :rtype: ``str``
+        :raise: :exc:`DataException` if there is a Proton error.
+        """
         sz = 16
         while True:
             err, result = pn_data_format(self._data, sz)
@@ -944,9 +1220,22 @@
                 return result
 
     def dump(self):
+        """
+        Dumps a debug representation of the internal state of this :class:`Data`
+        object that includes its navigational state to ``cout`` (``stdout``) for
+        debugging purposes.
+        """
         pn_data_dump(self._data)
 
     def put_dict(self, d):
+        """
+        A convenience method for encoding the contents of a Python ``dict``
+        as an AMQP map.
+
+        :param d: The dictionary to be encoded
+        :type d: ``dict``
+        :raise: :exc:`DataException` if there is a Proton error.
+        """
         self.put_map()
         self.enter()
         try:
@@ -957,6 +1246,12 @@
             self.exit()
 
     def get_dict(self):
+        """
+        A convenience method for decoding an AMQP map as a Python ``dict``.
+
+        :returns: The decoded dictionary.
+        :rtype: ``dict``
+        """
         if self.enter():
             try:
                 result = {}
@@ -972,6 +1267,14 @@
             return result
 
     def put_sequence(self, s):
+        """
+        A convenience method for encoding a Python ``list`` as an
+        AMQP list.
+
+        :param s: The sequence to be encoded
+        :type s: ``list``
+        :raise: :exc:`DataException` if there is a Proton error.
+        """
         self.put_list()
         self.enter()
         try:
@@ -981,6 +1284,12 @@
             self.exit()
 
     def get_sequence(self):
+        """
+        A convenience method for decoding an AMQP list as a Python ``list``.
+
+        :returns: The decoded list.
+        :rtype: ``list``
+        """
         if self.enter():
             try:
                 result = []
@@ -991,6 +1300,12 @@
             return result
 
     def get_py_described(self):
+        """
+        A convenience method for decoding an AMQP described value.
+
+        :returns: The decoded AMQP descriptor.
+        :rtype: :class:`Described`
+        """
         if self.enter():
             try:
                 self.next()
@@ -1002,6 +1317,15 @@
             return Described(descriptor, value)
 
     def put_py_described(self, d):
+        """
+        A convenience method for encoding a :class:`Described` object
+        as an AMQP described value. This method encapsulates all the steps
+        described in :func:`put_described` into a single method.
+
+        :param d: The descriptor to be encoded
+        :type d: :class:`Described`
+        :raise: :exc:`DataException` if there is a Proton error.
+        """
         self.put_described()
         self.enter()
         try:
@@ -1012,9 +1336,15 @@
 
     def get_py_array(self):
         """
+        A convenience method for decoding an AMQP array into an
+        :class:`Array` object. This method encapsulates all the
+        steps described in :func:`get_array` into a single function.
+
         If the current node is an array, return an Array object
-        representing the array and its contents. Otherwise return None.
-        This is a convenience wrapper around get_array, enter, etc.
+        representing the array and its contents. Otherwise return ``None``.
+
+        :returns: The decoded AMQP array.
+        :rtype: :class:`Array`
         """
 
         count, described, type = self.get_array()
@@ -1034,6 +1364,15 @@
             return Array(descriptor, type, *elements)
 
     def put_py_array(self, a):
+        """
+        A convenience method for encoding an :class:`Array` object as
+        an AMQP array. This method encapsulates the steps described in
+        :func:`put_array` into a single function.
+
+        :param a: The array object to be encoded
+        :type a: :class:`Array`
+        :raise: :exc:`DataException` if there is a Proton error.
+        """
         described = a.descriptor != UNDESCRIBED
         self.put_array(described, a.type)
         self.enter()
@@ -1073,7 +1412,7 @@
         Described: put_py_described,
         Array: put_py_array
     }
-    # for python 3.x, long is merely an alias for int, but for python 2.x
+    # for Python 3.x, long is merely an alias for int, but for Python 2.x
     # we need to add an explicit int since it is a different type
     if int not in put_mappings:
         put_mappings[int] = put_int
diff --git a/python/proton/_delivery.py b/python/proton/_delivery.py
index 665a77b..f5c955f 100644
--- a/python/proton/_delivery.py
+++ b/python/proton/_delivery.py
@@ -60,11 +60,53 @@
 
 
 class Disposition(object):
+    """
+    A delivery state.
+
+    Dispositions record the current state or final outcome of a
+    transfer. Every delivery contains both a local and remote
+    disposition. The local disposition holds the local state of the
+    delivery, and the remote disposition holds the last known remote
+    state of the delivery.
+    """
+
     RECEIVED = DispositionType(PN_RECEIVED, "RECEIVED")
+    """
+    A non terminal state indicating how much (if any) message data
+    has been received for a delivery.
+    """    
+
     ACCEPTED = DispositionType(PN_ACCEPTED, "ACCEPTED")
+    """
+    A terminal state indicating that the delivery was successfully
+    processed. Once in this state there will be no further state
+    changes prior to the delivery being settled.
+    """
+
     REJECTED = DispositionType(PN_REJECTED, "REJECTED")
+    """
+    A terminal state indicating that the delivery could not be
+    processed due to some error condition. Once in this state
+    there will be no further state changes prior to the delivery
+    being settled.
+    """
+
     RELEASED = DispositionType(PN_RELEASED, "RELEASED")
+    """
+    A terminal state indicating that the delivery is being
+    returned to the sender. Once in this state there will be no
+    further state changes prior to the delivery being settled.
+    """
+
     MODIFIED = DispositionType(PN_MODIFIED, "MODIFIED")
+    """
+    A terminal state indicating that the delivery is being
+    returned to the sender and should be annotated by the
+    sender prior to further delivery attempts. Once in this
+    state there will be no further state changes prior to the
+    delivery being settled.
+    """
+
 
     def __init__(self, impl, local):
         self._impl = impl
@@ -75,6 +117,19 @@
 
     @property
     def type(self):
+        """
+        Get the type of this disposition object.
+
+        Defined values are:
+        
+        * :const:`RECEIVED`
+        * :const:`ACCEPTED`
+        * :const:`REJECTED`
+        * :const:`RELEASED`
+        * :const:`MODIFIED`
+        
+        :type: ``str``
+        """
         return DispositionType.get(pn_disposition_type(self._impl))
 
     def _get_section_number(self):
@@ -83,7 +138,11 @@
     def _set_section_number(self, n):
         pn_disposition_set_section_number(self._impl, n)
 
-    section_number = property(_get_section_number, _set_section_number)
+    section_number = property(_get_section_number, _set_section_number, doc="""
+        The section number associated with a disposition.
+
+        :type: ``int``
+        """)
 
     def _get_section_offset(self):
         return pn_disposition_get_section_offset(self._impl)
@@ -91,7 +150,11 @@
     def _set_section_offset(self, n):
         pn_disposition_set_section_offset(self._impl, n)
 
-    section_offset = property(_get_section_offset, _set_section_offset)
+    section_offset = property(_get_section_offset, _set_section_offset, doc="""
+        The section offset associated with a disposition.
+
+        :type: ``int``
+        """)
 
     def _get_failed(self):
         return pn_disposition_is_failed(self._impl)
@@ -99,7 +162,11 @@
     def _set_failed(self, b):
         pn_disposition_set_failed(self._impl, b)
 
-    failed = property(_get_failed, _set_failed)
+    failed = property(_get_failed, _set_failed, doc="""
+        The failed flag for this disposition.
+
+        :type: ``bool``
+        """)
 
     def _get_undeliverable(self):
         return pn_disposition_is_undeliverable(self._impl)
@@ -107,7 +174,11 @@
     def _set_undeliverable(self, b):
         pn_disposition_set_undeliverable(self._impl, b)
 
-    undeliverable = property(_get_undeliverable, _set_undeliverable)
+    undeliverable = property(_get_undeliverable, _set_undeliverable, doc="""
+        The undeliverable flag for this disposition.
+
+        :type: ``bool``
+        """)
 
     def _get_data(self):
         if self.local:
@@ -121,7 +192,20 @@
         else:
             raise AttributeError("data attribute is read-only")
 
-    data = property(_get_data, _set_data)
+    data = property(_get_data, _set_data, doc="""
+        Access the disposition as a :class:`Data` object.
+
+        Dispositions are an extension point in the AMQP protocol. The
+        disposition interface provides setters/getters for those
+        dispositions that are predefined by the specification, however
+        access to the raw disposition data is provided so that other
+        dispositions can be used.
+
+        The :class:`Data` object returned by this operation is valid until
+        the parent delivery is settled.
+
+        :type: :class:`Data`
+        """)
 
     def _get_annotations(self):
         if self.local:
@@ -135,7 +219,21 @@
         else:
             raise AttributeError("annotations attribute is read-only")
 
-    annotations = property(_get_annotations, _set_annotations)
+    annotations = property(_get_annotations, _set_annotations, doc="""
+        The annotations associated with a disposition.
+
+        The :class:`Data` object retrieved by this operation may be modified
+        prior to updating a delivery. When a delivery is updated, the
+        annotations described by the :class:`Data` are reported to the peer
+        if applicable to the current delivery state, e.g. states such as
+        :const:`MODIFIED`. The :class:`Data` must be empty or contain a symbol
+        keyed map.
+
+        The :class:`Data` object returned by this operation is valid until
+        the parent delivery is settled.
+
+        :type: :class:`Data`
+        """)
 
     def _get_condition(self):
         if self.local:
@@ -149,7 +247,17 @@
         else:
             raise AttributeError("condition attribute is read-only")
 
-    condition = property(_get_condition, _set_condition)
+    condition = property(_get_condition, _set_condition, doc="""
+        The condition object associated with a disposition.
+        
+        The :class:`Condition` object retrieved by this operation may be
+        modified prior to updating a delivery. When a delivery is updated,
+        the condition described by the disposition is reported to the peer
+        if applicable to the current delivery state, e.g. states such as
+        :const:`REJECTED`.
+
+        :type: :class:`Condition`
+        """)
 
 
 class Delivery(Wrapper):
@@ -158,10 +266,42 @@
     """
 
     RECEIVED = Disposition.RECEIVED
+    """
+    A non terminal state indicating how much (if any) message data
+    has been received for a delivery.
+    """    
+
     ACCEPTED = Disposition.ACCEPTED
+    """
+    A terminal state indicating that the delivery was successfully
+    processed. Once in this state there will be no further state
+    changes prior to the delivery being settled.
+    """
+
     REJECTED = Disposition.REJECTED
+    """
+    A terminal state indicating that the delivery could not be
+    processed due to some error condition. Once in this state
+    there will be no further state changes prior to the delivery
+    being settled.
+    """
+
     RELEASED = Disposition.RELEASED
+    """
+    A terminal state indicating that the delivery is being
+    returned to the sender. Once in this state there will be no
+    further state changes prior to the delivery being settled.
+    """
+
     MODIFIED = Disposition.MODIFIED
+    """
+    A terminal state indicating that the delivery is being
+    returned to the sender and should be annotated by the
+    sender prior to further delivery attempts. Once in this
+    state there will be no further state changes prior to the
+    delivery being settled.
+    """
+
 
     @staticmethod
     def wrap(impl):
@@ -179,28 +319,51 @@
 
     @property
     def tag(self):
-        """The identifier for the delivery."""
+        """
+        The identifier for the delivery.
+
+        :type: ``bytes``
+        """
         return pn_delivery_tag(self._impl)
 
     @property
     def writable(self):
-        """Returns true for an outgoing delivery to which data can now be written."""
+        """
+        ``True`` for an outgoing delivery to which data can now be written,
+        ``False`` otherwise..
+
+        :type: ``bool``
+        """
         return pn_delivery_writable(self._impl)
 
     @property
     def readable(self):
-        """Returns true for an incoming delivery that has data to read."""
+        """
+        ``True`` for an incoming delivery that has data to read,
+        ``False`` otherwise..
+
+        :type: ``bool``
+        """
         return pn_delivery_readable(self._impl)
 
     @property
     def updated(self):
-        """Returns true if the state of the delivery has been updated
-        (e.g. it has been settled and/or accepted, rejected etc)."""
+        """
+        ``True`` if the state of the delivery has been updated
+        (e.g. it has been settled and/or accepted, rejected etc),
+        ``False`` otherwise.
+
+        :type: ``bool``
+        """
         return pn_delivery_updated(self._impl)
 
     def update(self, state):
         """
-        Set the local state of the delivery e.g. ACCEPTED, REJECTED, RELEASED.
+        Set the local state of the delivery e.g. :const:`ACCEPTED`,
+        :const:`REJECTED`, :const:`RELEASED`.
+
+        :param state: State of delivery
+        :type state: ``int``
         """
         obj2dat(self.local._data, pn_disposition_data(self.local._impl))
         obj2dat(self.local._annotations, pn_disposition_annotations(self.local._impl))
@@ -209,33 +372,49 @@
 
     @property
     def pending(self):
+        """
+        The amount of pending message data for a delivery.
+
+        :type: ``int``
+        """
         return pn_delivery_pending(self._impl)
 
     @property
     def partial(self):
         """
-        Returns true for an incoming delivery if not all the data is
-        yet available.
+        ``True`` for an incoming delivery if not all the data is
+        yet available, ``False`` otherwise.
+
+        :type: ``bool``
         """
         return pn_delivery_partial(self._impl)
 
     @property
     def local_state(self):
-        """Returns the local state of the delivery."""
+        """
+        A string representation of the local state of the delivery.
+
+        :type: ``str``
+        """
         return DispositionType.get(pn_delivery_local_state(self._impl))
 
     @property
     def remote_state(self):
         """
-        Returns the state of the delivery as indicated by the remote
-        peer.
+        A string representation of the state of the delivery as
+        indicated by the remote peer.
+
+        :type: ``str``
         """
         return DispositionType.get(pn_delivery_remote_state(self._impl))
 
     @property
     def settled(self):
         """
-        Returns true if the delivery has been settled by the remote peer.
+        ``True`` if the delivery has been settled by the remote peer,
+        ``False`` otherwise.
+
+        :type: ``bool``
         """
         return pn_delivery_settled(self._impl)
 
@@ -249,7 +428,11 @@
 
     @property
     def aborted(self):
-        """Returns true if the delivery has been aborted."""
+        """
+        ``True`` if the delivery has been aborted, ``False`` otherwise.
+
+        :type: ``bool``
+        """
         return pn_delivery_aborted(self._impl)
 
     def abort(self):
@@ -262,12 +445,20 @@
 
     @property
     def work_next(self):
+        """
+        The next :class:`Delivery` on the connection that has pending
+        operations.
+
+        :type: :class:`Delivery`
+        """
         return Delivery.wrap(pn_work_next(self._impl))
 
     @property
     def link(self):
         """
-        Returns the link on which the delivery was sent or received.
+        The :class:`Link` on which the delivery was sent or received.
+
+        :type: :class:`Link`
         """
         from . import _endpoints
         return _endpoints.Link.wrap(pn_delivery_link(self._impl))
@@ -275,17 +466,27 @@
     @property
     def session(self):
         """
-        Returns the session over which the delivery was sent or received.
+        The :class:`Session` over which the delivery was sent or received.
+
+        :type: :class:`Session`
         """
         return self.link.session
 
     @property
     def connection(self):
         """
-        Returns the connection over which the delivery was sent or received.
+        The :class:`Connection` over which the delivery was sent or received.
+
+        :type: :class:`Connection`
         """
         return self.session.connection
 
     @property
     def transport(self):
+        """
+        The :class:`Transport` bound to the :class:`Connection` over which
+        the delivery was sent or received.
+
+        :type: :class:`Transport`
+        """
         return self.connection.transport
diff --git a/python/proton/_endpoints.py b/python/proton/_endpoints.py
index a497b67..f4f68e2 100644
--- a/python/proton/_endpoints.py
+++ b/python/proton/_endpoints.py
@@ -65,12 +65,43 @@
 
 
 class Endpoint(object):
-    LOCAL_UNINIT = PN_LOCAL_UNINIT
+    """
+    Abstract class from which :class:`Connection`, :class:`Session`
+    and :class:`Link` are derived, and which defines the state
+    of these classes.
+
+    The :class:`Endpoint` state is an integral value with flags that
+    encode both the local and remote state of an AMQP Endpoint
+    (:class:`Connection`, :class:`Link`, or :class:`Session`).
+    The individual bits may be accessed using :const:`LOCAL_UNINIT`,
+    :const:`LOCAL_ACTIVE`, :const:`LOCAL_CLOSED`, and
+    :const:`REMOTE_UNINIT`, :const:`REMOTE_ACTIVE`, :const:`REMOTE_CLOSED`.
+
+    Every AMQP endpoint (:class:`Connection`, :class:`Link`, or
+    :class:`Session`) starts out in an uninitialized state and then
+    proceeds linearly to an active and then closed state. This
+    lifecycle occurs at both endpoints involved, and so the state
+    model for an endpoint includes not only the known local state,
+    but also the last known state of the remote endpoint.
+    """
+
+    LOCAL_UNINIT = PN_LOCAL_UNINIT 
+    """ The local  endpoint state is uninitialized. """
+
     REMOTE_UNINIT = PN_REMOTE_UNINIT
+    """ The local endpoint state is active. """
+
     LOCAL_ACTIVE = PN_LOCAL_ACTIVE
+    """ The local endpoint state is closed. """
+
     REMOTE_ACTIVE = PN_REMOTE_ACTIVE
+    """ The remote endpoint state is uninitialized. """
+
     LOCAL_CLOSED = PN_LOCAL_CLOSED
+    """ The remote endpoint state is active. """
+
     REMOTE_CLOSED = PN_REMOTE_CLOSED
+    """ The remote endpoint state is closed. """
 
     def _init(self):
         self.condition = None
@@ -81,6 +112,12 @@
 
     @property
     def remote_condition(self):
+        """
+        The remote condition associated with the connection endpoint.
+        See :class:`Condition` for more information.
+
+        :type: :class:`Condition`
+        """
         return cond2obj(self._get_remote_cond_impl())
 
     # the following must be provided by subclasses
@@ -97,19 +134,25 @@
         # TODO Hack This is here for some very odd (IMO) backwards compat behaviour
         from ._events import Handler
         if handler is None:
-          self._handler = None
+            self._handler = None
         elif issubclass(type(handler), Handler):
             self._handler = handler
         else:
             self._handler = Handler()
             self._handler.add(handler)
 
-    handler = property(_get_handler, _set_handler)
+    handler = property(_get_handler, _set_handler, doc="""
+        Handler for events.
+
+        :getter: Get the event handler, or return ``None`` if no handler has been set.
+        :setter: Set the event handler.
+        :type: :class:`Handler` or ``None``
+        """)
 
 
 class Connection(Wrapper, Endpoint):
     """
-    A representation of an AMQP connection
+    A representation of an AMQP connection.
     """
 
     @staticmethod
@@ -135,10 +178,21 @@
 
     @property
     def connection(self):
+        """
+        Get this connection.
+
+        :type: :class:`Connection`
+        """
         return self
 
     @property
     def transport(self):
+        """
+        The transport bound to this connection. If the connection
+        is unbound, then this operation will return ``None``.
+
+        :type: :class:`Transport` or ``None``
+        """
         return Transport.wrap(pn_connection_transport(self._impl))
 
     def _check(self, err):
@@ -154,6 +208,7 @@
     def _get_remote_cond_impl(self):
         return pn_connection_remote_condition(self._impl)
 
+    # TODO: Blacklisted API call
     def collect(self, collector):
         if collector is None:
             pn_connection_collect(self._impl, None)
@@ -167,7 +222,11 @@
     def _set_container(self, name):
         pn_connection_set_container(self._impl, unicode2utf8(name))
 
-    container = property(_get_container, _set_container)
+    container = property(_get_container, _set_container, doc="""
+        The container name for this connection object.
+
+        :type: ``str``
+        """)
 
     def _get_hostname(self):
         return utf82unicode(pn_connection_get_hostname(self._impl))
@@ -175,14 +234,15 @@
     def _set_hostname(self, name):
         pn_connection_set_hostname(self._impl, unicode2utf8(name))
 
-    hostname = property(_get_hostname, _set_hostname,
-                        doc="""
-Set the name of the host (either fully qualified or relative) to which this
-connection is connecting to.  This information may be used by the remote
-peer to determine the correct back-end service to connect the client to.
-This value will be sent in the Open performative, and will be used by SSL
-and SASL layers to identify the peer.
-""")
+    hostname = property(_get_hostname, _set_hostname, doc="""
+        Set the name of the host (either fully qualified or relative) to which this
+        connection is connecting to.  This information may be used by the remote
+        peer to determine the correct back-end service to connect the client to.
+        This value will be sent in the Open performative, and will be used by SSL
+        and SASL layers to identify the peer.
+
+        :type: ``str``
+        """)
 
     def _get_user(self):
         return utf82unicode(pn_connection_get_user(self._impl))
@@ -190,7 +250,20 @@
     def _set_user(self, name):
         pn_connection_set_user(self._impl, unicode2utf8(name))
 
-    user = property(_get_user, _set_user)
+    user = property(_get_user, _set_user, doc="""
+        The authentication username for a client connection.
+
+        It is necessary to set the username and password before binding
+        the connection to a transport and it isn't allowed to change
+        after the binding.
+
+        If not set then no authentication will be negotiated unless the
+        client sasl layer is explicitly created (this would be for something
+        like Kerberos where the credentials are implicit in the environment,
+        or to explicitly use the ``ANONYMOUS`` SASL mechanism)
+
+        :type: ``str``
+        """)
 
     def _get_password(self):
         return None
@@ -198,35 +271,98 @@
     def _set_password(self, name):
         pn_connection_set_password(self._impl, unicode2utf8(name))
 
-    password = property(_get_password, _set_password)
+    password = property(_get_password, _set_password, doc="""
+        Set the authentication password for a client connection.
+
+        It is necessary to set the username and password before binding the connection
+        to a transport and it isn't allowed to change after the binding.
+
+        .. note:: Getting the password always returns ``None``.
+
+        :type: ``str``
+        """)
 
     @property
     def remote_container(self):
-        """The container identifier specified by the remote peer for this connection."""
+        """
+        The container identifier specified by the remote peer for this connection.
+
+        This will return ``None`` until the :const:'REMOTE_ACTIVE` state is
+        reached. See :class:`Endpoint` for more details on endpoint state.
+
+        Any (non ``None``) name returned by this operation will be valid until
+        the connection object is unbound from a transport or freed,
+        whichever happens sooner.
+
+        :type: ``str``
+        """
         return pn_connection_remote_container(self._impl)
 
     @property
     def remote_hostname(self):
-        """The hostname specified by the remote peer for this connection."""
+        """
+        The hostname specified by the remote peer for this connection.
+
+        This will return ``None`` until the :const:`REMOTE_ACTIVE` state is
+        reached. See :class:`Endpoint` for more details on endpoint state.
+
+        Any (non ``None``) name returned by this operation will be valid until
+        the connection object is unbound from a transport or freed,
+        whichever happens sooner.
+
+        :type: ``str``
+        """
         return pn_connection_remote_hostname(self._impl)
 
     @property
     def remote_offered_capabilities(self):
-        """The capabilities offered by the remote peer for this connection."""
+        """
+        The capabilities offered by the remote peer for this connection.
+
+        This operation will return a :class:`Data` object that
+        is valid until the connection object is freed. This :class:`Data`
+        object will be empty until the remote connection is opened as
+        indicated by the :const:`REMOTE_ACTIVE` flag.
+
+        :type: :class:`Data`
+        """
         return dat2obj(pn_connection_remote_offered_capabilities(self._impl))
 
     @property
     def remote_desired_capabilities(self):
-        """The capabilities desired by the remote peer for this connection."""
+        """
+        The capabilities desired by the remote peer for this connection.
+
+        This operation will return a :class:`Data` object that
+        is valid until the connection object is freed. This :class:`Data`
+        object will be empty until the remote connection is opened as
+        indicated by the :const:`REMOTE_ACTIVE` flag.
+
+        :type: :class:`Data`
+        """
         return dat2obj(pn_connection_remote_desired_capabilities(self._impl))
 
     @property
     def remote_properties(self):
-        """The properties specified by the remote peer for this connection."""
+        """
+        The properties specified by the remote peer for this connection.
+
+        This operation will return a :class:`Data` object that
+        is valid until the connection object is freed. This :class:`Data`
+        object will be empty until the remote connection is opened as
+        indicated by the :const:`REMOTE_ACTIVE` flag.
+
+        :type: :class:`Data`
+        """
         return dat2obj(pn_connection_remote_properties(self._impl))
 
     @property
     def connected_address(self):
+        """
+        The address for this connection.
+
+        :type: ``str``
+        """
         return self.url and str(self.url)
 
     def open(self):
@@ -234,7 +370,7 @@
         Opens the connection.
 
         In more detail, this moves the local state of the connection to
-        the ACTIVE state and triggers an open frame to be sent to the
+        the ``ACTIVE`` state and triggers an open frame to be sent to the
         peer. A connection is fully active once both peers have opened it.
         """
         obj2dat(self.offered_capabilities,
@@ -249,7 +385,7 @@
         Closes the connection.
 
         In more detail, this moves the local state of the connection to
-        the CLOSED state and triggers a close frame to be sent to the
+        the ``CLOSED`` state and triggers a close frame to be sent to the
         peer. A connection is fully closed once both peers have closed it.
         """
         self._update_cond()
@@ -263,15 +399,19 @@
         """
         The state of the connection as a bit field. The state has a local
         and a remote component. Each of these can be in one of three
-        states: UNINIT, ACTIVE or CLOSED. These can be tested by masking
-        against LOCAL_UNINIT, LOCAL_ACTIVE, LOCAL_CLOSED, REMOTE_UNINIT,
-        REMOTE_ACTIVE and REMOTE_CLOSED.
+        states: ``UNINIT``, ``ACTIVE`` or ``CLOSED``. These can be tested by masking
+        against :const:`LOCAL_UNINIT`, :const:`LOCAL_ACTIVE`, :const:`LOCAL_CLOSED`, :const:`REMOTE_UNINIT`,
+        :const:`REMOTE_ACTIVE` and :const:`REMOTE_CLOSED`.
         """
         return pn_connection_state(self._impl)
 
     def session(self):
         """
         Returns a new session on this connection.
+
+        :return: New session
+        :rtype: :class:`Session`
+        :raises: :class:`SessionException`
         """
         ssn = pn_session(self._impl)
         if ssn is None:
@@ -280,25 +420,89 @@
             return Session(ssn)
 
     def session_head(self, mask):
+        """
+        Retrieve the first session from a given connection that matches the
+        specified state mask.
+
+        Examines the state of each session owned by the connection, and
+        returns the first session that matches the given state mask. If
+        state contains both local and remote flags, then an exact match
+        against those flags is performed. If state contains only local or
+        only remote flags, then a match occurs if any of the local or
+        remote flags are set respectively.
+
+        :param mask: State mask to match
+        :return: The first session owned by the connection that matches the
+            mask, else ``None`` if no sessions matches.
+        :rtype: :class:`Session` or ``None``
+        """
         return Session.wrap(pn_session_head(self._impl, mask))
 
     def link_head(self, mask):
+        """
+        Retrieve the first link that matches the given state mask.
+
+        Examines the state of each link owned by the connection and returns
+        the first link that matches the given state mask. If state contains
+        both local and remote flags, then an exact match against those
+        flags is performed. If state contains only local or only remote
+        flags, then a match occurs if any of the local or remote flags are
+        set respectively. ``state==0`` matches all links.
+
+        :param mask: State mask to match
+        :type mask: ``int``
+        :return: The first link owned by the connection that matches the
+            mask, else ``None`` if no link matches.
+        :rtype: :class:`Link` or ``None``
+        """
         return Link.wrap(pn_link_head(self._impl, mask))
 
     @property
     def work_head(self):
+        """
+        Extracts the first delivery on the connection that has pending
+        operations.
+
+        Retrieves the first delivery on the Connection that has pending
+        operations. A readable delivery indicates message data is waiting
+        to be read. A writable delivery indicates that message data may be
+        sent. An updated delivery indicates that the delivery's disposition
+        has changed. A delivery will never be both readable and writable,
+        but it may be both readable and updated or both writable and
+        updated.
+
+        :return: The first delivery object that needs to be serviced, or ``None`` if none.
+        :rtype: :class:`Delivery` or ``None``
+        """
         return Delivery.wrap(pn_work_head(self._impl))
 
     @property
     def error(self):
+        """
+        Additional error information associated with the connection.
+
+        Whenever a connection operation fails (i.e. returns an error code),
+        additional error details can be obtained using this property. The
+        returned value is the error code defined by Proton in ``pn_error_t``
+        (see ``error.h``).
+        
+        :type: ``int``
+        """
         return pn_error_code(pn_connection_error(self._impl))
 
     def free(self):
+        """
+        Releases this connection object.
+
+        When a connection object is released, all :class:`Session` and
+        :class:`Link` objects associated with this connection are also
+        released and all :class:`Delivery` objects are settled.
+        """
         pn_connection_release(self._impl)
 
 
 class Session(Wrapper, Endpoint):
-
+    """A container of links"""
     @staticmethod
     def wrap(impl):
         if impl is None:
@@ -324,7 +528,19 @@
     def _set_incoming_capacity(self, capacity):
         pn_session_set_incoming_capacity(self._impl, capacity)
 
-    incoming_capacity = property(_get_incoming_capacity, _set_incoming_capacity)
+    incoming_capacity = property(_get_incoming_capacity, _set_incoming_capacity, doc="""
+        The incoming capacity of this session in bytes. The incoming capacity
+        of a session determines how much incoming message data the session
+        can buffer.
+
+        .. note:: If set, this value must be greater than or equal to the negotiated
+            frame size of the transport. The window is computed as a whole number of
+            frames when dividing remaining capacity at a given time by the connection
+            max frame size. As such, capacity and max frame size should be chosen so
+            as to ensure the frame window isn't unduly small and limiting performance.
+
+        :type: ``int`` (bytes)
+        """)
 
     def _get_outgoing_window(self):
         return pn_session_get_outgoing_window(self._impl)
@@ -332,60 +548,146 @@
     def _set_outgoing_window(self, window):
         pn_session_set_outgoing_window(self._impl, window)
 
-    outgoing_window = property(_get_outgoing_window, _set_outgoing_window)
+    outgoing_window = property(_get_outgoing_window, _set_outgoing_window, doc="""
+        The outgoing window for this session.
+
+        :type: ``int``
+        """)
 
     @property
     def outgoing_bytes(self):
+        """
+        The number of outgoing bytes currently buffered.
+
+        :type: ``int`` (bytes)
+        """
         return pn_session_outgoing_bytes(self._impl)
 
     @property
     def incoming_bytes(self):
+        """
+        The number of incoming bytes currently buffered.
+
+        :type: ``int`` (bytes)
+        """
         return pn_session_incoming_bytes(self._impl)
 
     def open(self):
+        """
+        Open a session. Once this operation has completed, the
+        :const:`LOCAL_ACTIVE` state flag will be set.
+        """
         pn_session_open(self._impl)
 
     def close(self):
+        """
+        Close a session.
+
+        Once this operation has completed, the :const:`LOCAL_CLOSED` state flag
+        will be set. This may be called without calling
+        :meth:`open`, in this case it is equivalent to calling
+        :meth:`open` followed by :meth:`close`.
+        
+        """
         self._update_cond()
         pn_session_close(self._impl)
 
     def next(self, mask):
+        """
+        Retrieve the next session for this connection that matches the
+        specified state mask.
+
+        When used with :meth:`Connection.session_head`, application can
+        access all sessions on the connection that match the given state.
+        See :meth:`Connection.session_head` for description of match
+        behavior.
+
+        :param mask: Mask to match.
+        :return: The next session owned by this connection that matches the
+            mask, else ``None`` if no sessions match.
+        :rtype: :class:`Session` or ``None``
+        """
         return Session.wrap(pn_session_next(self._impl, mask))
 
     @property
     def state(self):
+        """
+        The endpoint state flags for this session. See :class:`Endpoint` for
+        details of the flags.
+
+        :type: ``int``
+        """
         return pn_session_state(self._impl)
 
     @property
     def connection(self):
+        """
+        The parent connection for this session.
+
+        :type: :class:`Connection`
+        """
         return Connection.wrap(pn_session_connection(self._impl))
 
     @property
     def transport(self):
+        """
+        The transport bound to the parent connection for this session.
+
+        :type: :class:`Transport`
+        """
         return self.connection.transport
 
     def sender(self, name):
+        """
+        Create a new :class:`Sender` on this session.
+
+        :param name: Name of sender
+        :type name: ``str``
+        :return: New Sender object
+        :rtype: :class:`Sender`
+        """
         return Sender(pn_sender(self._impl, unicode2utf8(name)))
 
     def receiver(self, name):
+        """
+        Create a new :class:`Receiver` on this session.
+
+        :param name: Name of receiver
+        :type name: ``str``
+        :return: New Receiver object
+        :rtype: :class:`Receiver`
+        """
         return Receiver(pn_receiver(self._impl, unicode2utf8(name)))
 
     def free(self):
+        """
+        Free this session. When a session is freed it will no
+        longer be retained by the connection once any internal
+        references to the session are no longer needed. Freeing
+        a session will free all links on that session and settle
+        any deliveries on those links.
+        """
         pn_session_free(self._impl)
 
 
 class Link(Wrapper, Endpoint):
     """
-    A representation of an AMQP link, of which there are two concrete
-    implementations, Sender and Receiver.
+    A representation of an AMQP link (a unidirectional channel for
+    transferring messages), of which there are two concrete
+    implementations, :class:`Sender` and :class:`Receiver`.
     """
 
     SND_UNSETTLED = PN_SND_UNSETTLED
+    """The sender will send all deliveries initially unsettled."""
     SND_SETTLED = PN_SND_SETTLED
+    """The sender will send all deliveries settled to the receiver."""
     SND_MIXED = PN_SND_MIXED
+    """The sender may send a mixture of settled and unsettled deliveries."""
 
     RCV_FIRST = PN_RCV_FIRST
+    """The receiver will settle deliveries regardless of what the sender does."""
     RCV_SECOND = PN_RCV_SECOND
+    """The receiver will only settle deliveries after the sender settles."""
 
     @staticmethod
     def wrap(impl):
@@ -419,8 +721,9 @@
         Opens the link.
 
         In more detail, this moves the local state of the link to the
-        ACTIVE state and triggers an attach frame to be sent to the
-        peer. A link is fully active once both peers have attached it.
+        :const:`LOCAL_ACTIVE` state and triggers an attach frame to be
+        sent to the peer. A link is fully active once both peers have
+        attached it.
         """
         pn_link_open(self._impl)
 
@@ -429,9 +732,12 @@
         Closes the link.
 
         In more detail, this moves the local state of the link to the
-        CLOSED state and triggers an detach frame (with the closed flag
-        set) to be sent to the peer. A link is fully closed once both
-        peers have detached it.
+        :const:`LOCAL_CLOSED` state and triggers an detach frame (with
+        the closed flag set) to be sent to the peer. A link is fully
+        closed once both peers have detached it.
+
+        This may be called without calling :meth:`open`, in this case it
+        is equivalent to calling :meth:`open` followed by :meth:`close`.
         """
         self._update_cond()
         pn_link_close(self._impl)
@@ -441,96 +747,273 @@
         """
         The state of the link as a bit field. The state has a local
         and a remote component. Each of these can be in one of three
-        states: UNINIT, ACTIVE or CLOSED. These can be tested by masking
-        against LOCAL_UNINIT, LOCAL_ACTIVE, LOCAL_CLOSED, REMOTE_UNINIT,
-        REMOTE_ACTIVE and REMOTE_CLOSED.
+        states: ``UNINIT``, ``ACTIVE`` or ``CLOSED``. These can be
+        tested by masking against :const:`LOCAL_UNINIT`,
+        :const:`LOCAL_ACTIVE`, :const:`LOCAL_CLOSED`,
+        :const:`REMOTE_UNINIT`, :const:`REMOTE_ACTIVE` and
+        :const:`REMOTE_CLOSED`.
+
+        :type: ``int``
         """
         return pn_link_state(self._impl)
 
     @property
     def source(self):
-        """The source of the link as described by the local peer."""
+        """
+        The source of the link as described by the local peer. The
+        returned object is valid until the link is freed.
+
+        :type: :class:`Terminus`
+        """
         return Terminus(pn_link_source(self._impl))
 
     @property
     def target(self):
-        """The target of the link as described by the local peer."""
+        """
+        The target of the link as described by the local peer. The
+        returned object is valid until the link is freed.
+
+        :type: :class:`Terminus`
+        """
         return Terminus(pn_link_target(self._impl))
 
     @property
     def remote_source(self):
-        """The source of the link as described by the remote peer."""
+        """
+        The source of the link as described by the remote peer. The
+        returned object is valid until the link is freed. The remote
+        :class:`Terminus` object will be empty until the link is
+        remotely opened as indicated by the :const:`REMOTE_ACTIVE`
+        flag.
+
+        :type: :class:`Terminus`
+        """
         return Terminus(pn_link_remote_source(self._impl))
 
     @property
     def remote_target(self):
-        """The target of the link as described by the remote peer."""
+        """
+        The target of the link as described by the remote peer. The
+        returned object is valid until the link is freed. The remote
+        :class:`Terminus` object will be empty until the link is
+        remotely opened as indicated by the :const:`REMOTE_ACTIVE`
+        flag.
+
+        :type: :class:`Terminus`
+        """
         return Terminus(pn_link_remote_target(self._impl))
 
     @property
     def session(self):
+        """
+        The parent session for this link.
+
+        :type: :class:`Session`
+        """
         return Session.wrap(pn_link_session(self._impl))
 
     @property
     def connection(self):
-        """The connection on which this link was attached."""
+        """
+        The connection on which this link was attached.
+
+        :type: :class:`Connection`
+        """
         return self.session.connection
 
     @property
     def transport(self):
+        """
+        The transport bound to the connection on which this link was attached.
+
+        :type: :class:`Transport`
+        """
         return self.session.transport
 
     def delivery(self, tag):
+        """
+        Create a delivery. Every delivery object within a
+        link must be supplied with a unique tag. Links
+        maintain a sequence of delivery object in the order that
+        they are created.
+
+        :param tag: Delivery tag unique for this link.
+        :type tag: ``bytes``
+        :rtype: :class:`Delivery`
+        """
         return Delivery(pn_delivery(self._impl, tag))
 
     @property
     def current(self):
+        """
+        The current delivery for this link.
+
+        Each link maintains a sequence of deliveries in the order
+        they were created, along with a pointer to the *current*
+        delivery. All send/recv operations on a link take place
+        on the *current* delivery. If a link has no current delivery,
+        the current delivery is automatically initialized to the
+        next delivery created on the link. Once initialized, the
+        current delivery remains the same until it is changed through
+        use of :meth:`advance` or until it is settled via
+        :meth:`Delivery.settle`.
+
+        :rtype: :class:`Delivery`
+        """
         return Delivery.wrap(pn_link_current(self._impl))
 
     def advance(self):
+        """
+        Advance the current delivery of this link to the next delivery.
+
+        For sending links this operation is used to finish sending message
+        data for the current outgoing delivery and move on to the next
+        outgoing delivery (if any).
+
+        For receiving links, this operation is used to finish accessing
+        message data from the current incoming delivery and move on to the
+        next incoming delivery (if any).
+
+        Each link maintains a sequence of deliveries in the order they were
+        created, along with a pointer to the *current* delivery. The
+        :meth:`advance` operation will modify the *current* delivery on the
+        link to point to the next delivery in the sequence. If there is no
+        next delivery in the sequence, the current delivery will be set to
+        ``NULL``.
+
+        :return: ``True`` if the value of the current delivery changed (even
+            if it was set to ``NULL``, ``False`` otherwise.
+        :rtype: ``bool``
+        """
         return pn_link_advance(self._impl)
 
     @property
     def unsettled(self):
+        """
+        The number of unsettled deliveries for this link.
+
+        :type: ``int``
+        """
         return pn_link_unsettled(self._impl)
 
     @property
     def credit(self):
-        """The amount of outstanding credit on this link."""
+        """
+        The amount of outstanding credit on this link.
+
+        Links use a credit based flow control scheme. Every receiver
+        maintains a credit balance that corresponds to the number of
+        deliveries that the receiver can accept at any given moment. As
+        more capacity becomes available at the receiver (see
+        :meth:`Receiver.flow`), it adds credit to this balance and
+        communicates the new balance to the sender. Whenever a delivery
+        is sent/received, the credit balance maintained by the link is
+        decremented by one. Once the credit balance at the sender reaches
+        zero, the sender must pause sending until more credit is obtained
+        from the receiver.
+
+        .. note:: A sending link may still be used to send deliveries even
+            if :attr:`credit` reaches zero, however those deliveries will end
+            up being buffered by the link until enough credit is obtained from
+            the receiver to send them over the wire. In this case the balance
+            reported by :attr:`credit` will go negative.
+
+        :type: ``int``
+        """
         return pn_link_credit(self._impl)
 
     @property
     def available(self):
+        """
+        The available deliveries hint for this link.
+
+        The available count for a link provides a hint as to the number of
+        deliveries that might be able to be sent if sufficient credit were
+        issued by the receiving link endpoint. See :meth:`Sender.offered` for
+        more details.
+
+        :type: ``int``
+        """
         return pn_link_available(self._impl)
 
     @property
     def queued(self):
+        """
+        The number of queued deliveries for a link.
+
+        Links may queue deliveries for a number of reasons, for example
+        there may be insufficient credit to send them to the receiver (see
+        :meth:`credit`), or they simply may not have yet had a chance to
+        be written to the wire. This operation will return the number of
+        queued deliveries on a link.
+
+        :type: ``int``
+        """
         return pn_link_queued(self._impl)
 
     def next(self, mask):
+        """
+        Retrieve the next link that matches the given state mask.
+
+        When used with :meth:`Connection.link_head`, the application
+        can access all links on the connection that match the given
+        state. See :meth:`Connection.link_head` for a description of
+        match behavior.
+
+        :param mask: State mask to match
+        :type mask: ``int``
+        :return: The next link that matches the given state mask, or
+                 ``None`` if no link matches.
+        :rtype: :class:`Link`
+        """
         return Link.wrap(pn_link_next(self._impl, mask))
 
     @property
     def name(self):
-        """Returns the name of the link"""
+        """
+        The name of the link.
+
+        :type: ``str``
+        """
         return utf82unicode(pn_link_name(self._impl))
 
     @property
     def is_sender(self):
-        """Returns true if this link is a sender."""
+        """
+        ``True`` if this link is a sender, ``False`` otherwise.
+
+        :type: ``bool``
+        """
         return pn_link_is_sender(self._impl)
 
     @property
     def is_receiver(self):
-        """Returns true if this link is a receiver."""
+        """
+        ``True`` if this link is a receiver, ``False`` otherwise.
+
+        :type: ``bool``
+        """
         return pn_link_is_receiver(self._impl)
 
     @property
     def remote_snd_settle_mode(self):
+        """
+        The remote sender settle mode for this link. One of
+        :const:`SND_UNSETTLED`, :const:`SND_SETTLED` or
+        :const:`SND_MIXED`.
+
+        :type: ``int``
+        """
         return pn_link_remote_snd_settle_mode(self._impl)
 
     @property
     def remote_rcv_settle_mode(self):
+        """
+        The remote receiver settle mode for this link. One of
+        :const:`RCV_FIRST` or :const:`RCV_SECOND`.
+
+        :type: ``int``
+        """
         return pn_link_remote_rcv_settle_mode(self._impl)
 
     def _get_snd_settle_mode(self):
@@ -539,7 +1022,13 @@
     def _set_snd_settle_mode(self, mode):
         pn_link_set_snd_settle_mode(self._impl, mode)
 
-    snd_settle_mode = property(_get_snd_settle_mode, _set_snd_settle_mode)
+    snd_settle_mode = property(_get_snd_settle_mode, _set_snd_settle_mode, doc="""
+        The local sender settle mode for this link. One of
+        :const:`SND_UNSETTLED`, :const:`SND_SETTLED` or
+        :const:`SND_MIXED`.
+
+        :type: ``int``
+        """)
 
     def _get_rcv_settle_mode(self):
         return pn_link_rcv_settle_mode(self._impl)
@@ -547,7 +1036,12 @@
     def _set_rcv_settle_mode(self, mode):
         pn_link_set_rcv_settle_mode(self._impl, mode)
 
-    rcv_settle_mode = property(_get_rcv_settle_mode, _set_rcv_settle_mode)
+    rcv_settle_mode = property(_get_rcv_settle_mode, _set_rcv_settle_mode, doc="""
+        The local receiver settle mode for this link. One of
+        :const:`RCV_FIRST` or :const:`RCV_SECOND`.
+
+        :type: ``int``
+        """)
 
     def _get_drain(self):
         return pn_link_get_drain(self._impl)
@@ -555,13 +1049,54 @@
     def _set_drain(self, b):
         pn_link_set_drain(self._impl, bool(b))
 
-    drain_mode = property(_get_drain, _set_drain)
+    drain_mode = property(_get_drain, _set_drain, doc="""
+        The drain mode on this link.
+
+        If a link is in drain mode (``True``), then the sending
+        endpoint of a link must immediately use up all available
+        credit on the link. If this is not possible, the excess
+        credit must be returned by invoking :meth:`drained`. Only
+        the receiving endpoint can set the drain mode.
+
+        When ``False``, this link is not in drain mode.
+
+        :type: ``bool``
+        """)
 
     def drained(self):
+        """
+        Drain excess credit for this link.
+
+        When a link is in drain mode (see :attr:`drain_mode`), the
+        sender must use all excess credit immediately, and release
+        any excess credit back to the receiver if there are no
+        deliveries available to send.
+
+        When invoked on a sending link that is in drain mode, this
+        operation will release all excess credit back to the receiver
+        and return the number of credits released back to the sender.
+        If the link is not in drain mode, this operation is a noop.
+
+        When invoked on a receiving link, this operation will return
+        and reset the number of credits the sender has released back
+        to the receiver.
+
+        :return: The number of credits drained.
+        :rtype: ``int``
+        """
         return pn_link_drained(self._impl)
 
     @property
     def remote_max_message_size(self):
+        """
+        Get the remote view of the maximum message size for this link.
+
+        .. warning:: **Unsettled API**
+
+        A zero value means the size is unlimited.
+
+        :type: ``long``
+        """
         return pn_link_remote_max_message_size(self._impl)
 
     def _get_max_message_size(self):
@@ -570,12 +1105,28 @@
     def _set_max_message_size(self, mode):
         pn_link_set_max_message_size(self._impl, mode)
 
-    max_message_size = property(_get_max_message_size, _set_max_message_size)
+    max_message_size = property(_get_max_message_size, _set_max_message_size, doc="""
+        The maximum message size for this link. A zero value means the
+        size is unlimited.
+
+        .. warning:: **Unsettled API**
+        
+        :type: ``long``
+        """)
 
     def detach(self):
+        """
+        Detach this link.
+        """
         return pn_link_detach(self._impl)
 
     def free(self):
+        """
+        Free this link object. When a link object is freed,
+        all :class:`Delivery` objects associated with the session (**<-- CHECK THIS**)
+        are also freed. Freeing a link will settle any unsettled
+        deliveries on the link.
+        """
         pn_link_free(self._impl)
 
 
@@ -585,24 +1136,33 @@
     """
 
     def offered(self, n):
+        """
+        Signal the availability of deliveries for this Sender.
+
+        :param n: Credit the number of deliveries potentially
+                  available for transfer.
+        :type n: ``int``
+        """
         pn_link_offered(self._impl, n)
 
     def stream(self, data):
         """
-        Send specified data as part of the current delivery
+        Send specified data as part of the current delivery.
 
-        @type data: binary
-        @param data: data to send
+        :param data: Data to send
+        :type data: ``binary``
         """
         return self._check(pn_link_send(self._impl, data))
 
     def send(self, obj, tag=None):
         """
+        A convenience method to send objects as message content.
+
         Send specified object over this sender; the object is expected to
-        have a send() method on it that takes the sender and an optional
+        have a ``send()`` method on it that takes the sender and an optional
         tag as arguments.
 
-        Where the object is a Message, this will send the message over
+        Where the object is a :class:`Message`, this will send the message over
         this link, creating a new delivery for the purpose.
         """
         if hasattr(obj, 'send'):
@@ -612,6 +1172,10 @@
             return self.stream(obj)
 
     def delivery_tag(self):
+        """
+        **HELP!** I have no idea what is going on with this!
+        :meth:`Link.next` returns a Link, not a Delivery.
+        """
         if not hasattr(self, 'tag_generator'):
             def simple_tags():
                 count = 1
@@ -629,10 +1193,33 @@
     """
 
     def flow(self, n):
-        """Increases the credit issued to the remote sender by the specified number of messages."""
+        """
+        Increases the credit issued to the remote sender by the specified number of messages.
+
+        :param n: The credit to be issued to the remote sender.
+        :type n: ``int``
+        """
         pn_link_flow(self._impl, n)
 
     def recv(self, limit):
+        """
+        Receive message data for the current delivery on this receiver.
+
+        .. note:: The link API can be used to stream large messages across
+            the network, so just because there is no data to read does not
+            imply the message is complete. To ensure the entirety of the
+            message data has been read, either invoke :meth:`recv` until
+            ``None`` is returned.
+
+        :param limit: the max data size to receive of this message
+        :type limit: ``int``
+        :return: The received message data, or ``None`` if the message
+            has been completely received.
+        :rtype: ``binary`` or ``None``
+        :raise: * :class:`Timeout` if timed out
+                * :class:`Interrupt` if interrupted
+                * :class:`LinkException` for all other exceptions
+        """
         n, binary = pn_link_recv(self._impl, limit)
         if n == PN_EOS:
             return None
@@ -641,30 +1228,64 @@
             return binary
 
     def drain(self, n):
+        """
+        Grant credit for incoming deliveries on this receiver, and
+        set drain mode to true.
+
+        Use :attr:`drain_mode` to set the drain mode explicitly.
+
+        :param n: The amount by which to increment the link credit
+        :type n: ``int``
+        """
         pn_link_drain(self._impl, n)
 
     def draining(self):
+        """
+        Check if a link is currently draining. A link is defined
+        to be draining when drain mode is set to ``True``, and the
+        sender still has excess credit.
+
+        :return: ``True`` if the link is currently draining, ``False`` otherwise.
+        :rtype: ``bool``
+        """
         return pn_link_draining(self._impl)
 
 
 class Terminus(object):
+    """
+    A source or target for messages.
+    """
     UNSPECIFIED = PN_UNSPECIFIED
+    """A nonexistent terminus, may used as a source or target."""   
     SOURCE = PN_SOURCE
+    """A source of messages."""
     TARGET = PN_TARGET
+    """A target for messages."""
     COORDINATOR = PN_COORDINATOR
+    """A special target identifying a transaction coordinator."""
 
     NONDURABLE = PN_NONDURABLE
+    """A non durable terminus."""
     CONFIGURATION = PN_CONFIGURATION
+    """A terminus with durably held configuration, but not delivery state."""
     DELIVERIES = PN_DELIVERIES
+    """A terminus with both durably held configuration and durably held delivery state."""
 
     DIST_MODE_UNSPECIFIED = PN_DIST_MODE_UNSPECIFIED
+    """The behavior is defined by the node."""
     DIST_MODE_COPY = PN_DIST_MODE_COPY
+    """The receiver gets all messages."""
     DIST_MODE_MOVE = PN_DIST_MODE_MOVE
+    """The receiver competes for messages."""
 
     EXPIRE_WITH_LINK = PN_EXPIRE_WITH_LINK
+    """The terminus is orphaned when the parent link is closed."""
     EXPIRE_WITH_SESSION = PN_EXPIRE_WITH_SESSION
+    """The terminus is orphaned when the parent session is closed"""
     EXPIRE_WITH_CONNECTION = PN_EXPIRE_WITH_CONNECTION
+    """The terminus is orphaned when the parent connection is closed"""
     EXPIRE_NEVER = PN_EXPIRE_NEVER
+    """The terminus is never considered orphaned"""
 
     def __init__(self, impl):
         self._impl = impl
@@ -682,16 +1303,27 @@
     def _set_type(self, type):
         self._check(pn_terminus_set_type(self._impl, type))
 
-    type = property(_get_type, _set_type)
+    type = property(_get_type, _set_type, doc="""
+        The terminus type, must be one of :const:`UNSPECIFIED`,
+        :const:`SOURCE`, :const:`TARGET` or :const:`COORDINATOR`
+
+        :type: ``int``
+        """)
 
     def _get_address(self):
-        """The address that identifies the source or target node"""
+        """
+        The address that identifies the source or target node
+        """
         return utf82unicode(pn_terminus_get_address(self._impl))
 
     def _set_address(self, address):
         self._check(pn_terminus_set_address(self._impl, unicode2utf8(address)))
 
-    address = property(_get_address, _set_address)
+    address = property(_get_address, _set_address, doc="""
+        The terminus address.
+
+        :type: ``str``
+        """)
 
     def _get_durability(self):
         return pn_terminus_get_durability(self._impl)
@@ -699,7 +1331,12 @@
     def _set_durability(self, seconds):
         self._check(pn_terminus_set_durability(self._impl, seconds))
 
-    durability = property(_get_durability, _set_durability)
+    durability = property(_get_durability, _set_durability, doc="""
+        The terminus durability mode, must be one of :const:`NONDURABLE`,
+        :const:`CONFIGURATION` or :const:`DELIVERIES`.
+
+        :type: ``int``
+        """)
 
     def _get_expiry_policy(self):
         return pn_terminus_get_expiry_policy(self._impl)
@@ -707,7 +1344,13 @@
     def _set_expiry_policy(self, seconds):
         self._check(pn_terminus_set_expiry_policy(self._impl, seconds))
 
-    expiry_policy = property(_get_expiry_policy, _set_expiry_policy)
+    expiry_policy = property(_get_expiry_policy, _set_expiry_policy, doc="""
+        The terminus expiry policy, must be one of :const:`EXPIRE_WITH_LINK`,
+        :const:`EXPIRE_WITH_SESSION`, :const:`EXPIRE_WITH_CONNECTION` or
+        :const:`EXPIRE_NEVER`.
+
+        :type: ``int``
+        """)
 
     def _get_timeout(self):
         return pn_terminus_get_timeout(self._impl)
@@ -715,7 +1358,11 @@
     def _set_timeout(self, seconds):
         self._check(pn_terminus_set_timeout(self._impl, seconds))
 
-    timeout = property(_get_timeout, _set_timeout)
+    timeout = property(_get_timeout, _set_timeout, doc="""
+        The terminus timeout in seconds.
+
+        :type: ``int``
+        """)
 
     def _is_dynamic(self):
         """Indicates whether the source or target node was dynamically
@@ -725,7 +1372,12 @@
     def _set_dynamic(self, dynamic):
         self._check(pn_terminus_set_dynamic(self._impl, dynamic))
 
-    dynamic = property(_is_dynamic, _set_dynamic)
+    dynamic = property(_is_dynamic, _set_dynamic, doc="""
+        The dynamic flag for this terminus object. This indicates if this
+        terminus was dynamically created.
+
+        :type: ``bool``
+        """)
 
     def _get_distribution_mode(self):
         return pn_terminus_get_distribution_mode(self._impl)
@@ -733,27 +1385,57 @@
     def _set_distribution_mode(self, mode):
         self._check(pn_terminus_set_distribution_mode(self._impl, mode))
 
-    distribution_mode = property(_get_distribution_mode, _set_distribution_mode)
+    distribution_mode = property(_get_distribution_mode, _set_distribution_mode, doc="""
+        The terminus distribution mode, must be one of :const:`DIST_MODE_UNSPECIFIED`,
+        :const:`DIST_MODE_COPY` or :const:`DIST_MODE_MOVE`.
+
+        :type: ``int``
+        """)
 
     @property
     def properties(self):
-        """Properties of a dynamic source or target."""
+        """
+        Properties of a dynamic source or target.
+
+        :type: :class:`Data` containing a map with :class:`symbol` keys.
+        """
         return Data(pn_terminus_properties(self._impl))
 
     @property
     def capabilities(self):
-        """Capabilities of the source or target."""
+        """
+        Capabilities of the source or target.
+
+        :type: :class:`Data` containing an array of :class:`symbol`.
+        """
         return Data(pn_terminus_capabilities(self._impl))
 
     @property
     def outcomes(self):
+        """
+        Outcomes of the source or target.
+ 
+        :type: :class:`Data` containing an array of :class:`symbol`.
+       """
         return Data(pn_terminus_outcomes(self._impl))
 
     @property
     def filter(self):
-        """A filter on a source allows the set of messages transfered over
-        the link to be restricted"""
+        """
+        A filter on a source allows the set of messages transfered over
+        the link to be restricted. The symbol-keyed map represents a'
+        filter set.
+
+        :type: :class:`Data` containing a map with :class:`symbol` keys.
+        """
         return Data(pn_terminus_filter(self._impl))
 
     def copy(self, src):
+        """
+        Copy another terminus object.
+
+        :param src: The terminus to be copied from
+        :type src: :class:`Terminus`
+        :raises: :class:`LinkException` if there is an error
+        """
         self._check(pn_terminus_copy(self._impl, src._impl))
diff --git a/python/proton/_events.py b/python/proton/_events.py
index e761312..59c3ae5 100644
--- a/python/proton/_events.py
+++ b/python/proton/_events.py
@@ -76,6 +76,14 @@
 
 
 class EventType(object):
+    """
+    Connects an event number to an event name, and is used
+    internally by :class:`Event` to represent all known
+    event types. A global list of events is maintained. An
+    :class:`EventType` created with a name but no number is
+    treated as an *extended* event, and is assigned an
+    internal event number starting at 10000.
+    """
     _lock = threading.Lock()
     _extended = TypeExtender(10000)
     TYPES = {}
@@ -124,13 +132,32 @@
 
     @property
     def type(self):
+        """
+        The type name for this event
+
+        :type: ``str``
+        """
         return self._type
 
     @property
     def handler(self):
+        """
+        The handler for this event type. Not implemented, always returns ``None``.
+
+        :type: ``None``
+        """
         return None
 
     def dispatch(self, handler, type=None):
+        """
+        Process this event by sending it to all known handlers that
+        are valid for this event type.
+
+        :param handler: Parent handler to process this event
+        :type handler: :class:`Handler`
+        :param type: Event type
+        :type type: :class:`EventType`
+        """
         type = type or self._type
         _dispatch(handler, type.method, self)
         if hasattr(handler, "handlers"):
@@ -161,46 +188,217 @@
 
 
 class Event(EventBase):
+    """
+    Notification of a state change in the protocol engine.
+    """
     TIMER_TASK = _core(PN_TIMER_TASK, "on_timer_task")
+    """A timer event has occurred."""
+
 
     CONNECTION_INIT = _core(PN_CONNECTION_INIT, "on_connection_init")
+    """
+    The connection has been created. This is the first event that
+    will ever be issued for a connection. Events of this type point
+    to the relevant connection.
+    """
+
     CONNECTION_BOUND = _core(PN_CONNECTION_BOUND, "on_connection_bound")
+    """
+    The connection has been bound to a transport. This event is
+    issued when the :meth:`Transport.bind` operation is invoked.
+    """
+
     CONNECTION_UNBOUND = _core(PN_CONNECTION_UNBOUND, "on_connection_unbound")
+    """
+    The connection has been unbound from its transport. This event is
+    issued when the :meth:`Transport.unbind` operation is invoked.
+    """
+
     CONNECTION_LOCAL_OPEN = _core(PN_CONNECTION_LOCAL_OPEN, "on_connection_local_open")
+    """
+    The local connection endpoint has been closed. Events of this
+    type point to the relevant connection.
+    """
+
     CONNECTION_LOCAL_CLOSE = _core(PN_CONNECTION_LOCAL_CLOSE, "on_connection_local_close")
+    """
+    The local connection endpoint has been closed. Events of this
+    type point to the relevant connection.
+    """
+
     CONNECTION_REMOTE_OPEN = _core(PN_CONNECTION_REMOTE_OPEN, "on_connection_remote_open")
+    """
+    The remote endpoint has opened the connection. Events of this
+    type point to the relevant connection.
+    """
+
     CONNECTION_REMOTE_CLOSE = _core(PN_CONNECTION_REMOTE_CLOSE, "on_connection_remote_close")
+    """
+    The remote endpoint has closed the connection. Events of this
+    type point to the relevant connection.
+    """
+
     CONNECTION_FINAL = _core(PN_CONNECTION_FINAL, "on_connection_final")
+    """
+    The connection has been freed and any outstanding processing has
+    been completed. This is the final event that will ever be issued
+    for a connection.
+    """
+
 
     SESSION_INIT = _core(PN_SESSION_INIT, "on_session_init")
+    """
+    The session has been created. This is the first event that will
+    ever be issued for a session.
+    """
+
     SESSION_LOCAL_OPEN = _core(PN_SESSION_LOCAL_OPEN, "on_session_local_open")
+    """
+    The local session endpoint has been opened. Events of this type
+    point to the relevant session.
+    """
+
     SESSION_LOCAL_CLOSE = _core(PN_SESSION_LOCAL_CLOSE, "on_session_local_close")
+    """
+    The local session endpoint has been closed. Events of this type
+    point ot the relevant session.
+    """
+
     SESSION_REMOTE_OPEN = _core(PN_SESSION_REMOTE_OPEN, "on_session_remote_open")
+    """
+    The remote endpoint has opened the session. Events of this type
+    point to the relevant session.
+    """
+
     SESSION_REMOTE_CLOSE = _core(PN_SESSION_REMOTE_CLOSE, "on_session_remote_close")
+    """
+    The remote endpoint has closed the session. Events of this type
+    point to the relevant session.
+    """
+
     SESSION_FINAL = _core(PN_SESSION_FINAL, "on_session_final")
+    """
+    The session has been freed and any outstanding processing has
+    been completed. This is the final event that will ever be issued
+    for a session.
+    """
+
 
     LINK_INIT = _core(PN_LINK_INIT, "on_link_init")
+    """
+    The link has been created. This is the first event that will ever
+    be issued for a link.
+    """
+
     LINK_LOCAL_OPEN = _core(PN_LINK_LOCAL_OPEN, "on_link_local_open")
+    """
+    The local link endpoint has been opened. Events of this type
+    point ot the relevant link.    
+    """
+
     LINK_LOCAL_CLOSE = _core(PN_LINK_LOCAL_CLOSE, "on_link_local_close")
+    """
+    The local link endpoint has been closed. Events of this type
+    point to the relevant link.
+    """
+
     LINK_LOCAL_DETACH = _core(PN_LINK_LOCAL_DETACH, "on_link_local_detach")
+    """
+    The local link endpoint has been detached. Events of this type
+    point to the relevant link.
+    """
+
     LINK_REMOTE_OPEN = _core(PN_LINK_REMOTE_OPEN, "on_link_remote_open")
+    """
+    The remote endpoint has opened the link. Events of this type
+    point to the relevant link.
+    """
+
     LINK_REMOTE_CLOSE = _core(PN_LINK_REMOTE_CLOSE, "on_link_remote_close")
+    """
+    The remote endpoint has closed the link. Events of this type
+    point to the relevant link.
+    """
+
     LINK_REMOTE_DETACH = _core(PN_LINK_REMOTE_DETACH, "on_link_remote_detach")
+    """
+    The remote endpoint has detached the link. Events of this type
+    point to the relevant link.
+    """
+
     LINK_FLOW = _core(PN_LINK_FLOW, "on_link_flow")
+    """
+    The flow control state for a link has changed. Events of this
+    type point to the relevant link.
+    """
+
     LINK_FINAL = _core(PN_LINK_FINAL, "on_link_final")
+    """
+    The link has been freed and any outstanding processing has been
+    completed. This is the final event that will ever be issued for a
+    link. Events of this type point to the relevant link.
+    """
+
 
     DELIVERY = _core(PN_DELIVERY, "on_delivery")
+    """
+    A delivery has been created or updated. Events of this type point
+    to the relevant delivery.
+    """
+
 
     TRANSPORT = _core(PN_TRANSPORT, "on_transport")
+    """
+    The transport has new data to read and/or write. Events of this
+    type point to the relevant transport.
+    """
+
     TRANSPORT_ERROR = _core(PN_TRANSPORT_ERROR, "on_transport_error")
+    """
+    Indicates that a transport error has occurred. Use :attr:`Transport.condition`
+    to access the details of the error from the associated transport.
+    """
+
     TRANSPORT_HEAD_CLOSED = _core(PN_TRANSPORT_HEAD_CLOSED, "on_transport_head_closed")
+    """
+    Indicates that the "head" or writing end of the transport has been closed. This
+    means the transport will never produce more bytes for output to
+    the network. Events of this type point to the relevant transport.
+    """
+
     TRANSPORT_TAIL_CLOSED = _core(PN_TRANSPORT_TAIL_CLOSED, "on_transport_tail_closed")
+    """
+    Indicates that the "tail" of the transport has been closed. This
+    means the transport will never be able to process more bytes from
+    the network. Events of this type point to the relevant transport.
+    """
+
     TRANSPORT_CLOSED = _core(PN_TRANSPORT_CLOSED, "on_transport_closed")
+    """
+    Indicates that the both the "head" and "tail" of the transport are
+    closed. Events of this type point to the relevant transport.
+    """
+
 
     # These events are now internal events in the python code
     REACTOR_INIT = _internal("reactor_init")
+    """
+    A reactor has been started. Events of this type point to the
+    reactor.
+    """
+
     REACTOR_QUIESCED = _internal("reactor_quiesced")
+    """
+    A reactor has no more events to process. Events of this type
+    point to the reactor.
+    """
+
     REACTOR_FINAL = _internal("reactor_final")
+    """
+    A reactor has been stopped. Events of this type point to the
+    reactor.
+    """
+
 
     SELECTABLE_INIT = _internal("selectable_init")
     SELECTABLE_UPDATED = _internal("selectable_updated")
@@ -268,15 +466,40 @@
 
     @property
     def clazz(self):
+        """
+        The name of the class associated with the event context.
+
+        :type: ``str``
+        """
         return self._clsname
 
     @property
     def context(self):
-        """Returns the context object associated with the event. The type of this depends on the type of event."""
+        """
+        The context object associated with the event.
+
+        :type: Depends on the type of event, and include the following:
+               - :class:`Connection`
+               - :class:`Session`
+               - :class:`Link`
+               - :class:`Delivery`
+               - :class:`Transport`
+        """
         return self._context
 
     @property
     def handler(self):
+        """
+        The handler for this event. The handler is determined by looking
+        at the following in order:
+
+        - The link
+        - The session
+        - The connection
+        - The context object with an attribute "handler"
+
+        If none of these has a handler, then ``None`` is returned.
+        """
         l = self.link
         if l:
             h = l.handler
@@ -301,14 +524,14 @@
     @property
     def reactor(self):
         """
-        Deprecated: Returns the container (was reactor) associated with the event.
+        **Deprecated** - The :class:`reactor.Container` (was reactor) associated with the event.
         """
         return self.container
 
     @property
     def container(self):
         """
-        Returns the container associated with the event.
+        The :class:`reactor.Container` associated with the event.
         """
         return self._transport._reactor
 
@@ -327,30 +550,54 @@
 
     @property
     def transport(self):
-        """Returns the transport associated with the event, or null if none is associated with it."""
+        """
+        The transport associated with the event, or ``None`` if none
+        is associated with it.
+
+        :type: :class:`Transport`
+        """
         return self._transport
 
     @property
     def connection(self):
-        """Returns the connection associated with the event, or null if none is associated with it."""
+        """
+        The connection associated with the event, or ``None`` if none
+        is associated with it.
+
+        :type: :class:`Connection`
+        """
         return self._connection
 
     @property
     def session(self):
-        """Returns the session associated with the event, or null if none is associated with it."""
+        """
+        The session associated with the event, or ``None`` if none
+        is associated with it.
+
+        :type: :class:`Session`
+        """
         return self._session
 
     @property
     def link(self):
-        """Returns the link associated with the event, or null if none is associated with it."""
+        """
+        The link associated with the event, or ``None`` if none
+        is associated with it.
+
+        :type: :class:`Link`
+        """
         return self._link
 
     @property
     def sender(self):
-        """Returns the sender link associated with the event, or null if
-           none is associated with it. This is essentially an alias for
-           link(), that does an additional check on the type of the
-           link."""
+        """
+        The sender link associated with the event, or ``None`` if
+        none is associated with it. This is essentially an alias for
+        link(), that does an additional check on the type of the
+        link.
+
+        :type: :class:`Sender` (**<-- CHECK!**)
+        """
         l = self.link
         if l and l.is_sender:
             return l
@@ -359,9 +606,13 @@
 
     @property
     def receiver(self):
-        """Returns the receiver link associated with the event, or null if
-           none is associated with it. This is essentially an alias for
-           link(), that does an additional check on the type of the link."""
+        """
+        The receiver link associated with the event, or ``None`` if
+        none is associated with it. This is essentially an alias for
+        link(), that does an additional check on the type of the link.
+
+        :type: :class:`Receiver` (**<-- CHECK!**)
+        """
         l = self.link
         if l and l.is_receiver:
             return l
@@ -370,7 +621,12 @@
 
     @property
     def delivery(self):
-        """Returns the delivery associated with the event, or null if none is associated with it."""
+        """
+        The delivery associated with the event, or ``None`` if none
+        is associated with it.
+
+        :type: :class:`Delivery`
+        """
         return self._delivery
 
 
@@ -384,12 +640,29 @@
 
 
 class Handler(object):
+    """
+    An abstract handler for events which supports child handlers.
+    """
     handlers = LazyHandlers()
 
     # TODO What to do with on_error?
     def add(self, handler, on_error=None):
-        """Add a child handler"""
+        """
+        Add a child handler
+
+        :param handler: A child handler
+        :type handler: :class:`Handler` or one of its derivatives.
+        :param on_error: Not used
+        """
         self.handlers.append(handler)
 
     def on_unhandled(self, method, *args):
+        """
+        The callback for handling events which are not handled by
+        any other handler.
+
+        :param method: The name of the intended handler method.
+        :type method: ``str``
+        :param args: Arguments for the intended handler method.
+        """
         pass
diff --git a/python/proton/_exceptions.py b/python/proton/_exceptions.py
index 47420c2..ccff4c7 100644
--- a/python/proton/_exceptions.py
+++ b/python/proton/_exceptions.py
@@ -69,24 +69,50 @@
 
 
 class TransportException(ProtonException):
+    """
+    An exception class raised when exceptions or errors related to the AMQP
+    transport arise.
+    """
     pass
 
 
 class SSLException(TransportException):
+    """
+    An exception class raised when exceptions or errors related to SSL usage
+    arise. These typically include problems with initializing or configuring
+    SSL.
+    """
     pass
 
 
 class SSLUnavailable(SSLException):
+    """
+    An exception class raised when exceptions or errors related to SSL
+    availability arise. These typically include problems finding the SSL
+    libraries.
+    """
     pass
 
 
 class ConnectionException(ProtonException):
+    """
+    An exception class raised when exceptions or errors related to a
+    connection arise.
+    """
     pass
 
 
 class SessionException(ProtonException):
+    """
+    An exception class raised when exceptions or errors related to a
+    session arise.
+    """
     pass
 
 
 class LinkException(ProtonException):
+    """
+    An exception class raised when exceptions or errors related to a
+    link arise.
+    """
     pass
diff --git a/python/proton/_handlers.py b/python/proton/_handlers.py
index 62b3dea..5ecb3e5 100644
--- a/python/proton/_handlers.py
+++ b/python/proton/_handlers.py
@@ -43,6 +43,11 @@
     """
     A utility for simpler and more intuitive handling of delivery
     events related to outgoing i.e. sent messages.
+
+    :param auto_settle: If ``True``, settle all messages (default). Otherwise
+        messages must be explicitly settled.
+    :type auto_settle: ``bool``
+    :param delegate: A client handler for the endpoint event
     """
 
     def __init__(self, auto_settle=True, delegate=None):
@@ -73,6 +78,10 @@
         """
         Called when the sender link has credit and messages can
         therefore be transferred.
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
         """
         if self.delegate is not None:
             _dispatch(self.delegate, 'on_sendable', event)
@@ -80,6 +89,10 @@
     def on_accepted(self, event):
         """
         Called when the remote peer accepts an outgoing message.
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
         """
         if self.delegate is not None:
             _dispatch(self.delegate, 'on_accepted', event)
@@ -87,6 +100,10 @@
     def on_rejected(self, event):
         """
         Called when the remote peer rejects an outgoing message.
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
         """
         if self.delegate is not None:
             _dispatch(self.delegate, 'on_rejected', event)
@@ -94,8 +111,12 @@
     def on_released(self, event):
         """
         Called when the remote peer releases an outgoing message. Note
-        that this may be in response to either the RELEASE or MODIFIED
+        that this may be in response to either the ``RELEASE`` or ``MODIFIED``
         state as defined by the AMQP specification.
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
         """
         if self.delegate is not None:
             _dispatch(self.delegate, 'on_released', event)
@@ -105,6 +126,10 @@
         Called when the remote peer has settled the outgoing
         message. This is the point at which it should never be
         retransmitted.
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
         """
         if self.delegate is not None:
             _dispatch(self.delegate, 'on_settled', event)
@@ -119,25 +144,32 @@
 
 class Reject(ProtonException):
     """
-    An exception that indicate a message should be rejected
+    An exception that indicates a message should be rejected.
     """
     pass
 
 
 class Release(ProtonException):
     """
-    An exception that indicate a message should be rejected
+    An exception that indicates a message should be released.
     """
     pass
 
 
 class Acking(object):
+    """
+    A class containing methods for handling received messages.
+    """
     def accept(self, delivery):
         """
         Accepts a received message.
 
-        Note that this method cannot currently be used in combination
-        with transactions.
+        .. note:: This method cannot currently be used in combination
+            with transactions. See :class:`proton.reactor.Transaction`
+            for transactional methods.
+
+        :param delivery: The message delivery tracking object
+        :type delivery: :class:`proton.Delivery`
         """
         self.settle(delivery, Delivery.ACCEPTED)
 
@@ -145,6 +177,13 @@
         """
         Rejects a received message that is considered invalid or
         unprocessable.
+
+        .. note:: This method cannot currently be used in combination
+            with transactions. See :class:`proton.reactor.Transaction`
+            for transactional methods.
+
+        :param delivery: The message delivery tracking object
+        :type delivery: :class:`proton.Delivery`
         """
         self.settle(delivery, Delivery.REJECTED)
 
@@ -154,6 +193,19 @@
         for any (other) interested receiver. The ``delivered``
         parameter indicates whether this should be considered a
         delivery attempt (and the delivery count updated) or not.
+
+        .. note:: This method cannot currently be used in combination
+            with transactions. See :class:`proton.reactor.Transaction`
+            for transactional methods.
+
+        :param delivery: The message delivery tracking object
+        :type delivery: :class:`proton.Delivery`
+        :param delivered: If ``True``, the message will be annotated
+            with a delivery attempt (setting delivery flag
+            :const:`proton.Delivery.MODIFIED`). Otherwise, the message
+            will be returned without the annotation and released (setting
+            delivery flag :const:`proton.Delivery.RELEASED`
+        :type delivered: ``bool``
         """
         if delivered:
             self.settle(delivery, Delivery.MODIFIED)
@@ -161,6 +213,16 @@
             self.settle(delivery, Delivery.RELEASED)
 
     def settle(self, delivery, state=None):
+        """
+        Settles the message delivery, and optionally updating the
+        delivery state.
+
+        :param delivery: The message delivery tracking object
+        :type delivery: :class:`proton.Delivery`
+        :param state: The delivery state, or ``None`` if not update
+            is to be performed.
+        :type  state: ``int`` or ``None``
+        """
         if state:
             delivery.update(state)
         delivery.settle()
@@ -170,6 +232,11 @@
     """
     A utility for simpler and more intuitive handling of delivery
     events related to incoming i.e. received messages.
+
+    :type auto_accept: ``bool``
+    :param auto_settle: If ``True``, settle all messages (default). Otherwise
+        messages must be explicitly settled.
+    :param delegate: A client handler for the endpoint event
     """
 
     def __init__(self, auto_accept=True, delegate=None):
@@ -210,30 +277,54 @@
         referring to this message in further actions (e.g. if
         explicitly accepting it, the ``delivery`` should be used, also
         obtainable via a property on the event.
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
         """
         if self.delegate is not None:
             _dispatch(self.delegate, 'on_message', event)
 
     def on_settled(self, event):
+        """
+        Callback for when a message delivery is settled by the remote peer.
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
+        """
         if self.delegate is not None:
             _dispatch(self.delegate, 'on_settled', event)
 
     def on_aborted(self, event):
+        """
+        Callback for when a message delivery is aborted by the remote peer.
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
+        """
         if self.delegate is not None:
             _dispatch(self.delegate, 'on_aborted', event)
 
 
 class EndpointStateHandler(Handler):
     """
-    A utility that exposes 'endpoint' events i.e. the open/close for
+    A utility that exposes 'endpoint' events - ie the open/close for
     links, sessions and connections in a more intuitive manner. A
-    XXX_opened method will be called when both local and remote peers
+    ``XXX_opened()`` method will be called when both local and remote peers
     have opened the link, session or connection. This can be used to
-    confirm a locally initiated action for example. A XXX_opening
+    confirm a locally initiated action for example. A ``XXX_opening()``
     method will be called when the remote peer has requested an open
     that was not initiated locally. By default this will simply open
-    locally, which then triggers the XXX_opened call. The same applies
+    locally, which then triggers the ``XXX_opened()`` call. The same applies
     to close.
+
+    :param peer_close_is_error: If ``True``, a peer endpoint closing will be
+        treated as an error with an error callback. Otherwise (default), the
+        normal callbacks for the closing will occur. 
+    :type peer_close_is_error:  ``bool`` 
+    :param delegate: A client handler for the endpoint event
     """
 
     def __init__(self, peer_close_is_error=False, delegate=None):
@@ -242,26 +333,85 @@
 
     @classmethod
     def is_local_open(cls, endpoint):
+        """
+        Test if local ``enpoint`` is open (ie has state
+        :const:`proton.Endpoint.LOCAL_ACTIVE`).
+
+        :param endpoint: The local endpoint to be tested.
+        :type endpoint: Any child of :class:`proton.Endpoint`
+        :return: ``True`` if local endpoint is in state
+            :const:`proton.Endpoint.LOCAL_ACTIVE`, ``False`` otherwise.
+        :rtype: ``bool``
+        """
         return endpoint.state & Endpoint.LOCAL_ACTIVE
 
     @classmethod
     def is_local_uninitialised(cls, endpoint):
+        """
+        Test if local ``enpoint`` is uninitialised (ie has state
+        :const:`proton.Endpoint.LOCAL_UNINIT`).
+
+        :param endpoint: The local endpoint to be tested.
+        :type endpoint: Any child of :class:`proton.Endpoint`
+        :return: ``True`` if local endpoint is in state
+            :const:`proton.Endpoint.LOCAL_UNINIT`, ``False`` otherwise.
+        :rtype: ``bool``
+        """
         return endpoint.state & Endpoint.LOCAL_UNINIT
 
     @classmethod
     def is_local_closed(cls, endpoint):
+        """
+        Test if local ``enpoint`` is closed (ie has state
+        :const:`proton.Endpoint.LOCAL_CLOSED`).
+
+        :param endpoint: The local endpoint to be tested.
+        :type endpoint: Any child of :class:`proton.Endpoint`
+        :return: ``True`` if local endpoint is in state
+            :const:`proton.Endpoint.LOCAL_CLOSED`, ``False`` otherwise.
+        :rtype: ``bool``
+        """
         return endpoint.state & Endpoint.LOCAL_CLOSED
 
     @classmethod
     def is_remote_open(cls, endpoint):
+        """
+        Test if remote ``enpoint`` is open (ie has state
+        :const:`proton.Endpoint.LOCAL_ACTIVE`).
+
+        :param endpoint: The remote endpoint to be tested.
+        :type endpoint: Any child of :class:`proton.Endpoint`
+        :return: ``True`` if remote endpoint is in state
+            :const:`proton.Endpoint.LOCAL_ACTIVE`, ``False`` otherwise.
+        :rtype: ``bool``
+        """
         return endpoint.state & Endpoint.REMOTE_ACTIVE
 
     @classmethod
     def is_remote_closed(cls, endpoint):
+        """
+        Test if remote ``enpoint`` is closed (ie has state
+        :const:`proton.Endpoint.REMOTE_CLOSED`).
+
+        :param endpoint: The remote endpoint to be tested.
+        :type endpoint: Any child of :class:`proton.Endpoint`
+        :return: ``True`` if remote endpoint is in state
+            :const:`proton.Endpoint.REMOTE_CLOSED`, ``False`` otherwise.
+        :rtype: ``bool``
+        """
         return endpoint.state & Endpoint.REMOTE_CLOSED
 
     @classmethod
     def print_error(cls, endpoint, endpoint_type):
+        """
+        Logs an error message related to an error condition at an endpoint.
+
+        :param endpoint: The endpoint to be tested
+        :type endpoint: :class:`proton.Endpoint`
+        :param endpoint_type: The endpoint type as a string to be printed
+            in the log message.
+        :type endpoint_type: ``str``
+        """
         if endpoint.remote_condition:
             log.error(endpoint.remote_condition.description or endpoint.remote_condition.name)
         elif cls.is_local_open(endpoint) and cls.is_remote_closed(endpoint):
@@ -332,36 +482,98 @@
             event.link.open()
 
     def on_connection_opened(self, event):
+        """
+        Callback for when both the local and remote endpoints of a
+        connection have opened.
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
+        """
         if self.delegate is not None:
             _dispatch(self.delegate, 'on_connection_opened', event)
 
     def on_session_opened(self, event):
+        """
+        Callback for when both the local and remote endpoints of a
+        session have opened.
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
+        """
         if self.delegate is not None:
             _dispatch(self.delegate, 'on_session_opened', event)
 
     def on_link_opened(self, event):
+        """
+        Callback for when both the local and remote endpoints of a
+        link have opened.
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
+        """
         if self.delegate is not None:
             _dispatch(self.delegate, 'on_link_opened', event)
 
     def on_connection_opening(self, event):
+        """
+        Callback for when a remote peer initiates the opening of
+        a connection.
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
+        """
         if self.delegate is not None:
             _dispatch(self.delegate, 'on_connection_opening', event)
 
     def on_session_opening(self, event):
+        """
+        Callback for when a remote peer initiates the opening of
+        a session.
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
+        """
         if self.delegate is not None:
             _dispatch(self.delegate, 'on_session_opening', event)
 
     def on_link_opening(self, event):
+        """
+        Callback for when a remote peer initiates the opening of
+        a link.
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
+        """
         if self.delegate is not None:
             _dispatch(self.delegate, 'on_link_opening', event)
 
     def on_connection_error(self, event):
+        """
+        Callback for when an initiated connection open fails.
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
+        """
         if self.delegate is not None:
             _dispatch(self.delegate, 'on_connection_error', event)
         else:
             self.print_error(event.connection, "connection")
 
     def on_session_error(self, event):
+        """
+        Callback for when an initiated session open fails.
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
+        """
         if self.delegate is not None:
             _dispatch(self.delegate, 'on_session_error', event)
         else:
@@ -369,6 +581,13 @@
             event.connection.close()
 
     def on_link_error(self, event):
+        """
+        Callback for when an initiated link open fails.
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
+        """
         if self.delegate is not None:
             _dispatch(self.delegate, 'on_link_error', event)
         else:
@@ -376,39 +595,103 @@
             event.connection.close()
 
     def on_connection_closed(self, event):
+        """
+        Callback for when both the local and remote endpoints of a
+        connection have closed.
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
+        """
         if self.delegate is not None:
             _dispatch(self.delegate, 'on_connection_closed', event)
 
     def on_session_closed(self, event):
+        """
+        Callback for when both the local and remote endpoints of a
+        session have closed.
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
+        """
         if self.delegate is not None:
             _dispatch(self.delegate, 'on_session_closed', event)
 
     def on_link_closed(self, event):
+        """
+        Callback for when both the local and remote endpoints of a
+        link have closed.
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
+        """
         if self.delegate is not None:
             _dispatch(self.delegate, 'on_link_closed', event)
 
     def on_connection_closing(self, event):
+        """
+        Callback for when a remote peer initiates the closing of
+        a connection.
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
+        """
         if self.delegate is not None:
             _dispatch(self.delegate, 'on_connection_closing', event)
         elif self.peer_close_is_error:
             self.on_connection_error(event)
 
     def on_session_closing(self, event):
+        """
+        Callback for when a remote peer initiates the closing of
+        a session.
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
+        """
         if self.delegate is not None:
             _dispatch(self.delegate, 'on_session_closing', event)
         elif self.peer_close_is_error:
             self.on_session_error(event)
 
     def on_link_closing(self, event):
+        """
+        Callback for when a remote peer initiates the closing of
+        a link.
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
+        """
         if self.delegate is not None:
             _dispatch(self.delegate, 'on_link_closing', event)
         elif self.peer_close_is_error:
             self.on_link_error(event)
 
     def on_transport_tail_closed(self, event):
+        """
+        Callback for when the transport tail has closed (ie no further input will
+        be accepted by the transport).
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
+        """
         self.on_transport_closed(event)
 
     def on_transport_closed(self, event):
+        """
+        Callback for when the transport has closed - ie both the head (input) and
+        tail (output) of the transport pipeline are closed.
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
+        """
         if self.delegate is not None and event.connection and self.is_local_open(event.connection):
             _dispatch(self.delegate, 'on_disconnected', event)
 
@@ -418,6 +701,19 @@
     A general purpose handler that makes the proton-c events somewhat
     simpler to deal with and/or avoids repetitive tasks for common use
     cases.
+
+    :param prefetch: Initial flow credit for receiving messages, defaults to 10.
+    :type prefetch: ``int``
+    :param auto_accept: If ``True``, accept all messages (default). Otherwise messages
+        must be individually accepted or rejected.
+    :type auto_accept: ``bool``
+    :param auto_settle: If ``True``, settle all messages (default). Otherwise
+        messages must be explicitly settled.
+    :type auto_settle: ``bool``
+    :param peer_close_is_error: If ``True``, a peer endpoint closing will be
+        treated as an error with an error callback. Otherwise (default), the
+        normal callbacks for the closing will occur. 
+    :type peer_close_is_error:  ``bool``  
     """
 
     def __init__(self, prefetch=10, auto_accept=True, auto_settle=True, peer_close_is_error=False):
@@ -434,6 +730,10 @@
         Called when some error is encountered with the transport over
         which the AMQP connection is to be established. This includes
         authentication errors as well as socket errors.
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
         """
         if event.transport.condition:
             if event.transport.condition.info:
@@ -450,12 +750,20 @@
     def on_connection_error(self, event):
         """
         Called when the peer closes the connection with an error condition.
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
         """
         EndpointStateHandler.print_error(event.connection, "connection")
 
     def on_session_error(self, event):
         """
         Called when the peer closes the session with an error condition.
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
         """
         EndpointStateHandler.print_error(event.session, "session")
         event.connection.close()
@@ -463,6 +771,10 @@
     def on_link_error(self, event):
         """
         Called when the peer closes the link with an error condition.
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
         """
         EndpointStateHandler.print_error(event.link, "link")
         event.connection.close()
@@ -470,6 +782,10 @@
     def on_reactor_init(self, event):
         """
         Called when the event loop - the reactor - starts.
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
         """
         if hasattr(event.reactor, 'subclass'):
             setattr(event, event.reactor.subclass.__name__.lower(), event.reactor)
@@ -478,48 +794,80 @@
     def on_start(self, event):
         """
         Called when the event loop starts. (Just an alias for on_reactor_init)
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
         """
         pass
 
     def on_connection_closed(self, event):
         """
         Called when the connection is closed.
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
         """
         pass
 
     def on_session_closed(self, event):
         """
         Called when the session is closed.
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
         """
         pass
 
     def on_link_closed(self, event):
         """
         Called when the link is closed.
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
         """
         pass
 
     def on_connection_closing(self, event):
         """
         Called when the peer initiates the closing of the connection.
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
         """
         pass
 
     def on_session_closing(self, event):
         """
         Called when the peer initiates the closing of the session.
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
         """
         pass
 
     def on_link_closing(self, event):
         """
         Called when the peer initiates the closing of the link.
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
         """
         pass
 
     def on_disconnected(self, event):
         """
         Called when the socket is disconnected.
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
         """
         pass
 
@@ -527,18 +875,30 @@
         """
         Called when the sender link has credit and messages can
         therefore be transferred.
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
         """
         pass
 
     def on_accepted(self, event):
         """
         Called when the remote peer accepts an outgoing message.
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
         """
         pass
 
     def on_rejected(self, event):
         """
         Called when the remote peer rejects an outgoing message.
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
         """
         pass
 
@@ -547,6 +907,10 @@
         Called when the remote peer releases an outgoing message. Note
         that this may be in response to either the RELEASE or MODIFIED
         state as defined by the AMQP specification.
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
         """
         pass
 
@@ -555,6 +919,10 @@
         Called when the remote peer has settled the outgoing
         message. This is the point at which it should never be
         retransmitted.
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
         """
         pass
 
@@ -565,42 +933,113 @@
         referring to this message in further actions (e.g. if
         explicitly accepting it, the ``delivery`` should be used, also
         obtainable via a property on the event.
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event. In particular, the message itself may
+            be obtained by accessing ``event.message``.
+        :type event: :class:`proton.Event`
         """
         pass
 
 
 class TransactionHandler(object):
     """
-    The interface for transaction handlers, i.e. objects that want to
+    The interface for transaction handlers - ie objects that want to
     be notified of state changes related to a transaction.
     """
 
     def on_transaction_declared(self, event):
+        """
+        Called when a local transaction is declared.
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event. In particular, the :class:`proton.reactor.Transaction`
+            object may be obtained by accessing ``event.transaction``.
+        :type event: :class:`proton.Event`
+        """
         pass
 
     def on_transaction_committed(self, event):
+        """
+        Called when a local transaction is discharged successfully
+        (committed).
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
+        """
         pass
 
     def on_transaction_aborted(self, event):
+        """
+        Called when a local transaction is discharged unsuccessfully
+        (aborted).
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
+        """
         pass
 
     def on_transaction_declare_failed(self, event):
+        """
+        Called when a local transaction declare fails.
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
+        """
         pass
 
     def on_transaction_commit_failed(self, event):
+        """
+        Called when the commit of a local transaction fails. 
+
+        :param event: The underlying event object. Use this to obtain further
+            information on the event.
+        :type event: :class:`proton.Event`
+        """
         pass
 
 
 class TransactionalClientHandler(MessagingHandler, TransactionHandler):
     """
     An extension to the MessagingHandler for applications using
-    transactions.
+    transactions. This handler provides all of the callbacks found
+    in :class:`MessagingHandler` and :class:`TransactionHandler`,
+    and provides a convenience method :meth:`accept` for performing
+    a transactional acceptance of received messages.
+
+    :param prefetch: Initial flow credit for receiving messages, defaults to 10.
+    :type prefetch: ``int``
+    :param auto_accept: If ``True``, accept all messages (default). Otherwise messages
+        must be individually accepted or rejected.
+    :type auto_accept: ``bool``
+    :param auto_settle: If ``True``, settle all messages (default). Otherwise
+        messages must be explicitly settled.
+    :type auto_settle: ``bool``
+    :param peer_close_is_error: If ``True``, a peer endpoint closing will be
+        treated as an error with an error callback. Otherwise (default), the
+        normal callbacks for the closing will occur. 
+    :type peer_close_is_error:  ``bool`` 
     """
 
     def __init__(self, prefetch=10, auto_accept=False, auto_settle=True, peer_close_is_error=False):
         super(TransactionalClientHandler, self).__init__(prefetch, auto_accept, auto_settle, peer_close_is_error)
 
     def accept(self, delivery, transaction=None):
+        """
+        A convenience method for accepting a received message as part of a
+        transaction. If no transaction object is supplied, a regular
+        non-transactional acceptance will be performed.
+
+        :param delivery: Delivery tracking object for received message.
+        :type delivery: :class:`proton.Delivery`
+        :param transaction: Transaction tracking object which is required if
+            the message is being accepted under the transaction. If ``None`` (default),
+            then a normal non-transactional accept occurs.
+        :type transaction: :class:`proton.reactor.Transaction`
+        """
         if transaction:
             transaction.accept(delivery)
         else:
diff --git a/python/proton/_message.py b/python/proton/_message.py
index 753ac4d..f89664c 100644
--- a/python/proton/_message.py
+++ b/python/proton/_message.py
@@ -47,24 +47,24 @@
 
 
 class Message(object):
-    """The L{Message} class is a mutable holder of message content.
+    """The :py:class:`Message` class is a mutable holder of message content.
 
-    @ivar instructions: delivery instructions for the message
-    @type instructions: dict
-    @ivar annotations: infrastructure defined message annotations
-    @type annotations: dict
-    @ivar properties: application defined message properties
-    @type properties: dict
-    @ivar body: message body
-    @type body: bytes | unicode | dict | list | int | long | float | UUID
+    :ivar instructions: delivery instructions for the message
+    :vartype instructions: ``dict``
+    :ivar ~.annotations: infrastructure defined message annotations
+    :vartype ~.annotations: ``dict``
+    :ivar ~.properties: application defined message properties
+    :vartype ~.properties: ``dict``
+    :ivar body: message body
+    :vartype body: bytes | unicode | dict | list | int | long | float | UUID
+
+    :param kwargs: Message property name/value pairs to initialize the Message
     """
 
     DEFAULT_PRIORITY = PN_DEFAULT_PRIORITY
+    """ Default AMQP message priority"""
 
     def __init__(self, body=None, **kwargs):
-        """
-        @param kwargs: Message property name/value pairs to initialise the Message
-        """
         self._msg = pn_message()
         self._id = Data(pn_message_id(self._msg))
         self._correlation_id = Data(pn_message_correlation_id(self._msg))
@@ -145,7 +145,7 @@
 
     def clear(self):
         """
-        Clears the contents of the L{Message}. All fields will be reset to
+        Clears the contents of the :class:`Message`. All fields will be reset to
         their default values.
         """
         pn_message_clear(self._msg)
@@ -161,13 +161,16 @@
         self._check(pn_message_set_inferred(self._msg, bool(value)))
 
     inferred = property(_is_inferred, _set_inferred, doc="""
-The inferred flag for a message indicates how the message content
-is encoded into AMQP sections. If inferred is true then binary and
-list values in the body of the message will be encoded as AMQP DATA
-and AMQP SEQUENCE sections, respectively. If inferred is false,
-then all values in the body of the message will be encoded as AMQP
-VALUE sections regardless of their type.
-""")
+        The inferred flag for a message indicates how the message content
+        is encoded into AMQP sections. If inferred is true then binary and
+        list values in the body of the message will be encoded as AMQP DATA
+        and AMQP SEQUENCE sections, respectively. If inferred is false,
+        then all values in the body of the message will be encoded as AMQP
+        VALUE sections regardless of their type.
+
+        :type: ``bool``
+        :raise: :exc:`MessageException` if there is any Proton error when using the setter.
+        """)
 
     def _is_durable(self):
         return pn_message_is_durable(self._msg)
@@ -175,11 +178,13 @@
     def _set_durable(self, value):
         self._check(pn_message_set_durable(self._msg, bool(value)))
 
-    durable = property(_is_durable, _set_durable,
-                       doc="""
-The durable property indicates that the message should be held durably
-by any intermediaries taking responsibility for the message.
-""")
+    durable = property(_is_durable, _set_durable, doc="""
+        The durable property indicates that the message should be held durably
+        by any intermediaries taking responsibility for the message.
+
+        :type: ``bool``
+        :raise: :exc:`MessageException` if there is any Proton error when using the setter.
+        """)
 
     def _get_priority(self):
         return pn_message_get_priority(self._msg)
@@ -187,10 +192,17 @@
     def _set_priority(self, value):
         self._check(pn_message_set_priority(self._msg, value))
 
-    priority = property(_get_priority, _set_priority,
-                        doc="""
-The priority of the message.
-""")
+    priority = property(_get_priority, _set_priority, doc="""
+        The relative priority of the message, with higher numbers indicating
+        higher priority. The number of available priorities depends
+        on the implementation, but AMQP defines the default priority as
+        the value ``4``. See the
+        `OASIS AMQP 1.0 standard <http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-messaging-v1.0-os.html#type-header>`_
+        for more details on message priority.
+
+        :type: ``int``
+        :raise: :exc:`MessageException` if there is any Proton error when using the setter.
+        """)
 
     def _get_ttl(self):
         return millis2secs(pn_message_get_ttl(self._msg))
@@ -198,11 +210,13 @@
     def _set_ttl(self, value):
         self._check(pn_message_set_ttl(self._msg, secs2millis(value)))
 
-    ttl = property(_get_ttl, _set_ttl,
-                   doc="""
-The time to live of the message measured in seconds. Expired messages
-may be dropped.
-""")
+    ttl = property(_get_ttl, _set_ttl, doc="""
+        The time to live of the message measured in seconds. Expired messages
+        may be dropped.
+
+        :type: ``int``
+        :raise: :exc:`MessageException` if there is any Proton error when using the setter.
+        """)
 
     def _is_first_acquirer(self):
         return pn_message_is_first_acquirer(self._msg)
@@ -210,10 +224,13 @@
     def _set_first_acquirer(self, value):
         self._check(pn_message_set_first_acquirer(self._msg, bool(value)))
 
-    first_acquirer = property(_is_first_acquirer, _set_first_acquirer,
-                              doc="""
-True iff the recipient is the first to acquire the message.
-""")
+    first_acquirer = property(_is_first_acquirer, _set_first_acquirer, doc="""
+        ``True`` iff the recipient is the first to acquire the message,
+        ``False`` otherwise.
+
+        :type: ``bool``
+        :raise: :exc:`MessageException` if there is any Proton error when using the setter.
+        """)
 
     def _get_delivery_count(self):
         return pn_message_get_delivery_count(self._msg)
@@ -221,10 +238,12 @@
     def _set_delivery_count(self, value):
         self._check(pn_message_set_delivery_count(self._msg, value))
 
-    delivery_count = property(_get_delivery_count, _set_delivery_count,
-                              doc="""
-The number of delivery attempts made for this message.
-""")
+    delivery_count = property(_get_delivery_count, _set_delivery_count, doc="""
+        The number of delivery attempts made for this message.
+
+        :type: ``int``
+        :raise: :exc:`MessageException` if there is any Proton error when using the setter.
+        """)
 
     def _get_id(self):
         return self._id.get_object()
@@ -235,10 +254,18 @@
         self._id.rewind()
         self._id.put_object(value)
 
-    id = property(_get_id, _set_id,
-                  doc="""
-The id of the message.
-""")
+    id = property(_get_id, _set_id, doc="""
+        The globally unique id of the message, and can be used
+        to determine if a received message is a duplicate. The allowed
+        types to set the id are:
+
+        :type: The valid AMQP types for an id are one of:
+
+               * ``int`` (unsigned)
+               * ``uuid.UUID``
+               * ``bytes``
+               * ``str``
+        """)
 
     def _get_user_id(self):
         return pn_message_get_user_id(self._msg)
@@ -246,10 +273,12 @@
     def _set_user_id(self, value):
         self._check(pn_message_set_user_id(self._msg, value))
 
-    user_id = property(_get_user_id, _set_user_id,
-                       doc="""
-The user id of the message creator.
-""")
+    user_id = property(_get_user_id, _set_user_id, doc="""
+        The user id of the message creator.
+
+        :type: ``bytes``
+        :raise: :exc:`MessageException` if there is any Proton error when using the setter.
+        """)
 
     def _get_address(self):
         return utf82unicode(pn_message_get_address(self._msg))
@@ -257,10 +286,12 @@
     def _set_address(self, value):
         self._check(pn_message_set_address(self._msg, unicode2utf8(value)))
 
-    address = property(_get_address, _set_address,
-                       doc="""
-The address of the message.
-""")
+    address = property(_get_address, _set_address, doc="""
+        The address of the message.
+
+        :type: ``str``
+        :raise: :exc:`MessageException` if there is any Proton error when using the setter.
+        """)
 
     def _get_subject(self):
         return utf82unicode(pn_message_get_subject(self._msg))
@@ -268,10 +299,12 @@
     def _set_subject(self, value):
         self._check(pn_message_set_subject(self._msg, unicode2utf8(value)))
 
-    subject = property(_get_subject, _set_subject,
-                       doc="""
-The subject of the message.
-""")
+    subject = property(_get_subject, _set_subject, doc="""
+        The subject of the message.
+
+        :type: ``str``
+        :raise: :exc:`MessageException` if there is any Proton error when using the setter.
+        """)
 
     def _get_reply_to(self):
         return utf82unicode(pn_message_get_reply_to(self._msg))
@@ -279,10 +312,12 @@
     def _set_reply_to(self, value):
         self._check(pn_message_set_reply_to(self._msg, unicode2utf8(value)))
 
-    reply_to = property(_get_reply_to, _set_reply_to,
-                        doc="""
-The reply-to address for the message.
-""")
+    reply_to = property(_get_reply_to, _set_reply_to, doc="""
+        The reply-to address for the message.
+
+        :type: ``str``
+        :raise: :exc:`MessageException` if there is any Proton error when using the setter.
+        """)
 
     def _get_correlation_id(self):
         return self._correlation_id.get_object()
@@ -293,10 +328,16 @@
         self._correlation_id.rewind()
         self._correlation_id.put_object(value)
 
-    correlation_id = property(_get_correlation_id, _set_correlation_id,
-                              doc="""
-The correlation-id for the message.
-""")
+    correlation_id = property(_get_correlation_id, _set_correlation_id, doc="""
+        The correlation-id for the message.
+
+        :type: The valid AMQP types for a correlation-id are one of:
+
+               * ``int`` (unsigned)
+               * ``uuid.UUID``
+               * ``bytes``
+               * ``str``
+        """)
 
     def _get_content_type(self):
         return symbol(utf82unicode(pn_message_get_content_type(self._msg)))
@@ -304,10 +345,12 @@
     def _set_content_type(self, value):
         self._check(pn_message_set_content_type(self._msg, unicode2utf8(value)))
 
-    content_type = property(_get_content_type, _set_content_type,
-                            doc="""
-The content-type of the message.
-""")
+    content_type = property(_get_content_type, _set_content_type, doc="""
+        The RFC-2046 [RFC2046] MIME type for the message body.
+
+        :type: :class:`symbol`
+        :raise: :exc:`MessageException` if there is any Proton error when using the setter.
+        """)
 
     def _get_content_encoding(self):
         return symbol(utf82unicode(pn_message_get_content_encoding(self._msg)))
@@ -315,10 +358,12 @@
     def _set_content_encoding(self, value):
         self._check(pn_message_set_content_encoding(self._msg, unicode2utf8(value)))
 
-    content_encoding = property(_get_content_encoding, _set_content_encoding,
-                                doc="""
-The content-encoding of the message.
-""")
+    content_encoding = property(_get_content_encoding, _set_content_encoding, doc="""
+        The content-encoding of the message.
+
+        :type: :class:`symbol`
+        :raise: :exc:`MessageException` if there is any Proton error when using the setter.
+        """)
 
     def _get_expiry_time(self):
         return millis2secs(pn_message_get_expiry_time(self._msg))
@@ -326,10 +371,12 @@
     def _set_expiry_time(self, value):
         self._check(pn_message_set_expiry_time(self._msg, secs2millis(value)))
 
-    expiry_time = property(_get_expiry_time, _set_expiry_time,
-                           doc="""
-The expiry time of the message.
-""")
+    expiry_time = property(_get_expiry_time, _set_expiry_time, doc="""
+        The absolute expiry time of the message in seconds using the Unix time_t [IEEE1003] encoding.
+
+        :type: ``int``
+        :raise: :exc:`MessageException` if there is any Proton error when using the setter.
+        """)
 
     def _get_creation_time(self):
         return millis2secs(pn_message_get_creation_time(self._msg))
@@ -337,10 +384,12 @@
     def _set_creation_time(self, value):
         self._check(pn_message_set_creation_time(self._msg, secs2millis(value)))
 
-    creation_time = property(_get_creation_time, _set_creation_time,
-                             doc="""
-The creation time of the message.
-""")
+    creation_time = property(_get_creation_time, _set_creation_time, doc="""
+        The creation time of the message in seconds using the Unix time_t [IEEE1003] encoding.
+
+        :type: ``int``
+        :raise: :exc:`MessageException` if there is any Proton error when using the setter.
+        """)
 
     def _get_group_id(self):
         return utf82unicode(pn_message_get_group_id(self._msg))
@@ -348,10 +397,12 @@
     def _set_group_id(self, value):
         self._check(pn_message_set_group_id(self._msg, unicode2utf8(value)))
 
-    group_id = property(_get_group_id, _set_group_id,
-                        doc="""
-The group id of the message.
-""")
+    group_id = property(_get_group_id, _set_group_id, doc="""
+        The group id of the message.
+
+        :type: ``str``
+        :raise: :exc:`MessageException` if there is any Proton error when using the setter.
+        """)
 
     def _get_group_sequence(self):
         return pn_message_get_group_sequence(self._msg)
@@ -359,10 +410,12 @@
     def _set_group_sequence(self, value):
         self._check(pn_message_set_group_sequence(self._msg, value))
 
-    group_sequence = property(_get_group_sequence, _set_group_sequence,
-                              doc="""
-The sequence of the message within its group.
-""")
+    group_sequence = property(_get_group_sequence, _set_group_sequence, doc="""
+        The sequence of the message within its group.
+
+        :type: ``int``
+        :raise: :exc:`MessageException` if there is any Proton error when using the setter.
+        """)
 
     def _get_reply_to_group_id(self):
         return utf82unicode(pn_message_get_reply_to_group_id(self._msg))
@@ -370,10 +423,12 @@
     def _set_reply_to_group_id(self, value):
         self._check(pn_message_set_reply_to_group_id(self._msg, unicode2utf8(value)))
 
-    reply_to_group_id = property(_get_reply_to_group_id, _set_reply_to_group_id,
-                                 doc="""
-The group-id for any replies.
-""")
+    reply_to_group_id = property(_get_reply_to_group_id, _set_reply_to_group_id, doc="""
+        The group-id for any replies.
+
+        :type: ``str``
+        :raise: :exc:`MessageException` if there is any Proton error when using the setter.        
+        """)
 
     def encode(self):
         self._pre_encode()
@@ -392,6 +447,18 @@
         self._post_decode()
 
     def send(self, sender, tag=None):
+        """
+        Encodes and sends the message content using the specified sender,
+        and, if present, using the specified tag. Upon success, will
+        return the :class:`Delivery` object for the sent message.
+
+        :param sender: The sender to send the message
+        :type sender: :class:`Sender`
+        :param tag: The delivery tag for the sent message
+        :type tag: ``bytes``
+        :return: The delivery associated with the sent message
+        :rtype: :class:`Delivery`
+        """
         dlv = sender.delivery(tag or sender.delivery_tag())
         encoded = self.encode()
         sender.stream(encoded)
@@ -402,15 +469,16 @@
 
     def recv(self, link):
         """
-        Receives and decodes the message content for the current delivery
+        Receives and decodes the message content for the current :class:`Delivery`
         from the link. Upon success it will return the current delivery
         for the link. If there is no current delivery, or if the current
         delivery is incomplete, or if the link is not a receiver, it will
-        return None.
+        return ``None``.
 
-        @type link: Link
-        @param link: the link to receive a message from
-        @return the delivery associated with the decoded message (or None)
+        :param link: The link to receive a message from
+        :type link: :class:`Link`
+        :return: the delivery associated with the decoded message (or None)
+        :rtype: :class:`Delivery`
 
         """
         if link.is_sender: return None
diff --git a/python/proton/_reactor.py b/python/proton/_reactor.py
index 628cdd5..6f44841 100644
--- a/python/proton/_reactor.py
+++ b/python/proton/_reactor.py
@@ -175,6 +175,9 @@
     handler = property(_get_handler, _set_handler)
 
     def run(self):
+        """
+        Start the processing of events and messages for this container.
+        """
         # TODO: Why do we timeout like this?
         self.timeout = 3.14159265359
         self.start()
@@ -265,6 +268,13 @@
         self._collector.release()
 
     def schedule(self, delay, handler):
+        """
+        Schedule a task to run on this container after a given delay,
+        and using the supplied handler.
+
+        :param delay:
+        :param handler:
+        """
         himpl = self._make_handler(handler)
         task = Task(self, self._now+delay, himpl)
         heapq.heappush(self._timerheap, task)
@@ -336,7 +346,7 @@
 
     def get_connection_address(self, connection):
         """This may be used to retrieve the remote peer address.
-        @return: string containing the address in URL format or None if no
+        :return: string containing the address in URL format or None if no
         address is available.  Use the proton.Url class to create a Url object
         from the returned value.
         """
@@ -344,6 +354,14 @@
         return utf82unicode(_url)
 
     def selectable(self, handler=None, delegate=None):
+        """
+        NO IDEA!
+
+        :param handler: no idea
+        :type handler: ?
+        :param delegate: no idea
+        :type delegate: ?
+        """
         if delegate is None:
             delegate = handler
         result = Selectable(delegate, self)
@@ -361,11 +379,11 @@
 
 class EventInjector(object):
     """
-    Can be added to a reactor to allow events to be triggered by an
+    Can be added to a :class:`Container` to allow events to be triggered by an
     external thread but handled on the event thread associated with
-    the reactor. An instance of this class can be passed to the
-    Reactor.selectable() method of the reactor in order to activate
-    it. The close() method should be called when it is no longer
+    the container. An instance of this class can be passed to the
+    :meth:`Container.selectable` method in order to activate
+    it. :meth:`close` should be called when it is no longer
     needed, to allow the event loop to end if needed.
     """
 
@@ -378,7 +396,10 @@
     def trigger(self, event):
         """
         Request that the given event be dispatched on the event thread
-        of the reactor to which this EventInjector was added.
+        of the container to which this EventInjector was added.
+
+        :param event: Event to be injected
+        :type event: :class:`proton.Event`, :class:`ApplicationEvent`
         """
         self.queue.put(event)
         os.write(self.pipe[1], b"!")
@@ -386,7 +407,7 @@
     def close(self):
         """
         Request that this EventInjector be closed. Existing events
-        will be dispatched on the reactors event dispatch thread,
+        will be dispatched on the container's event dispatch thread,
         then this will be removed from the set of interest.
         """
         self._closed = True
@@ -415,7 +436,21 @@
 class ApplicationEvent(EventBase):
     """
     Application defined event, which can optionally be associated with
-    an engine object and or an arbitrary subject
+    an engine object and or an arbitrary subject. This produces
+    extended event types - see :class:`proton.EventType` for details.
+
+    :param typename: Event type name
+    :type typename: ``str``
+    :param connection: Associates this event with a connection.
+    :type connection: :class:`proton.Connection`
+    :param session: Associates this event with a session.
+    :type session: :class:`proton.Session`
+    :param link: Associate this event with a link.
+    :type link: :class:`proton.Link` or one of its subclasses
+    :param delivery: Associate this event with a delivery.
+    :type delivery: :class:`proton.Delivery`
+    :param subject: Associate this event with an arbitrary object
+    :type subject: any
     """
 
     def __init__(self, typename, connection=None, session=None, link=None, delivery=None, subject=None):
@@ -435,6 +470,9 @@
 
     @property
     def context(self):
+        """
+        A reference to this event.
+        """
         return self
 
     def __repr__(self):
@@ -444,7 +482,19 @@
 
 class Transaction(object):
     """
-    Class to track state of an AMQP 1.0 transaction.
+    Tracks the state of an AMQP 1.0 local transaction. In typical usage, this
+    object is not created directly, but is obtained through the event returned
+    by :meth:`proton.handlers.TransactionHandler.on_transaction_declared` after
+    a call to :meth:`proton.reactor.Container.declare_transaction`.
+
+    To send messages under this transaction, use :meth:`send`.
+    
+    To receive messages under this transaction, call :meth:`accept` once the
+    message is received (typically from the
+    :meth:`proton.handlers.MessagingHandler.on_message` callback).
+    
+    To discharge the transaction, call either :meth:`commit`
+    (for a successful transaction), or :meth:`abort` (for a failed transaction).
     """
 
     def __init__(self, txn_ctrl, handler, settle_before_discharge=False):
@@ -459,9 +509,17 @@
         self.declare()
 
     def commit(self):
+        """
+        Commit this transaction. Closes the transaction as a success.
+        """
         self.discharge(False)
 
     def abort(self):
+        """
+        Abort or roll back this transaction. Closes the transaction as a failure,
+        and reverses, or rolls back all actions (sent and received messages)
+        performed under this transaction.
+        """
         self.discharge(True)
 
     def declare(self):
@@ -477,12 +535,30 @@
         return delivery
 
     def send(self, sender, msg, tag=None):
+        """
+        Send a message under this transaction.
+
+        :param sender: Link over which to send the message.
+        :type sender: :class:`proton.Sender`
+        :param msg: Message to be sent under this transaction.
+        :type msg: :class:`proton.Message`
+        :param tag: The delivery tag
+        :type tag: ``bytes``
+        :return: Delivery object for this message.
+        :rtype: :class:`proton.Delivery`
+        """
         dlv = sender.send(msg, tag=tag)
         dlv.local.data = [self.id]
         dlv.update(0x34)
         return dlv
 
     def accept(self, delivery):
+        """
+        Accept a received message under this transaction.
+
+        :param delivery: Delivery object for the received message.
+        :type delivery: :class:`proton.Delivery`
+        """
         self.update(delivery, PN_ACCEPTED)
         if self.settle_before_discharge:
             delivery.settle()
@@ -548,29 +624,80 @@
 
 
 class AtMostOnce(LinkOption):
+    """
+    Set at-most-once delivery semantics for message delivery. This is achieved by
+    setting the sender link settle mode to :const:`proton.Link.SND_SETTLED`
+    (ie pre-settled).
+    """
     def apply(self, link):
+        """
+        Set the at-most-once delivery semantics on the link.
+
+        :param link: The link on which this option is to be applied.
+        :type link: :class:`proton.Link`
+        """
         link.snd_settle_mode = Link.SND_SETTLED
 
 
 class AtLeastOnce(LinkOption):
+    """
+    Set at-least-once delivery semantics for message delivery. This is achieved
+    by setting the sender link settle mode to :const:`proton.Link.SND_UNSETTLED`
+    and the receiver link settle mode to :const:`proton.Link.RCV_FIRST`. This
+    forces the receiver to settle all messages once they are successfully received.
+    """
     def apply(self, link):
+        """
+        Set the at-least-once delivery semantics on the link.
+
+        :param link: The link on which this option is to be applied.
+        :type link: :class:`proton.Link`
+        """
         link.snd_settle_mode = Link.SND_UNSETTLED
         link.rcv_settle_mode = Link.RCV_FIRST
 
 
 class SenderOption(LinkOption):
-    def apply(self, sender): pass
+    """
+    Abstract class for sender options.
+    """
+    def apply(self, sender):
+        """
+        Set the option on the sender.
+
+        :param sender: The sender on which this option is to be applied.
+        :type sender: :class:`proton.Sender`
+        """
+        pass
 
     def test(self, link): return link.is_sender
 
 
 class ReceiverOption(LinkOption):
-    def apply(self, receiver): pass
+    """
+    Abstract class for receiver options
+    """
+    def apply(self, receiver):
+        """
+        Set the option on the receiver.
+
+        :param receiver: The receiver on which this option is to be applied.
+        :type receiver: :class:`proton.Receiver`
+        """
+        pass
 
     def test(self, link): return link.is_receiver
 
 
 class DynamicNodeProperties(LinkOption):
+    """
+    Allows a map of link properties to be set on a link. The
+    keys may be :class:`proton.symbol` or strings (in which case
+    they will be converted to symbols before being applied).
+
+    :param props: A map of link options to be applied to a link.
+    :type props: ``dict``
+    """
     def __init__(self, props={}):
         self.properties = {}
         for k in props:
@@ -580,6 +707,12 @@
                 self.properties[symbol(k)] = props[k]
 
     def apply(self, link):
+        """
+        Set the map of properties on the specified link.
+
+        :param link: The link on which this property map is to be set.
+        :type link: :class:`proton.Link`
+        """
         if link.is_receiver:
             link.source.properties.put_dict(self.properties)
         else:
@@ -587,16 +720,34 @@
 
 
 class Filter(ReceiverOption):
+    """
+    Receiver option which allows incoming messages to be filtered.
+
+    :param filter_set: A map of filters with :class:`proton.symbol` keys
+        containing the filter name, and the value a filter string.
+    :type filter_set: ``dict``
+    """
     def __init__(self, filter_set={}):
         self.filter_set = filter_set
 
     def apply(self, receiver):
+        """
+        Set the filter on the specified receiver.
+
+        :param receiver: The receiver on which this filter is to be applied.
+        :type receiver: :class:`proton.Receiver`
+        """
         receiver.source.filter.put_dict(self.filter_set)
 
 
 class Selector(Filter):
     """
-    Configures a link with a message selector filter
+    Configures a receiver with a message selector filter
+
+    :param value: Selector filter string
+    :type value: ``str``
+    :param name: Name of the selector, defaults to ``"selector"``.
+    :type name: ``str``
     """
 
     def __init__(self, value, name='selector'):
@@ -604,18 +755,54 @@
 
 
 class DurableSubscription(ReceiverOption):
+    """
+    Receiver option which sets both the configuration and delivery state
+    to durable. This is achieved by setting the receiver's source durability
+    to :const:`proton.Terminus.DELIVERIES` and the source expiry policy to
+    :const:`proton.Terminus.EXPIRE_NEVER`.
+    """
     def apply(self, receiver):
+        """
+        Set durability on the specified receiver.
+
+        :param receiver: The receiver on which durability is to be set.
+        :type receiver: :class:`proton.Receiver`
+        """
         receiver.source.durability = Terminus.DELIVERIES
         receiver.source.expiry_policy = Terminus.EXPIRE_NEVER
 
 
 class Move(ReceiverOption):
+    """
+    Receiver option which moves messages to the receiver (rather than copying).
+    This has the effect of distributing the incoming messages between the
+    receivers. This is achieved by setting the receiver source distribution
+    mode to :const:`proton.Terminus.DIST_MODE_MOVE`.
+    """
     def apply(self, receiver):
+        """
+        Set message move semantics on the specified receiver.
+
+        :param receiver: The receiver on which message move semantics is to be set.
+        :type receiver: :class:`proton.Receiver`
+        """
         receiver.source.distribution_mode = Terminus.DIST_MODE_MOVE
 
 
 class Copy(ReceiverOption):
+    """
+    Receiver option which copies messages to the receiver. This ensures that all
+    receivers receive all incoming messages, no matter how many receivers there
+    are. This is achieved by setting the receiver source distribution mode to
+    :const:`proton.Terminus.DIST_MODE_COPY`.
+    """
     def apply(self, receiver):
+        """
+        Set message copy semantics on the specified receiver.
+
+        :param receiver: The receiver on which message copy semantics is to be set.
+        :type receiver: :class:`proton.Receiver`
+        """
         receiver.source.distribution_mode = Terminus.DIST_MODE_COPY
 
 
@@ -803,16 +990,30 @@
 class Backoff(object):
     """
     A reconnect strategy involving an increasing delay between
-    retries, up to a maximum or 10 seconds.
+    retries, up to a maximum or 10 seconds. Repeated calls
+    to :meth:`next` returns a value for the next delay, starting
+    with an initial value of 0 seconds.
     """
 
     def __init__(self):
         self.delay = 0
 
     def reset(self):
+        """
+        Reset the backoff delay to 0 seconds.
+        """
         self.delay = 0
 
     def next(self):
+        """
+        Start the next delay in the sequence of delays. The first
+        delay is 0 seconds, the second 0.1 seconds, and each subsequent
+        call to :meth:`next` doubles the next delay period until a
+        maximum value of 10 seconds is reached.
+
+        :return: The next delay in seconds.
+        :rtype: ``float``
+        """
         current = self.delay
         if current == 0:
             self.delay = 0.1
@@ -888,11 +1089,12 @@
         return 5672
 
 class Container(Reactor):
-    """A representation of the AMQP concept of a 'container', which
-       loosely speaking is something that establishes links to or from
-       another container, over which messages are transfered. This is
-       an extension to the Reactor class that adds convenience methods
-       for creating connections and sender- or receiver- links.
+    """
+    A representation of the AMQP concept of a 'container', which
+    loosely speaking is something that establishes links to or from
+    another container, over which messages are transfered. This is
+    an extension to the Reactor class that adds convenience methods
+    for creating connections and sender- or receiver- links.
     """
 
     def __init__(self, *handlers, **kwargs):
@@ -914,51 +1116,103 @@
     def connect(self, url=None, urls=None, address=None, handler=None, reconnect=None, heartbeat=None, ssl_domain=None,
                 **kwargs):
         """
-        Initiates the establishment of an AMQP connection. Returns an
-        instance of proton.Connection.
+        Initiates the establishment of an AMQP connection.
 
-        @param url: URL string of process to connect to
+        An optional JSON configuration file may be used to specify some connection
+        parameters. If present, these will override some of those given in this call
+        (see note below). Some connection parameters (for SSL/TLS) can only be
+        provided through this file. The configuration file is located by searching
+        for it as follows:
 
-        @param urls: list of URL strings of process to try to connect to
+            1.  The location set in the environment variable ``MESSAGING_CONNECT_FILE``
+            2.  ``.connect.json``
+            3.  ``~/.config/messaging/connect.json``
+            4.  ``/etc/messaging/connect.json``
 
-        Only one of url or urls should be specified.
+        To use SSL/TLS for encryption (when an ``amqps`` URL scheme is used), the above
+        configuration file must contain a ``tls`` submap containing the following
+        configuration entries (See :class:`proton.SSLDomain` for details):
+        
+        *   ``ca``: Path to a database of trusted CAs that the server will advertise.
+        *   ``cert``: Path to a file/database containing the identifying certificate.
+        *   ``key``: An optional key to access the identifying certificate.
+        *   ``verify``: If ``True``, verify the peer name
+            (:const:`proton.SSLDomain.VERIFY_PEER_NAME`) and certificate using the
+            ``ca`` above.
 
-        @param reconnect: Reconnect is enabled by default.  You can
-        pass in an instance of Backoff to control reconnect behavior.
-        A value of False will prevent the library from automatically
-        trying to reconnect if the underlying socket is disconnected
-        before the connection has been closed.
+        :param url: URL string of process to connect to
+        :type url: ``str``
 
-        @param heartbeat: A value in milliseconds indicating the
-        desired frequency of heartbeats used to test the underlying
-        socket is alive.
+        :param urls: list of URL strings of process to try to connect to
+        :type urls: ``[str, str, ...]``
 
-        @param ssl_domain: SSL configuration in the form of an
-        instance of proton.SSLDomain.
+        :param reconnect: Reconnect is enabled by default.  You can
+            pass in an instance of :class:`Backoff` to control reconnect behavior.
+            A value of ``False`` will prevent the library from automatically
+            trying to reconnect if the underlying socket is disconnected
+            before the connection has been closed.
+        :type reconnect: :class:`Backoff` or ``bool``
 
-        @param handler: a connection scoped handler that will be
-        called to process any events in the scope of this connection
-        or its child links
+        :param heartbeat: A value in seconds indicating the
+            desired frequency of heartbeats used to test the underlying
+            socket is alive.
+        :type heartbeat: ``float``
 
-        @param kwargs: 'sasl_enabled', which determines whether a sasl
-        layer is used for the connection. 'allowed_mechs', an optional
-        string specifying the SASL mechanisms allowed for this
-        connection; the value is a space-separated list of mechanism
-        names; the mechanisms allowed by default are determined by
-        your SASL library and system configuration, with two
-        exceptions: GSSAPI and GSS-SPNEGO are disabled by default; to
-        enable them, you must explicitly add them using this option;
-        clients must set the allowed mechanisms before the the
-        outgoing connection is attempted; servers must set them before
-        the listening connection is setup.  'allow_insecure_mechs', a
-        flag indicating whether insecure mechanisms, such as PLAIN
-        over a non-encrypted socket, are allowed. 'virtual_host', the
-        hostname to set in the Open performative used by peer to
-        determine the correct back-end service for the client; if
-        'virtual_host' is not supplied the host field from the URL is
-        used instead. 'user', the user to authenticate. 'password',
-        the authentication secret.
+        :param ssl_domain: SSL configuration.
+        :type ssl_domain: :class:`proton.SSLDomain`
 
+        :param handler: a connection scoped handler that will be
+            called to process any events in the scope of this connection
+            or its child links.
+        :type handler: Any child of :class:`proton.Events.Handler`
+
+        :param kwargs:
+
+            *   ``sasl_enabled`` (``bool``), which determines whether a sasl layer
+                is used for the connection.
+            *   ``allowed_mechs`` (``str``), an optional string specifying the
+                SASL mechanisms allowed for this  connection; the value is a
+                space-separated list of mechanism  names; the mechanisms allowed
+                by default are determined by your SASL library and system
+                configuration, with two exceptions: ``GSSAPI`` and ``GSS-SPNEGO``
+                are disabled by default; to enable them, you must explicitly add
+                them using this option; clients must set the allowed mechanisms
+                before the the outgoing connection is attempted; servers must set
+                them before the listening connection is setup.
+            *   ``allow_insecure_mechs`` (``bool``), a flag indicating whether insecure
+                mechanisms, such as PLAIN over a non-encrypted socket, are
+                allowed.
+            *   ``password`` (``str``), the authentication secret. Ignored without ``user``
+                kwarg also being present.
+            *   ``user`` (``str``), the user to authenticate.
+            *   ``virtual_host`` (``str``), the hostname to set in the Open performative
+                used by peer to determine the correct back-end service for
+                the client; if ``virtual_host`` is not supplied the host field
+                from the URL is used instead.
+            *   ``offered_capabilities``, a list of capabilities being offered to the
+                peer.
+            *   ``desired_capabilities``, a list of capabilities desired from the peer.
+            *   ``properties``, a list of connection properties
+            *   ``sni`` (``str``), a hostname to use with SSL/TLS Server Name Indication (SNI)
+            *   ``max_frame_size`` (``int``), the maximum allowable TCP packet size between the
+                peers.
+
+        :return: A new connection object.
+        :rtype: :class:`proton.Connection`
+
+        .. note:: Only one of ``url`` or ``urls`` should be specified.
+
+        .. note:: The following kwargs will be overridden by the values found
+            in the JSON configuration file (if they exist there):
+
+            * ``password``
+            * ``user``
+
+            and the following kwargs will be overridden by the values found in the ``sasl``
+            sub-map of the above configuration file (if they exist there):
+
+            * ``sasl_enabled``
+            * ``allowed_mechs``
         """
         if not url and not urls and not address:
             config = _get_default_config()
@@ -1059,24 +1313,50 @@
     def create_sender(self, context, target=None, source=None, name=None, handler=None, tags=None, options=None):
         """
         Initiates the establishment of a link over which messages can
-        be sent. Returns an instance of proton.Sender.
+        be sent.
 
-        There are two patterns of use. (1) A connection can be passed
-        as the first argument, in which case the link is established
-        on that connection. In this case the target address can be
-        specified as the second argument (or as a keyword
-        argument). The source address can also be specified if
-        desired. (2) Alternatively a URL can be passed as the first
-        argument. In this case a new connection will be established on
-        which the link will be attached. If a path is specified and
-        the target is not, then the path of the URL is used as the
-        target address.
+        There are two patterns of use:
+
+        1.  A connection can be passed as the first argument, in which
+            case the link is established on that connection. In this case
+            the target address can be specified as the second argument (or
+            as a keyword argument). The source address can also be specified
+            if desired.
+
+        2.  Alternatively a URL can be passed as the first argument. In
+            this case a new connection will be established on which the link
+            will be attached. If a path is specified and the target is not,
+            then the path of the URL is used as the target address.
 
         The name of the link may be specified if desired, otherwise a
         unique name will be generated.
 
-        Various LinkOptions can be specified to further control the
+        Various :class:`LinkOption` s can be specified to further control the
         attachment.
+
+        :param context: A connection object or a URL.
+        :type context: :class:`proton.Connection` or ``str``
+
+        :param target: Address of target node.
+        :type target: ``str``
+
+        :param source: Address of source node.
+        :type source: ``str``
+
+        :param name: Sender name.
+        :type name: ``str``
+
+        :param handler: Event handler for this sender.
+        :type handler: Any child class of :class:`proton.Handler`
+
+        :param tags: Function to generate tags for this sender of the form ``def simple_tags():`` and returns a ``bytes`` type
+        :type tags: function pointer
+
+        :param options: A single option, or a list of sender options
+        :type options: :class:`SenderOption` or [SenderOption, SenderOption, ...]
+
+        :return: New sender instance.
+        :rtype: :class:`proton.Sender`
         """
         if isstring(context):
             context = Url(context)
@@ -1099,25 +1379,50 @@
     def create_receiver(self, context, source=None, target=None, name=None, dynamic=False, handler=None, options=None):
         """
         Initiates the establishment of a link over which messages can
-        be received (aka a subscription). Returns an instance of
-        proton.Receiver.
+        be received (aka a subscription).
 
-        There are two patterns of use. (1) A connection can be passed
-        as the first argument, in which case the link is established
-        on that connection. In this case the source address can be
-        specified as the second argument (or as a keyword
-        argument). The target address can also be specified if
-        desired. (2) Alternatively a URL can be passed as the first
-        argument. In this case a new connection will be established on
-        which the link will be attached. If a path is specified and
-        the source is not, then the path of the URL is used as the
-        target address.
+        There are two patterns of use:
+
+        (1) A connection can be passed as the first argument, in which
+        case the link is established on that connection. In this case
+        the source address can be specified as the second argument (or
+        as a keyword argument). The target address can also be specified
+        if desired.
+
+        (2) Alternatively a URL can be passed as the first argument. In
+        this case a new connection will be established on which the link
+        will be attached. If a path is specified and the source is not,
+        then the path of the URL is used as the target address.
 
         The name of the link may be specified if desired, otherwise a
         unique name will be generated.
 
-        Various LinkOptions can be specified to further control the
+        Various :class:`LinkOption` s can be specified to further control the
         attachment.
+
+        :param context: A connection object or a URL.
+        :type context: :class:`proton.Connection` or ``str``
+
+        :param source: Address of source node.
+        :type source: ``str``
+
+        :param target: Address of target node.
+        :type target: ``str``
+
+        :param name: Receiver name.
+        :type name: ``str``
+
+        :param dynamic: If ``True``, indicates dynamic creation of the receiver.
+        :type dynamic: ``bool``
+
+        :param handler: Event handler for this receiver.
+        :type handler: Any child class of :class:`proton.Handler`
+
+        :param options: A single option, or a list of receiver options
+        :type options: :class:`ReceiverOption` or [ReceiverOption, ReceiverOption, ...]
+
+        :return: New receiver instance.
+        :rtype: :class:`proton.Receiver`
         """
         if isstring(context):
             context = Url(context)
@@ -1138,6 +1443,17 @@
         return rcv
 
     def declare_transaction(self, context, handler=None, settle_before_discharge=False):
+        """
+        Declare a local transaction.
+
+        :param context: Context for the transaction, usually the connection.
+        :type context: :class:`proton.Connection`
+        :param handler: Handler for transactional events.
+        :type handler: :class:`proton.handlers.TransactionHandler`
+        :param settle_before_discharge: Settle all transaction control messages before
+            the transaction is discharged.
+        :type settle_before_discharge: ``bool``
+        """
         if not _get_attr(context, '_txn_ctrl'):
             class InternalTransactionHandler(OutgoingMessageHandler):
                 def __init__(self):
@@ -1161,6 +1477,11 @@
         """
         Initiates a server socket, accepting incoming AMQP connections
         on the interface and port specified.
+
+        :param url: URL on which to listen for incoming AMQP connections.
+        :type url: ``str`` or :class:`Url`
+        :param ssl_domain: SSL configuration object if SSL is to be used, ``None`` otherwise.
+        :type ssl_domain: :class:`proton.SSLDomain` or ``None``
         """
         url = Url(url)
         acceptor = self.acceptor(url.host, url.port)
diff --git a/python/proton/_transport.py b/python/proton/_transport.py
index eb61a22..af9ab9d 100644
--- a/python/proton/_transport.py
+++ b/python/proton/_transport.py
@@ -58,13 +58,29 @@
 
 
 class Transport(Wrapper):
+    """
+    A network channel supporting an AMQP connection.
+    """
+
     TRACE_OFF = PN_TRACE_OFF
+    """ Turn logging off entirely. """
+
     TRACE_DRV = PN_TRACE_DRV
+    """  Log driver-related events. """
+
     TRACE_FRM = PN_TRACE_FRM
+    """ Log protocol frames going in and out of the transport. """
+
     TRACE_RAW = PN_TRACE_RAW
+    """ Log raw binary data going in and out of the transport. """
+
 
     CLIENT = 1
+    """ Transport mode is as a client. """
+
     SERVER = 2
+    """ Transport mode is as a server. """
+
 
     @staticmethod
     def wrap(impl):
@@ -104,54 +120,169 @@
         else:
             return None
 
-    tracer = property(_get_tracer, _set_tracer,
-                      doc="""
-A callback for trace logging. The callback is passed the transport and log message.
-""")
+    tracer = property(_get_tracer, _set_tracer, doc="""
+        A callback for trace logging. The callback is passed the transport
+        and log message. For no tracer callback, value is ``None``.
+
+        :type: Tracer callback function
+        """)
 
     def log(self, message):
+        """
+        Log a message using a transport's logging mechanism.
+        
+        This can be useful in a debugging context as the log message will
+        be prefixed with the transport's identifier.
+
+        :param message: The message to be logged.
+        :type message: ``str``
+        """
         pn_transport_log(self._impl, message)
 
     def require_auth(self, bool):
+        """
+        Set whether a non-authenticated transport connection is allowed.
+
+        There are several ways within the AMQP protocol suite to get
+        unauthenticated connections:
+
+            - Use no SASL layer (with either no TLS or TLS without client certificates)
+            - Use a SASL layer but the ANONYMOUS mechanism
+
+        The default if this option is not set is to allow unauthenticated connections.
+
+        :param bool: ``True`` when authenticated connections are required.
+        :type bool: ``bool``
+        """
         pn_transport_require_auth(self._impl, bool)
 
     @property
     def authenticated(self):
+        """
+        Indicate whether the transport connection is authenticated.
+
+        .. note:: This property may not be stable until the :const:`Event.CONNECTION_REMOTE_OPEN`
+            event is received.
+
+        :type: ``bool``
+        """
         return pn_transport_is_authenticated(self._impl)
 
     def require_encryption(self, bool):
+        """
+        Set whether a non encrypted transport connection is allowed
+
+        There are several ways within the AMQP protocol suite to get encrypted connections:
+
+            - Use TLS
+            - Use a SASL with a mechanism that supports security layers
+
+        The default if this option is not set is to allow unencrypted connections.
+
+        :param bool: ``True`` if encryption is required on this transport, ``False`` otherwise.
+        :type bool: ``bool``
+        """
         pn_transport_require_encryption(self._impl, bool)
 
     @property
     def encrypted(self):
+        """
+        Indicate whether the transport connection is encrypted.
+
+        .. note:: This property may not be stable until the :const:`Event.CONNECTION_REMOTE_OPEN`
+            event is received.
+
+        :type: ``bool``
+        """
         return pn_transport_is_encrypted(self._impl)
 
     @property
     def user(self):
+        """
+        The authenticated user.
+ 
+        On the client it will return whatever user was passed in to the
+        :attr:`Connection.user` attribute of the bound connection.
+
+        The returned value is only reliable after the ``PN_TRANSPORT_AUTHENTICATED``
+        event has been received.
+
+        :type: ``str``
+        """
         return pn_transport_get_user(self._impl)
 
     def bind(self, connection):
-        """Assign a connection to the transport"""
+        """
+        Assign a connection to the transport.
+
+        :param connection: Connection to which to bind.
+        :type connection: :class:`Connection`
+        :raise: :exc:`TransportException` if there is any Proton error.
+        """
         self._check(pn_transport_bind(self._impl, connection._impl))
 
     def bind_nothrow(self, connection):
-        """Assign a connection to the transport"""
+        """
+        Assign a connection to the transport. Any failure is
+        ignored rather than thrown.
+
+        :param connection: Connection to which to bind.
+        :type connection: :class:`Connection`
+        """
         pn_transport_bind(self._impl, connection._impl)
 
     def unbind(self):
-        """Release the connection"""
+        """
+        Unbinds a transport from its AMQP connection.
+
+        :raise: :exc:`TransportException` if there is any Proton error.
+        """
         self._check(pn_transport_unbind(self._impl))
 
     def trace(self, n):
+        """
+        Update a transports trace flags.
+
+        The trace flags for a transport control what sort of information is
+        logged. The value may be :const:`TRACE_OFF` or any combination of
+        :const:`TRACE_DRV`, :const:`TRACE_FRM`, :const:`TRACE_RAW` using
+        a bitwise or operation.
+
+        :param n: Trace flags
+        :type n: ``int``
+        """
         pn_transport_trace(self._impl, n)
 
     def tick(self, now):
-        """Process any timed events (like heartbeat generation).
-        now = seconds since epoch (float).
+        """
+        Process any pending transport timer events (like heartbeat generation).
+
+        This method should be called after all pending input has been
+        processed by the transport and before generating output. It returns
+        the deadline for the next pending timer event, if any are present.
+
+        .. note:: This function does nothing until the first data is read
+            from or written to the transport.
+
+        :param now: seconds since epoch.
+        :type now: ``float``
+        :return: If non-zero, then the monotonic expiration time of the next
+                 pending timer event for the transport.  The caller must invoke
+                 :meth:`tick` again at least once at or before this deadline
+                 occurs. If ``0.0``, then there are no pending events.
+        :rtype: ``float``
         """
         return millis2secs(pn_transport_tick(self._impl, secs2millis(now)))
 
     def capacity(self):
+        """
+        Get the amount of free space for input following the transport's
+        tail pointer.
+        
+        :return: Available space for input in bytes.
+        :rtype: ``int``
+        :raise: :exc:`TransportException` if there is any Proton error.
+        """
         c = pn_transport_capacity(self._impl)
         if c >= PN_EOS:
             return c
@@ -159,14 +290,41 @@
             return self._check(c)
 
     def push(self, binary):
+        """
+        Pushes the supplied bytes into the tail of the transport.
+        Only some of the bytes will be copied if there is insufficient
+        capacity available. Use :meth:`capacity` to determine how much
+        capacity the transport has.
+
+        :param binary: Data to be pushed onto the transport tail.
+        :type binary: ``bytes``
+        :raise: - :exc:`TransportException` if there is any Proton error.
+                - ``OverflowError`` if the size of the data exceeds the
+                  transport capacity.
+        """
         n = self._check(pn_transport_push(self._impl, binary))
         if n != len(binary):
             raise OverflowError("unable to process all bytes: %s, %s" % (n, len(binary)))
 
     def close_tail(self):
+        """
+        Indicate that the input has reached End Of Stream (EOS).
+
+        This tells the transport that no more input will be forthcoming.
+
+        :raise: :exc:`TransportException` if there is any Proton error.
+        """
         self._check(pn_transport_close_tail(self._impl))
 
     def pending(self):
+        """
+        Get the number of pending output bytes following the transport's
+        head pointer.
+
+        :return: The number of pending output bytes.
+        :rtype: ``int``
+        :raise: :exc:`TransportException` if there is any Proton error.
+        """
         p = pn_transport_pending(self._impl)
         if p >= PN_EOS:
             return p
@@ -174,6 +332,19 @@
             return self._check(p)
 
     def peek(self, size):
+        """
+        Returns ``size`` bytes from the head of the transport.
+
+        It is an error to call this with a value of ``size`` that
+        is greater than the value reported by :meth:`pending`.
+
+        :param size: Number of bytes to return.
+        :type size: ``int``
+        :return: ``size`` bytes from the head of the transport, or ``None``
+                 if none are available.
+        :rtype: ``bytes``
+        :raise: :exc:`TransportException` if there is any Proton error.
+        """
         cd, out = pn_transport_peek(self._impl, size)
         if cd == PN_EOS:
             return None
@@ -182,13 +353,37 @@
             return out
 
     def pop(self, size):
+        """
+        Removes ``size`` bytes of output from the pending output queue
+        following the transport's head pointer.
+
+        Calls to this function may alter the transport's head pointer as
+        well as the number of pending bytes reported by
+        :meth:`pending`.
+
+        :param size: Number of bytes to return.
+        :type size: ``int``
+        """
         pn_transport_pop(self._impl, size)
 
     def close_head(self):
+        """
+        Indicate that the output has closed.
+
+        This tells the transport that no more output will be popped.
+
+        :raise: :exc:`TransportException` if there is any Proton error.
+        """
         self._check(pn_transport_close_head(self._impl))
 
     @property
     def closed(self):
+        """
+        ``True`` iff both the transport head and transport tail are closed
+        using :meth:`close_head` and :meth:`close_tail` respectively.
+
+        :type: ``bool``
+        """
         return pn_transport_closed(self._impl)
 
     # AMQP 1.0 max-frame-size
@@ -198,13 +393,19 @@
     def _set_max_frame_size(self, value):
         pn_transport_set_max_frame(self._impl, value)
 
-    max_frame_size = property(_get_max_frame_size, _set_max_frame_size,
-                              doc="""
-Sets the maximum size for received frames (in bytes).
-""")
+    max_frame_size = property(_get_max_frame_size, _set_max_frame_size, doc="""
+        The maximum size for transport frames (in bytes).
+
+        :type: ``int``
+        """)
 
     @property
     def remote_max_frame_size(self):
+        """
+        The maximum frame size of a transport's remote peer (in bytes).
+
+        :type: ``int``
+        """
         return pn_transport_get_remote_max_frame(self._impl)
 
     def _get_channel_max(self):
@@ -214,13 +415,34 @@
         if pn_transport_set_channel_max(self._impl, value):
             raise SessionException("Too late to change channel max.")
 
-    channel_max = property(_get_channel_max, _set_channel_max,
-                           doc="""
-Sets the maximum channel that may be used on the transport.
-""")
+    channel_max = property(_get_channel_max, _set_channel_max, doc="""
+        The maximum channel number that may be used on this transport.
+
+        .. note:: This is the maximum channel number allowed, giving a
+            valid channel number range of ``[0 .. channel_max]``. Therefore the
+            maximum number of simultaneously active channels will be
+            channel_max plus 1.
+
+        You can set this more than once to raise and lower
+        the limit your application imposes on max channels for this
+        transport.  However, smaller limits may be imposed by Proton,
+        or by the remote peer.
+
+        After the ``OPEN`` frame has been sent to the remote peer,
+        further calls to this function will have no effect.
+
+        :type: ``int``
+        :raise: :exc:`SessionException` if the ``OPEN`` frame has already
+                been sent.
+        """)
 
     @property
     def remote_channel_max(self):
+        """
+        The maximum allowed channel number of a transport's remote peer.
+
+        :type: ``int``
+        """
         return pn_transport_remote_channel_max(self._impl)
 
     # AMQP 1.0 idle-time-out
@@ -230,27 +452,63 @@
     def _set_idle_timeout(self, sec):
         pn_transport_set_idle_timeout(self._impl, secs2millis(sec))
 
-    idle_timeout = property(_get_idle_timeout, _set_idle_timeout,
-                            doc="""
-The idle timeout of the connection (float, in seconds).
-""")
+    idle_timeout = property(_get_idle_timeout, _set_idle_timeout, doc="""
+        The idle timeout of the connection in seconds. A zero idle
+        timeout means heartbeats are disabled.
+
+        :type: ``float``
+        """)
 
     @property
     def remote_idle_timeout(self):
+        """
+        Get the idle timeout for a transport's remote peer in
+        seconds. A zero idle timeout means heartbeats are disabled.
+
+        :type: ``float``
+        """
         return millis2secs(pn_transport_get_remote_idle_timeout(self._impl))
 
     @property
     def frames_output(self):
+        """
+        Get the number of frames output by a transport.
+
+        :type: ``int``
+        """
         return pn_transport_get_frames_output(self._impl)
 
     @property
     def frames_input(self):
+        """
+        Get the number of frames input by a transport.
+
+        :type: ``int``
+        """
         return pn_transport_get_frames_input(self._impl)
 
     def sasl(self):
+        """
+        Get the :class:`SASL` object associated with this transport.
+
+        :return: SASL object associated with this transport.
+        :rtype: :class:`SASL`
+        """
         return SASL(self)
 
     def ssl(self, domain=None, session_details=None):
+        """
+        Get the :class:`SSL` session associated with this transport. If
+        not set, then a new session will be created using ``domain`` and
+        ``session_details``.
+
+        :param domain: An SSL domain configuration object
+        :type domain: :class:`SSLDomain`
+        :param session_details: A unique identifier for the SSL session.
+        :type session_details: :class:`SSLSessionDetails`
+        :return: SSL session associated with this transport.
+        :rtype: :class:`SSL`
+        """
         # SSL factory (singleton for this transport)
         if not self._ssl:
             self._ssl = SSL(self, domain, session_details)
@@ -263,13 +521,24 @@
         pn_cond = pn_transport_condition(self._impl)
         obj2cond(cond, pn_cond)
 
-    condition = property(_get_condition, _set_condition,
-                         doc="""
-The error condition (if any) of the transport.
-""")
+    condition = property(_get_condition, _set_condition, doc="""
+        Get additional information about the condition of the transport.
+
+        When a :const:`Event.TRANSPORT_ERROR` event occurs, this operation
+        can be used to access the details of the error condition.
+
+        See :class:`Condition` for more information.
+
+        :type: :class:`Condition`
+        """)
 
     @property
     def connection(self):
+        """
+        The connection bound to this transport.
+
+        :type: :class:`Connection`
+        """
         from . import _endpoints
         return _endpoints.Connection.wrap(pn_transport_connection(self._impl))
 
@@ -279,6 +548,13 @@
 
 
 class SASL(Wrapper):
+    """
+    The SASL layer is responsible for establishing an authenticated
+    and/or encrypted tunnel over which AMQP frames are passed between
+    peers. The peer acting as the SASL Client must provide
+    authentication credentials. The peer acting as the SASL Server must
+    provide authentication against the received credentials.
+    """
     OK = PN_SASL_OK
     AUTH = PN_SASL_AUTH
     SYS = PN_SASL_SYS
@@ -287,6 +563,18 @@
 
     @staticmethod
     def extended():
+        """
+        Check for support of extended SASL negotiation.
+
+        All implementations of Proton support ``ANONYMOUS`` and ``EXTERNAL`` on both
+        client and server sides and ``PLAIN`` on the client side.
+
+        Extended SASL implementations use an external library (Cyrus SASL)
+        to support other mechanisms beyond these basic ones.
+
+        :rtype: ``True`` if we support extended SASL negotiation, ``False`` if
+               we only support basic negotiation.
+        """
         return pn_sasl_extended()
 
     def __init__(self, transport):
@@ -302,14 +590,42 @@
 
     @property
     def user(self):
+        """
+        Retrieve the authenticated user. This is usually used at the the
+        server end to find the name of the authenticated user.
+
+        If :meth:`outcome` returns a value other than :const:`OK`, then
+        there will be no user to return. The returned value is only reliable
+        after the ``PN_TRANSPORT_AUTHENTICATED`` event has been received.
+
+        :rtype: * If the SASL layer was not negotiated then ``0`` is returned.
+                * If the ``ANONYMOUS`` mechanism is used then the user will be
+                  ``"anonymous"``.
+                * Otherwise a string containing the user is
+                  returned.
+        """
         return pn_sasl_get_user(self._sasl)
 
     @property
     def mech(self):
+        """
+        Return the selected SASL mechanism.
+
+        The returned value is only reliable after the ``PN_TRANSPORT_AUTHENTICATED``
+        event has been received.
+        
+        :rtype: The authentication mechanism selected by the SASL layer.
+        """
         return pn_sasl_get_mech(self._sasl)
 
     @property
     def outcome(self):
+        """
+        Retrieve the outcome of SASL negotiation.
+        
+        :rtype: * ``None`` if no negotiation has taken place.
+                * Otherwise the outcome of the negotiation.
+        """
         outcome = pn_sasl_outcome(self._sasl)
         if outcome == PN_SASL_NONE:
             return None
@@ -317,6 +633,29 @@
             return outcome
 
     def allowed_mechs(self, mechs):
+        """
+        SASL mechanisms that are to be considered for authentication.
+
+        This can be used on either the client or the server to restrict
+        the SASL mechanisms that may be used to the mechanisms on the list.
+
+        **NOTE:** By default the ``GSSAPI`` and ``GSS-SPNEGO`` mechanisms
+        are not enabled for clients. This is because these mechanisms have
+        the problematic behaviour of 'capturing' the client whenever they
+        are installed so that they will be used by the client if offered by
+        the server even if the client can't successfully authenticate this
+        way. This can lead to some very hard to debug failures.
+
+        **NOTE:** The ``GSSAPI`` or ``GSS-SPNEGO`` mechanisms need to be
+        explicitly enabled if they are required (together with any other
+        required mechanisms).
+
+        :param mechs: A list of mechanisms that are allowed for authentication,
+                      either a string containing a space-separated list of mechs
+                      ``"mech1 mech2 ..."``, or a Python list of strings
+                      ``["mech1", "mech2", ...]``.
+        :type mechs: string
+        """
         if isinstance(mechs, list):
             mechs = " ".join(mechs)
         pn_sasl_allowed_mechs(self._sasl, unicode2utf8(mechs))
@@ -333,21 +672,67 @@
 """)
 
     def done(self, outcome):
+        """
+        Set the outcome of SASL negotiation. Used by the server to set the
+        result of the negotiation process.
+        """
         pn_sasl_done(self._sasl, outcome)
 
     def config_name(self, name):
+        """
+        Set the SASL configuration name. This is used to construct the SASL
+        configuration filename. In the current implementation ``".conf"`` is
+        added to the name and the file is looked for in the configuration
+        directory.
+
+        If not set it will default to ``"proton-server"`` for a sasl server
+        and ``"proton-client"`` for a client.
+
+        :param name: The configuration name.
+        :type name: string
+        """
         pn_sasl_config_name(self._sasl, name)
 
     def config_path(self, path):
+        """
+        Set the SASL configuration path. This is used to tell SASL where
+        to look for the configuration file. In the current implementation
+        it can be a colon separated list of directories.
+
+        The environment variable ``PN_SASL_CONFIG_PATH`` can also be used
+        to set this path, but if both methods are used then this
+        :meth:`config_path` will take precedence.
+
+        If not set, the underlying implementation default will be used.
+
+        :param path: The configuration path, may contain colon-separated list
+                     if more than one path is specified.
+        :type path: string
+        """
         pn_sasl_config_path(self._sasl, path)
 
 
 class SSLDomain(object):
+    """
+    An SSL configuration domain, used to hold the SSL configuration
+    for one or more SSL sessions.
+    """
+
     MODE_CLIENT = PN_SSL_MODE_CLIENT
+    """Local connection endpoint is an SSL client."""
+
     MODE_SERVER = PN_SSL_MODE_SERVER
+    """Local connection endpoint is an SSL server."""
+
     VERIFY_PEER = PN_SSL_VERIFY_PEER
+    """Require peer to provide a valid identifying certificate."""
+
     VERIFY_PEER_NAME = PN_SSL_VERIFY_PEER_NAME
+    """Require valid certificate and matching name."""
+
     ANONYMOUS_PEER = PN_SSL_ANONYMOUS_PEER
+    """Do not require a certificate nor cipher authorization."""
+
 
     def __init__(self, mode):
         self._domain = pn_ssl_domain(mode)
@@ -362,20 +747,104 @@
             return err
 
     def set_credentials(self, cert_file, key_file, password):
+        """
+        Set the certificate that identifies the local node to the remote.
+
+        This certificate establishes the identity for the local node for all :class:`SSL` sessions
+        created from this domain.  It will be sent to the remote if the remote needs to verify
+        the identity of this node.  This may be used for both SSL servers and SSL clients (if
+        client authentication is required by the server).
+
+        .. note:: This setting effects only those :class:`SSL` objects created after this call
+            returns.  :class:`SSL` objects created before invoking this method will use the domain's
+            previous setting.
+
+        :param cert_file: Specifier for the file/database containing the identifying
+               certificate. For Openssl users, this is a PEM file. For Windows SChannel
+               users, this is the PKCS#12 file or system store.
+        :type cert_file: ``str``
+        :param key_file: An optional key to access the identifying certificate. For
+               Openssl users, this is an optional PEM file containing the private key
+               used to sign the certificate. For Windows SChannel users, this is the
+               friendly name of the self-identifying certificate if there are multiple
+               certificates in the store.
+        :type key_file: ``str``
+        :param password: The password used to sign the key, else ``None`` if key is not
+               protected.
+        :type password: ``str`` 
+        :return: 0 on success
+        :rtype: ``int``
+        :raise: :exc:`SSLException` if there is any Proton error
+        """
         return self._check(pn_ssl_domain_set_credentials(self._domain,
                                                          cert_file, key_file,
                                                          password))
 
     def set_trusted_ca_db(self, certificate_db):
+        """
+        Configure the set of trusted CA certificates used by this domain to verify peers.
+
+        If the local SSL client/server needs to verify the identity of the remote, it must
+        validate the signature of the remote's certificate.  This function sets the database of
+        trusted CAs that will be used to verify the signature of the remote's certificate.
+
+        .. note:: This setting effects only those :class:`SSL` objects created after this call
+            returns.  :class:`SSL` objects created before invoking this method will use the domain's
+            previous setting.
+
+        .. note:: By default the list of trusted CA certificates will be set to the system default.
+            What this is is depends on the OS and the SSL implementation used: For OpenSSL the default
+            will depend on how the OS is set up. When using the Windows SChannel implementation the default
+            will be the users default trusted certificate store.
+
+        :param certificate_db: Database of trusted CAs, used to authenticate the peer.
+        :type certificate_db: ``str``
+        :return: 0 on success
+        :rtype: ``int``
+        :raise: :exc:`SSLException` if there is any Proton error
+        """
         return self._check(pn_ssl_domain_set_trusted_ca_db(self._domain,
                                                            certificate_db))
 
     def set_peer_authentication(self, verify_mode, trusted_CAs=None):
+        """
+        This method controls how the peer's certificate is validated, if at all.  By default,
+        neither servers nor clients attempt to verify their peers (PN_SSL_ANONYMOUS_PEER).
+        Once certificates and trusted CAs are configured, peer verification can be enabled.
+
+        .. note:: In order to verify a peer, a trusted CA must be configured. See
+            :meth:`set_trusted_ca_db`.
+
+        .. note:: Servers must provide their own certificate when verifying a peer.  See
+            :meth:`set_credentials`.
+
+        .. note:: This setting effects only those :class:`SSL` objects created after this call
+            returns.  :class:`SSL` objects created before invoking this method will use the domain's
+            previous setting.
+
+        :param verify_mode: The level of validation to apply to the peer, one of :const:`VERIFY_PEER`,
+                            :const:`VERIFY_PEER_NAME`, :const:`ANONYMOUS_PEER`, 
+        :type verify_mode: ``int``
+        :param trusted_CAs: Path to a database of trusted CAs that the server will advertise.
+        :type trusted_CAs: ``str``
+        :return: 0 on success
+        :rtype: ``int``
+        :raise: :exc:`SSLException` if there is any Proton error
+        """
         return self._check(pn_ssl_domain_set_peer_authentication(self._domain,
                                                                  verify_mode,
                                                                  trusted_CAs))
 
     def allow_unsecured_client(self):
+        """
+        Permit a server to accept connection requests from non-SSL clients.
+
+        This configures the server to "sniff" the incoming client data stream,
+        and dynamically determine whether SSL/TLS is being used.  This option
+        is disabled by default: only clients using SSL/TLS are accepted.
+
+        :raise: :exc:`SSLException` if there is any Proton error
+        """
         return self._check(pn_ssl_domain_allow_unsecured_client(self._domain))
 
     def __del__(self):
@@ -383,9 +852,19 @@
 
 
 class SSL(object):
+    """
+    An SSL session associated with a transport. A transport must have
+    an SSL object in order to "speak" SSL over its connection.   
+    """
 
     @staticmethod
     def present():
+        """
+        Tests for an SSL implementation being present.
+
+        :return: ``True`` if we support SSL, ``False`` if not.
+        :rtype: ``bool``
+        """
         return pn_ssl_present()
 
     def _check(self, err):
@@ -421,34 +900,101 @@
         return transport._ssl
 
     def cipher_name(self):
+        """
+        Get the name of the Cipher that is currently in use.
+
+        Gets a text description of the cipher that is currently active, or
+        returns ``None`` if SSL is not active (no cipher).
+
+        .. note:: The cipher in use may change over time due to renegotiation
+            or other changes to the SSL state.
+
+        :return: The cypher name, or ``None`` if no cipher in use.
+        :rtype: ``str`` or ``None``
+        """
         rc, name = pn_ssl_get_cipher_name(self._ssl, 128)
         if rc:
             return name
         return None
 
     def protocol_name(self):
+        """
+        Get the name of the SSL protocol that is currently in use.
+
+        Gets a text description of the SSL protocol that is currently active,
+        or returns ``None`` if SSL is not active.
+
+        .. note:: The protocol may change over time due to renegotiation.
+
+        :return: The protocol name if SSL is active, or ``None`` if SSL connection
+                 is not ready or active.
+        :rtype: ``str`` or ``None``
+        """
         rc, name = pn_ssl_get_protocol_name(self._ssl, 128)
         if rc:
             return name
         return None
 
     SHA1 = PN_SSL_SHA1
+    """Produces hash that is 20 bytes long using SHA-1"""
+
     SHA256 = PN_SSL_SHA256
+    """Produces hash that is 32 bytes long using SHA-256"""
+
     SHA512 = PN_SSL_SHA512
+    """Produces hash that is 64 bytes long using SHA-512"""
+
     MD5 = PN_SSL_MD5
+    """Produces hash that is 16 bytes long using MD5"""
 
     CERT_COUNTRY_NAME = PN_SSL_CERT_SUBJECT_COUNTRY_NAME
+    """Certificate country name 2-char ISO code"""
+
     CERT_STATE_OR_PROVINCE = PN_SSL_CERT_SUBJECT_STATE_OR_PROVINCE
+    """Certificate state or province, not abbreviated"""
+
     CERT_CITY_OR_LOCALITY = PN_SSL_CERT_SUBJECT_CITY_OR_LOCALITY
+    """Certificate city or place name, not abbreviated"""
+
     CERT_ORGANIZATION_NAME = PN_SSL_CERT_SUBJECT_ORGANIZATION_NAME
+    """Certificate organization name"""
+
     CERT_ORGANIZATION_UNIT = PN_SSL_CERT_SUBJECT_ORGANIZATION_UNIT
+    """Certificate organization unit or division within organization"""
+
     CERT_COMMON_NAME = PN_SSL_CERT_SUBJECT_COMMON_NAME
+    """Certificate common name or URL"""
 
     def get_cert_subject_subfield(self, subfield_name):
+        """
+        Returns a string that contains the value of the sub field of
+        the subject field in the ssl certificate. The subject field
+        usually contains the following values:
+
+            * :const:`CERT_COUNTRY_NAME`
+            * :const:`CERT_STATE_OR_PROVINCE` 
+            * :const:`CERT_CITY_OR_LOCALITY`
+            * :const:`CERT_ORGANIZATION_NAME`
+            * :const:`CERT_ORGANIZATION_UNIT`
+            * :const:`CERT_COMMON_NAME` 
+
+        :param subfield_name: The enumeration representing the required
+                              sub field listed above
+        :type subfield_name: ``int``
+        :return: A string which contains the requested sub field value which
+                 is valid until the ssl object is destroyed.
+        :rtype: ``str``
+        """
         subfield_value = pn_ssl_get_remote_subject_subfield(self._ssl, subfield_name)
         return subfield_value
 
     def get_cert_subject(self):
+        """
+        Get the subject from the peer's certificate.
+
+        :return: A string containing the full subject.
+        :rtype: ``str``
+        """
         subject = pn_ssl_get_remote_subject(self._ssl)
         return subject
 
@@ -458,24 +1004,84 @@
 
     # Convenience functions for obtaining the subfields of the subject field.
     def get_cert_common_name(self):
+        """
+        A convenience method to get a string that contains the :const:`CERT_COMMON_NAME`
+        sub field of the subject field in the ssl certificate.
+        
+        :return: A string containing the :const:`CERT_COMMON_NAME` sub field.
+        :rtype: ``str``
+        """
         return self.get_cert_subject_subfield(SSL.CERT_COMMON_NAME)
 
     def get_cert_organization(self):
+        """
+        A convenience method to get a string that contains the :const:`CERT_ORGANIZATION_NAME`
+        sub field of the subject field in the ssl certificate.
+        
+        :return: A string containing the :const:`CERT_ORGANIZATION_NAME` sub field.
+        :rtype: ``str``
+        """
         return self.get_cert_subject_subfield(SSL.CERT_ORGANIZATION_NAME)
 
     def get_cert_organization_unit(self):
+        """
+        A convenience method to get a string that contains the :const:`CERT_ORGANIZATION_UNIT`
+        sub field of the subject field in the ssl certificate.
+        
+        :return: A string containing the :const:`CERT_ORGANIZATION_UNIT` sub field.
+        :rtype: ``str``
+        """
         return self.get_cert_subject_subfield(SSL.CERT_ORGANIZATION_UNIT)
 
     def get_cert_locality_or_city(self):
+        """
+        A convenience method to get a string that contains the :const:`CERT_CITY_OR_LOCALITY`
+        sub field of the subject field in the ssl certificate.
+        
+        :return: A string containing the :const:`CERT_CITY_OR_LOCALITY` sub field.
+        :rtype: ``str``
+        """
         return self.get_cert_subject_subfield(SSL.CERT_CITY_OR_LOCALITY)
 
     def get_cert_country(self):
+        """
+        A convenience method to get a string that contains the :const:`CERT_COUNTRY_NAME`
+        sub field of the subject field in the ssl certificate.
+        
+        :return: A string containing the :const:`CERT_COUNTRY_NAME` sub field.
+        :rtype: ``str``
+        """
         return self.get_cert_subject_subfield(SSL.CERT_COUNTRY_NAME)
 
     def get_cert_state_or_province(self):
+        """
+        A convenience method to get a string that contains the :const:`CERT_STATE_OR_PROVINCE`
+        sub field of the subject field in the ssl certificate.
+        
+        :return: A string containing the :const:`CERT_STATE_OR_PROVINCE` sub field.
+        :rtype: ``str``
+        """
         return self.get_cert_subject_subfield(SSL.CERT_STATE_OR_PROVINCE)
 
     def get_cert_fingerprint(self, fingerprint_length, digest_name):
+        """
+        Get the fingerprint of the certificate. The certificate fingerprint
+        (as displayed in the Fingerprints section when looking at a certificate
+        with say the Firefox browser) is the hexadecimal hash of the entire
+        certificate. The fingerprint is not part of the certificate, rather
+        it is computed from the certificate and can be used to uniquely identify
+        a certificate.
+
+        :param fingerprint_length: Must be :math:`>= 33` for md5, :math:`>= 41`
+                                   for sha1, :math:`>= 65` for sha256 and :math:`>= 129`
+                                   for sha512.
+        :type fingerprint_length: ``int``
+        :param digest_name: The hash algorithm to use. Must be one of :const:`SHA1`,
+                            :const:`SHA256`, :const:`SHA512`,  :const:`MD5`.
+        :type digest_name: ``str``
+        :return: Hex fingerprint in a string, or ``None`` if an error occurred.
+        :rtype: ``str`` or ``None``
+        """
         rc, fingerprint_str = pn_ssl_get_cert_fingerprint(self._ssl, fingerprint_length, digest_name)
         if rc == PN_OK:
             return fingerprint_str
@@ -486,28 +1092,84 @@
         return self.get_cert_fingerprint(41, 10)
 
     def get_cert_fingerprint_sha1(self):
+        """
+        A convenience method to get the :const:`SHA1` fingerprint of the
+        certificate.
+        
+        :return: Hex fingerprint in a string, or ``None`` if an error occurred.
+        :rtype: ``str`` or ``None``
+        """
         return self.get_cert_fingerprint(41, SSL.SHA1)
 
     def get_cert_fingerprint_sha256(self):
+        """
+        A convenience method to get the :const:`SHA256` fingerprint of the
+        certificate.
+        
+        :return: Hex fingerprint in a string, or ``None`` if an error occurred.
+        :rtype: ``str`` or ``None``
+        """
         # sha256 produces a fingerprint that is 64 characters long
         return self.get_cert_fingerprint(65, SSL.SHA256)
 
     def get_cert_fingerprint_sha512(self):
+        """
+        A convenience method to get the :const:`SHA512` fingerprint of the
+        certificate.
+        
+        :return: Hex fingerprint in a string, or ``None`` if an error occurred.
+        :rtype: ``str`` or ``None``
+        """
         # sha512 produces a fingerprint that is 128 characters long
         return self.get_cert_fingerprint(129, SSL.SHA512)
 
     def get_cert_fingerprint_md5(self):
+        """
+        A convenience method to get the :const:`MD5` fingerprint of the
+        certificate.
+        
+        :return: Hex fingerprint in a string, or ``None`` if an error occurred.
+        :rtype: ``str`` or ``None``
+        """
         return self.get_cert_fingerprint(33, SSL.MD5)
 
     @property
     def remote_subject(self):
+        """
+        The subject from the peers certificate.
+
+        :type: ``str``
+        """
         return pn_ssl_get_remote_subject(self._ssl)
 
     RESUME_UNKNOWN = PN_SSL_RESUME_UNKNOWN
+    """Session resume state unknown/not supported."""
+
     RESUME_NEW = PN_SSL_RESUME_NEW
+    """Session renegotiated - not resumed."""
+
     RESUME_REUSED = PN_SSL_RESUME_REUSED
+    """Session resumed from previous session."""
 
     def resume_status(self):
+        """
+        Check whether the state has been resumed.
+
+        Used for client session resume.  When called on an active session,
+        indicates whether the state has been resumed from a previous session.
+
+        .. note:: This is a best-effort service - there is no guarantee that
+            the remote server will accept the resumed parameters.  The remote
+            server may choose to ignore these parameters, and request a
+            re-negotiation instead.
+
+        :return: Status code indicating whether or not the session has been
+                 resumed. One of:
+                 * :const:`RESUME_UNKNOWN`
+                 * :const:`RESUME_NEW`
+                 * :const:`RESUME_REUSED`
+        :rtype: ``int``
+        """
         return pn_ssl_resume_status(self._ssl)
 
     def _set_peer_hostname(self, hostname):
@@ -518,19 +1180,41 @@
         self._check(err)
         return utf82unicode(name)
 
-    peer_hostname = property(_get_peer_hostname, _set_peer_hostname,
-                             doc="""
-Manage the expected name of the remote peer.  Used to authenticate the remote.
-""")
+    peer_hostname = property(_get_peer_hostname, _set_peer_hostname, doc="""
+        Manage the expected name of the remote peer.
+
+        The hostname is used for two purposes:
+        
+            1. when set on an SSL client, it is sent to the server during the
+               handshake (if Server Name Indication is supported)
+            2. it is used to check against the identifying name provided in the
+               peer's certificate. If the supplied name does not exactly match a
+               SubjectAltName (type DNS name), or the CommonName entry in the
+               peer's certificate, the peer is considered unauthenticated
+               (potential imposter), and the SSL connection is aborted.
+ 
+        .. note:: Verification of the hostname is only done if
+            :const:`SSLDomain.VERIFY_PEER_NAME` is set using
+            :meth:`SSLDomain.set_peer_authentication`.
+
+        :type: ``str``
+        """)
 
 
 class SSLSessionDetails(object):
-    """ Unique identifier for the SSL session.  Used to resume previous session on a new
-    SSL connection.
+    """
+    Unique identifier for the SSL session.  Used to resume previous
+    session on a new SSL connection.
     """
 
     def __init__(self, session_id):
         self._session_id = session_id
 
     def get_session_id(self):
+        """
+        Get the unique identifier for this SSL session
+        
+        :return: Session identifier
+        :rtype: ``str``
+        """
         return self._session_id
diff --git a/python/proton/_url.py b/python/proton/_url.py
index 67e1456..2388912 100644
--- a/python/proton/_url.py
+++ b/python/proton/_url.py
@@ -26,35 +26,54 @@
 
 class Url(object):
     """
-    Simple URL parser/constructor, handles URLs of the form:
+    **DEPRECATED** Simple URL parser/constructor.
 
-    <scheme>://<user>:<password>@<host>:<port>/<path>
+    .. deprecated:: 0.27
+        Use a ``str`` containing the URL instead.
 
-    All components can be None if not specified in the URL string.
+    Handles URLs of the form:
+
+        ``<scheme>://<user>:<password>@<host>:<port>/<path>``
+
+    All components can be ``None`` if not specified in the URL string.
 
     The port can be specified as a service name, e.g. 'amqp' in the
-    URL string but Url.port always gives the integer value.
+    URL string but :class:`Url.Port` always gives the integer value.
 
-    Warning: The placement of user and password in URLs is not
-    recommended.  It can result in credentials leaking out in program
-    logs.  Use connection configuration attributes instead.
+    .. warning:: The placement of user and password in URLs is not
+        recommended.  It can result in credentials leaking out in program
+        logs.  Use connection configuration attributes instead.
 
-    @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
-    @ivar user: Username
-    @ivar password: Password
-    @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
-    @ivar port: Integer port.
-    @ivar host_port: Returns host:port
+    :ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
+    :ivar username: Username
+    :ivar ~.password: Password
+    :ivar ~.host: Host name, ipv6 literal or ipv4 dotted quad.
+    :ivar ~.port: Integer port.
+    :ivar host_port: Returns host:port
+    
+    :param url: URL string to parse.
+    :type url: ``str``
+    :param defaults: If ``True``, fill in missing default values in the URL.
+        If ``False``, you can fill them in later by calling self.defaults()
+    :type defaults: ``bool``
+    :param kwargs: scheme, user, password, host, port, path.
+        If specified, replaces corresponding part in url string.
     """
 
     AMQPS = "amqps"
+    """URL scheme for the AMQP protocol secured with SSL."""
+
     AMQP = "amqp"
+    """URL scheme for the AMQP protocol."""
+
 
     class Port(int):
         """An integer port number that can be constructed from a service name string"""
 
         def __new__(cls, value):
-            """@param value: integer port number or string service name."""
+            """
+            :param value: integer port number or string service name.
+            """
             port = super(Url.Port, cls).__new__(cls, cls._port_int(value))
             setattr(port, 'name', str(value))
             return port
@@ -86,13 +105,6 @@
                         raise ValueError("Not a valid port number or service name: '%s'" % value)
 
     def __init__(self, url=None, defaults=True, **kwargs):
-        """
-        @param url: URL string to parse.
-        @param defaults: If true, fill in missing default values in the URL.
-            If false, you can fill them in later by calling self.defaults()
-        @param kwargs: scheme, user, password, host, port, path.
-          If specified, replaces corresponding part in url string.
-        """
         if isinstance(url, Url):
             self.scheme = url.scheme
             self.username = url.username
@@ -159,6 +171,11 @@
 
     @property
     def path(self):
+        """
+        The path segment of a URL
+
+        :type: ``str``
+        """
         return self._path if not self._path or self._path[0] != '/' else self._path[1:]
 
     @path.setter
@@ -171,6 +188,11 @@
 
     @property
     def host(self):
+        """
+        The host segment of a URL
+
+        :type: ``str``
+        """
         if self._host and self._ipv6literal(self._host):
             return self._host[1:-1]
         else:
@@ -185,6 +207,11 @@
 
     @property
     def port(self):
+        """
+        The port number segment of a URL.
+
+        :type: :class:`Url.Port`
+        """
         return self._port and Url.Port(self._port)
 
     @port.setter
@@ -229,7 +256,7 @@
     def defaults(self):
         """
         Fill in missing values (scheme, host or port) with defaults
-        @return: self
+        :return: self
         """
         self.scheme = self.scheme or self.AMQP
         self._host = self._host or '0.0.0.0'
diff --git a/python/proton/_utils.py b/python/proton/_utils.py
index 38639bb..8a10b0f 100644
--- a/python/proton/_utils.py
+++ b/python/proton/_utils.py
@@ -57,6 +57,9 @@
                 raise LinkDetached(self.link)
 
     def close(self):
+        """
+        Close the link.
+        """
         self.link.close()
         self.connection.wait(lambda: not (self.link.state & Endpoint.REMOTE_ACTIVE),
                              msg="Closing link %s" % self.link.name)
@@ -68,7 +71,10 @@
 
 class SendException(ProtonException):
     """
-    Exception used to indicate an exceptional state/condition on a send request
+    Exception used to indicate an exceptional state/condition on a send request.
+
+    :param state: The delivery state which caused the exception.
+    :type state: ``int``
     """
 
     def __init__(self, state):
@@ -80,6 +86,10 @@
 
 
 class BlockingSender(BlockingLink):
+    """
+    A synchronous sender wrapper. This is typically created by calling
+    :meth:`BlockingConnection.create_sender`.
+    """
     def __init__(self, connection, sender):
         super(BlockingSender, self).__init__(connection, sender)
         if self.link.target and self.link.target.address and self.link.target.address != self.link.remote_target.address:
@@ -90,6 +100,21 @@
             raise LinkException("Failed to open sender %s, target does not match" % self.link.name)
 
     def send(self, msg, timeout=False, error_states=None):
+        """
+        Blocking send which will return only when the send is complete
+        and the message settled.
+
+        :param timeout: Timeout in seconds. If ``False``, the value of ``timeout`` used in the
+            constructor of the :class:`BlockingConnection` object used in the constructor will be used.
+            If ``None``, there is no timeout. Any other value is treated as a timeout in seconds.
+        :type timeout: ``None``, ``False``, ``float``
+        :param error_states: List of delivery flags which when present in Delivery object
+            will cause a :class:`SendException` exception to be raised. If ``None``, these
+            will default to a list containing :const:`proton.Delivery.REJECTED` and :const:`proton.Delivery.RELEASED`.
+        :type error_states: ``list``
+        :return: Delivery object for this message.
+        :rtype: :class:`proton.Delivery`
+        """
         delivery = self.link.send(msg)
         self.connection.wait(lambda: _is_settled(delivery), msg="Sending on sender %s" % self.link.name,
                              timeout=timeout)
@@ -104,6 +129,14 @@
 
 
 class Fetcher(MessagingHandler):
+    """
+    A message handler for blocking receivers.
+
+    :param connection:
+    :type connection: :class:
+    :param prefetch:
+    :type prefetch:
+    """
     def __init__(self, connection, prefetch):
         super(Fetcher, self).__init__(prefetch=prefetch, auto_accept=False)
         self.connection = connection
@@ -126,15 +159,34 @@
 
     @property
     def has_message(self):
+        """
+        The number of messages that have been received and are waiting to be
+        retrieved with :meth:`pop`.
+
+        :type: ``int``
+        """
         return len(self.incoming)
 
     def pop(self):
+        """
+        Get the next available incoming message. If the message is unsettled, its
+        delivery object is moved onto the unsettled queue, and can be settled with
+        a call to :meth:`settle`.
+
+        :rtype: :class:`proton.Message`
+        """
         message, delivery = self.incoming.popleft()
         if not delivery.settled:
             self.unsettled.append(delivery)
         return message
 
     def settle(self, state=None):
+        """
+        Settle the next message previously taken with :meth:`pop`.
+
+        :param state:
+        :type state:
+        """
         delivery = self.unsettled.popleft()
         if state:
             delivery.update(state)
@@ -142,6 +194,10 @@
 
 
 class BlockingReceiver(BlockingLink):
+    """
+    A synchronous receiver wrapper. This is typically created by calling
+    :meth:`BlockingConnection.create_receiver`.
+    """
     def __init__(self, connection, receiver, fetcher, credit=1):
         super(BlockingReceiver, self).__init__(connection, receiver)
         if self.link.source and self.link.source.address and self.link.source.address != self.link.remote_source.address:
@@ -163,8 +219,17 @@
             self.link.handler = None  # implicit call to reactor
 
     def receive(self, timeout=False):
+        """
+        Blocking receive call which will return only when a message is received or
+        a timeout (if supplied) occurs.
+
+        :param timeout: Timeout in seconds. If ``False``, the value of ``timeout`` used in the
+            constructor of the :class:`BlockingConnection` object used in the constructor will be used.
+            If ``None``, there is no timeout. Any other value is treated as a timeout in seconds.
+        :type timeout: ``None``, ``False``, ``float``
+        """
         if not self.fetcher:
-            raise Exception("Can't call receive on this receiver as a handler was provided")
+            raise Exception("Can't call receive on this receiver as a handler was not provided")
         if not self.link.credit:
             self.link.flow(1)
         self.connection.wait(lambda: self.fetcher.has_message, msg="Receiving on receiver %s" % self.link.name,
@@ -172,24 +237,56 @@
         return self.fetcher.pop()
 
     def accept(self):
+        """
+        Accept and settle the received message. The delivery is set to
+        :const:`proton.Delivery.ACCEPTED`.
+        """
         self.settle(Delivery.ACCEPTED)
 
     def reject(self):
+        """
+        Reject the received message. The delivery is set to
+        :const:`proton.Delivery.REJECTED`.
+        """
         self.settle(Delivery.REJECTED)
 
     def release(self, delivered=True):
+        """
+        Release the received message.
+
+        :param delivered: If ``True``, the message delivery is being set to
+            :const:`proton.Delivery.MODIFIED`, ie being returned to the sender
+            and annotated. If ``False``, the message is returned without
+            annotations and the delivery set to  :const:`proton.Delivery.RELEASED`.
+        :type delivered: ``bool``
+        """
         if delivered:
             self.settle(Delivery.MODIFIED)
         else:
             self.settle(Delivery.RELEASED)
 
     def settle(self, state=None):
+        """
+        Settle any received messages.
+
+        :param state: Update the delivery of all unsettled messages with the
+            supplied state, then settle them.
+        :type state: ``None`` or a valid delivery state (see
+            :class:`proton.Delivery`.
+        """
         if not self.fetcher:
-            raise Exception("Can't call accept/reject etc on this receiver as a handler was provided")
+            raise Exception("Can't call accept/reject etc on this receiver as a handler was not provided")
         self.fetcher.settle(state)
 
 
 class LinkDetached(LinkException):
+    """
+    The exception raised when the remote peer unexpectedly closes a link in a blocking
+    context, or an unexpected link error occurs.
+
+    :param link: The link which closed unexpectedly.
+    :type link: :class:`proton.Link`
+    """
     def __init__(self, link):
         self.link = link
         if link.is_sender:
@@ -206,6 +303,13 @@
 
 
 class ConnectionClosed(ConnectionException):
+    """
+    The exception raised when the remote peer unexpectedly closes a connection in a blocking
+    context, or an unexpected connection error occurs.
+
+    :param connection: The connection which closed unexpectedly.
+    :type connection: :class:`proton.Connection`
+    """
     def __init__(self, connection):
         self.connection = connection
         txt = "Connection %s closed" % connection.hostname
@@ -226,6 +330,19 @@
     are released when the object is no longer in use, make sure that
     object operations are enclosed in a try block and that close() is
     always executed on exit.
+
+    :param url: Connection URL
+    :type url: :class:`proton.Url` or ``str``
+    :param timeout: Connection timeout in seconds. If ``None``, defaults to 60 seconds.
+    :type timeout: ``None`` or float
+    :param container: Container to process the events on the connection. If ``None``,
+        a new :class:`proton.Container` will be created.
+    :param ssl_domain: 
+    :param heartbeat: A value in seconds indicating the desired frequency of
+        heartbeats used to test the underlying socket is alive.
+    :type heartbeat: ``float``
+    :param kwargs: Container keyword arguments. See :class:`proton.reactor.Container`
+        for a list of the valid kwargs.
     """
 
     def __init__(self, url, timeout=None, container=None, ssl_domain=None, heartbeat=None, **kwargs):
@@ -249,10 +366,42 @@
                 self.close()
 
     def create_sender(self, address, handler=None, name=None, options=None):
+        """
+        Create a blocking sender.
+
+        :param address: Address of target node.
+        :type address: ``str``
+        :param handler: Event handler for this sender.
+        :type handler: Any child class of :class:`proton.Handler`
+        :param name: Sender name.
+        :type name: ``str``
+        :param options: A single option, or a list of sender options
+        :type options: :class:`SenderOption` or [SenderOption, SenderOption, ...]
+        :return: New blocking sender instance.
+        :rtype: :class:`BlockingSender`
+        """
         return BlockingSender(self, self.container.create_sender(self.conn, address, name=name, handler=handler,
                                                                  options=options))
 
     def create_receiver(self, address, credit=None, dynamic=False, handler=None, name=None, options=None):
+        """
+        Create a blocking receiver.
+
+        :param address: Address of source node.
+        :type address: ``str``
+        :param credit: Initial link flow credit. If not set, will default to 1.
+        :type credit: ``int``
+        :param dynamic: If ``True``, indicates dynamic creation of the receiver.
+        :type dynamic: ``bool``
+        :param handler: Event handler for this receiver.
+        :type handler: Any child class of :class:`proton.Handler`
+        :param name: Receiver name.
+        :type name: ``str``
+        :param options: A single option, or a list of receiver options
+        :type options: :class:`ReceiverOption` or [ReceiverOption, ReceiverOption, ...]
+        :return: New blocking receiver instance.
+        :rtype: :class:`BlockingReceiver`
+        """
         prefetch = credit
         if handler:
             fetcher = None
@@ -266,6 +415,9 @@
                                            options=options), fetcher, credit=prefetch)
 
     def close(self):
+        """
+        Close the connection.
+        """
         # TODO: provide stronger interrupt protection on cleanup.  See PEP 419
         if self.closing:
             return
@@ -289,13 +441,26 @@
         return self.conn.state & (Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED)
 
     def run(self):
-        """ Hand control over to the event loop (e.g. if waiting indefinitely for incoming messages) """
+        """
+        Hand control over to the event loop (e.g. if waiting indefinitely for incoming messages)
+        """
         while self.container.process(): pass
         self.container.stop()
         self.container.process()
 
     def wait(self, condition, timeout=False, msg=None):
-        """Call process until condition() is true"""
+        """
+        Process events until ``condition()`` returns ``True``.
+
+        :param condition: Condition which determines when the wait will end.
+        :type condition: Function which returns ``bool``
+        :param timeout: Timeout in seconds. If ``False``, the value of ``timeout`` used in the
+            constructor of this object will be used. If ``None``, there is no timeout. Any other
+            value is treated as a timeout in seconds.
+        :type timeout: ``None``, ``False``, ``float``
+        :param msg: Context message for :class:`proton.Timeout` exception
+        :type msg: ``str``
+        """
         if timeout is False:
             timeout = self.timeout
         if timeout is None:
@@ -322,12 +487,18 @@
                 "Connection %s disconnected: %s" % (self.url, self.disconnected))
 
     def on_link_remote_close(self, event):
+        """
+        Event callback for when the remote terminus closes.
+        """
         if event.link.state & Endpoint.LOCAL_ACTIVE:
             event.link.close()
             if not self.closing:
                 raise LinkDetached(event.link)
 
     def on_connection_remote_close(self, event):
+        """
+        Event callback for when the link peer closes the connection.
+        """
         if event.connection.state & Endpoint.LOCAL_ACTIVE:
             event.connection.close()
             if not self.closing:
@@ -361,22 +532,20 @@
 class SyncRequestResponse(IncomingMessageHandler):
     """
     Implementation of the synchronous request-response (aka RPC) pattern.
-    @ivar address: Address for all requests, may be None.
-    @ivar connection: Connection for requests and responses.
+    A single instance can send many requests to the same or different
+    addresses.
+
+    :param connection: Connection for requests and responses.
+    :type connection: :class:`BlockingConnection`
+    :param address: Address for all requests. If not specified, each request
+        must have the address property set. Successive messages may have
+        different addresses.
+    :type address: ``str`` or ``None``
     """
 
     correlation_id = AtomicCount()
 
     def __init__(self, connection, address=None):
-        """
-        Send requests and receive responses. A single instance can send many requests
-        to the same or different addresses.
-
-        @param connection: A L{BlockingConnection}
-        @param address: Address for all requests.
-            If not specified, each request must have the address property set.
-            Successive messages may have different addresses.
-        """
         super(SyncRequestResponse, self).__init__()
         self.connection = connection
         self.address = address
@@ -390,8 +559,9 @@
         """
         Send a request message, wait for and return the response message.
 
-        @param request: A L{proton.Message}. If L{self.address} is not set the 
-            L{self.address} must be set and will be used.
+        :param request: Request message. If ``self.address`` is not set the
+            request message address must be set and will be used.
+        :type request: :class:`proton.Message`
         """
         if not self.address and not request.address:
             raise ValueError("Request message has no address: %s" % request)
@@ -410,10 +580,19 @@
 
     @property
     def reply_to(self):
-        """Return the dynamic address of our receiver."""
+        """
+        The dynamic address of our receiver.
+
+        :type: ``str``
+        """
         return self.receiver.remote_source.address
 
     def on_message(self, event):
-        """Called when we receive a message for our receiver."""
+        """
+        Called when we receive a message for our receiver.
+
+        :param event: The event which occurs when a message is received.
+        :type event: :class:`proton.Event`
+        """
         self.response = event.message
         self.connection.container.yield_()  # Wake up the wait() loop to handle the message.
diff --git a/python/proton/reactor.py b/python/proton/reactor.py
index db1f826..2051fda 100644
--- a/python/proton/reactor.py
+++ b/python/proton/reactor.py
@@ -22,7 +22,7 @@
 from ._reactor import Container, ApplicationEvent, EventInjector, Handler,\
     LinkOption, ReceiverOption, SenderOption,\
     AtLeastOnce, AtMostOnce, DynamicNodeProperties, Filter, Selector, \
-    DurableSubscription, Copy, Move, Backoff
+    DurableSubscription, Copy, Move, Backoff, Transaction
 
 __all__ = [
     'Container',
@@ -40,5 +40,6 @@
     'DurableSubscription',
     'Copy',
     'Move',
-    'Backoff'
+    'Backoff',
+    'Transaction'
 ]
diff --git a/python/proton/utils.py b/python/proton/utils.py
index 270e534..fb514c6 100644
--- a/python/proton/utils.py
+++ b/python/proton/utils.py
@@ -19,10 +19,12 @@
 
 from __future__ import absolute_import
 
-from ._utils import BlockingConnection, SyncRequestResponse, SendException, LinkDetached, ConnectionClosed
+from ._utils import BlockingConnection, BlockingSender, BlockingReceiver, SyncRequestResponse, SendException, LinkDetached, ConnectionClosed
 
 __all__ = [
     'BlockingConnection',
+    'BlockingSender',
+    'BlockingReceiver',
     'SyncRequestResponse',
     'SendException',
     'LinkDetached',