..
authorShikhar Bhushan <shikhar@schmizz.net>
Sat, 11 Sep 2010 22:04:26 +0000 (23:04 +0100)
committerShikhar Bhushan <shikhar@schmizz.net>
Sat, 11 Sep 2010 22:04:26 +0000 (23:04 +0100)
18 files changed:
docs/source/capabilities.rst
docs/source/conf.py
docs/source/index.rst
docs/source/manager.rst
docs/source/operations.rst
docs/source/transport.rst
docs/source/xml_.rst
ncclient/capabilities.py
ncclient/manager.py
ncclient/operations/__init__.py
ncclient/operations/edit.py
ncclient/operations/lock.py
ncclient/operations/retrieve.py
ncclient/operations/rpc.py
ncclient/operations/session.py
ncclient/transport/session.py
ncclient/transport/ssh.py
ncclient/xml_.py

index f38a26c..98119c2 100644 (file)
@@ -6,4 +6,13 @@
 .. autofunction:: schemes
 
 .. autoclass:: Capabilities
-    :members:
\ No newline at end of file
+
+    :members:
+
+    .. describe:: ":cap" in caps
+
+        Check for the presence of capability. In addition to the URI, for capabilities of the form `urn:ietf:params:netconf:capability:$name:$version` their shorthand can be used as a key. For example, for `urn:ietf:params:netconf:capability:candidate:1.0` the shorthand would be `:candidate`. If version is significant, use `:candidate:1.0` as key.
+
+    .. describe:: iter(caps)
+
+        Return an iterator over the full URI's of capabilities represented by this object.
\ No newline at end of file
index d0d199b..0a1415e 100644 (file)
@@ -67,7 +67,7 @@ release = '0.2a'
 exclude_trees = []
 
 # The reST default role (used for this markup: `text`) to use for all documents.
-default_role = 'class' 
+#default_role = 'obj'
 
 # If true, '()' will be appended to :func: etc. cross-reference text.
 #add_function_parentheses = True
index 4ebf597..64fe8a1 100644 (file)
@@ -1,9 +1,7 @@
 Welcome
 =======
 
-``ncclient`` is a Python library for NETCONF clients. It aims to offer an intuitive API that
-sensibly maps the XML-encoded nature of NETCONF to Python constructs and idioms, and make writing
-network-management scripts easier. Other key features are:
+`ncclient` is a Python library for NETCONF clients. It aims to offer an intuitive API that sensibly maps the XML-encoded nature of NETCONF to Python constructs and idioms, and make writing network-management scripts easier. Other key features are:
 
 * Supports all operations and capabilities defined in :rfc:`4741`.
 * Request pipelining.
@@ -11,10 +9,9 @@ network-management scripts easier. Other key features are:
 * Keeping XML out of the way unless really needed.
 * Extensible. New transport mappings and capabilities/operations can be easily added.
 
-It is suitable for Python 2.6+ (not Python 3 yet, though), and depends on `paramiko
-<http://www.lag.net/paramiko/>`_, an SSH library.
+It is suitable for Python 2.6+ (not Python 3 yet, though), and depends on `paramiko <http://www.lag.net/paramiko/>`_, an SSH library.
 
-The best way to introduce is of course, through a simple code example::
+The best way to introduce is through a simple code example::
 
     from ncclient import manager
 
@@ -31,7 +28,6 @@ Contents:
     
     manager
     api
-    extending
 
 Indices and tables
 ------------------
index a387cdf..b718f05 100644 (file)
 .. automodule:: ncclient.manager
     :synopsis: High-level API
 
-Module data
------------
 
-These attributes control what capabilties are exchanged with the NETCONF server and what operations
-are available through the `Manager` API.
+Customizing
+------------
+
+These attributes control what capabilties are exchanged with the NETCONF server and what operations are available through the :class:`Manager` API.
 
 .. autodata:: OPERATIONS
 
 .. autodata:: CAPABILITIES
 
+
 Factory functions
 -----------------
 
-A `Manager` instance is created using a factory function.
+A :class:`Manager` instance is created using a factory function.
 
-.. autofunction:: connect_ssh(host[, port=830, timeout=None, unknown_host_cb=default_unknown_host_cb, username=None, password, key_filename=None, allow_agent=True, look_for_keys=True])
+.. autofunction:: connect_ssh
 
 .. autodata:: connect
 
 Manager
 -------
 
-Exposes an API for RPC operations as method calls. The return type of these methods depends on
-whether we are is in :attr:`asynchronous or synchronous mode <ncclient.manager.Manager.async_mode>`.
+Exposes an API for RPC operations as method calls. The return type of these methods depends on whether we are in :attr:`asynchronous or synchronous mode <ncclient.manager.Manager.async_mode>`.
 
-In synchronous mode replies are awaited and the corresponding `~ncclient.operations.RPCReply` object
-is returned. Depending on the :attr:`exception raising mode <ncclient.manager.Manager.raise_mode>`,
-an *rpc-error* in the reply may be raised as :exc:`RPCError` exceptions.
+In synchronous mode replies are awaited and the corresponding :class:`~ncclient.operations.RPCReply` object is returned. Depending on the :attr:`exception raising mode <ncclient.manager.Manager.raise_mode>`, an `rpc-error` in the reply may be raised as an :exc:`~ncclient.operations.RPCError` exception.
 
-However in asynchronous mode, operations return immediately with an `~ncclient.operations.RPC`
-object. Error handling and checking for whether a reply has been received must be dealt with
-manually. See the `~ncclient.operations.RPC` documentation for details.
+However in asynchronous mode, operations return immediately with the corresponding :class:`~ncclient.operations.RPC` object. Error handling and checking for whether a reply has been received must be dealt with manually. See the :class:`~ncclient.operations.RPC` documentation for details.
 
-Note that in case of the *get* and *get-config* operations, the reply is an instance of
-`~ncclient.operations.GetReply` which exposes the additional attributes
-:attr:`~ncclient.operations.GetReply.data` (as `~xml.etree.ElementTree.Element`) and
-:attr:`~ncclient.operations.GetReply.data_xml` (as `string`), which are of primary interest in case
-of these operations.
+Note that in case of the :meth:`~Manager.get` and :meth:`~Manager.get_config` operations, the reply is an instance of :class:`~ncclient.operations.GetReply` which exposes the additional attributes :attr:`~ncclient.operations.GetReply.data` (as :class:`~xml.etree.ElementTree.Element`) and :attr:`~ncclient.operations.GetReply.data_xml` (as a string), which are of primary interest in case of these operations.
 
-Presence of capabilities is verified to the extent possible, and you can expect a
-:exc:`~ncclient.operations.MissingCapabilityError` if something is amiss. In case of transport-layer
-errors, e.g. unexpected session close, :exc:`~ncclient.transport.TransportError` will be raised.
+Presence of capabilities is verified to the extent possible, and you can expect a :exc:`~ncclient.operations.MissingCapabilityError` if something is amiss. In case of transport-layer errors, e.g. unexpected session close, :exc:`~ncclient.transport.TransportError` will be raised.
 
-.. class:: Manager
-    
-    For details on the expected behavior of the operations and their parameters 
-    refer to :rfc:`4741`.
+.. autoclass:: Manager
 
-    Manager instances are also context managers so you can use it like this::
+    .. automethod:: get_config(source, filter=None)
 
-        with manager.connect("host") as m:
-            # do your stuff
-    
-    ... or like this::
-    
-        m = manager.connect("host")
-        try:
-            # do your stuff
-        finally:
-            m.close()
-    
-    .. method:: get_config(source[, filter=None])
-        
-        Retrieve all or part of a specified configuration.
-        
-        :param source: name of the configuration datastore being queried
-        :type source: `string`
-        
-        :param filter: portions of the device configuration to retrieve (by default entire configuration is retrieved)
-        :type filter: :ref:`filter_params`
-    
-    .. method:: edit_config(target, config[, default_operation=None, test_option=None, error_option=None])
-        
-        Loads all or part of a specified configuration to the specified target configuration.
-        
-        The ``"rollback-on-error"`` *error_option* depends on the ``:rollback-on-error`` capability.
-        
-        :param target: name of the configuration datastore being edited
-        :type target: `string`
-        
-        :param config: configuration (must be rooted in *<config> .. </config>*)
-        :type config: `string` or `~xml.etree.ElementTree.Element`
-        
-        :param default_operation: one of { ``"merge"``, ``"replace"``, or ``"none"`` }
-        :type default_operation: `string`
-        
-        :param test_option: one of { ``"test_then_set"``, ``"set"`` }
-        :type test_option: `string`
-        
-        :param error_option: one of { ``"stop-on-error"``, ``"continue-on-error"``, ``"rollback-on-error"`` }
-        :type error_option: `string`
-    
-    .. method:: copy_config(source, target)
-        
-        Create or replace an entire configuration datastore with the contents of another complete
-        configuration datastore. 
-        
-        :param source: configuration datastore to use as the source of the copy operation or *<config>* element containing the configuration subtree to copy
-        :type source: :ref:`srctarget_params`
-        
-        :param target: configuration datastore to use as the destination of the copy operation
-        :type target: :ref:`srctarget_params`
-    
-    .. method:: delete_config(target)
-        
-        Delete a configuration datastore.
-        
-        :param target: name or URL of configuration datastore to delete
-        :type: :ref:`srctarget_params`
-    
-    .. method:: lock(target)
-        
-        Allows the client to lock the configuration system of a device.
-        
-        :param target: name of the configuration datastore to lock
-        :type target: `string`
-        
-    .. method:: unlock(target)
-    
-        Release a configuration lock, previously obtained with the
-        :meth:`~ncclient.manager.Manager.lock` operation.
-        
-        :param target: name of the configuration datastore to unlock
-        :type target: `string`
-    
-    .. method:: locked(target)
-        
-        Returns a context manager for a lock on a datastore, e.g.::
-        
-            with m.locked("running"):
-                # do your stuff
+    .. automethod:: edit_config(target, config, default_operation=None, test_option=None, error_option=None)
 
-        ... instead of::
-        
-            m.lock("running")
-            try:
-                # do your stuff
-            finally:
-                m.unlock("running")
-        
-        :param target: name of configuration datastore to lock
-        :type target: `string`
-        
-        :rtype: `~ncclient.operations.LockContext`
-    
-    .. method:: get([filter=None])
-        
-        Retrieve running configuration and device state information.
-        
-        :param filter: portions of the device configuration to retrieve (by default entire configuration is retrieved)
-        :type filter: :ref:`filter_params`
-    
-    .. method:: close_session()
-        
-        Request graceful termination of the NETCONF session, and also close the transport.
-    
-    .. method:: kill_session(session_id)
-        
-        Force the termination of a NETCONF session (not the current one!).
-        
-        :param session_id: session identifier of the NETCONF session to be terminated
-        :type session_id: `string`
-    
-    .. method:: commit([confirmed=False, timeout=None])
-    
-        Commit the candidate configuration as the device's new current configuration. Depends on the
-        *:candidate* capability.
-        
-        A confirmed commit (i.e. if *confirmed* is :const:`True`) is reverted if there is no
-        followup commit within the *timeout* interval. If no timeout is specified the confirm
-        timeout defaults to 600 seconds (10 minutes). A confirming commit may have the *confirmed*
-        parameter but this is not required. Depends on the *:confirmed-commit* capability.
-        
-        :param confirmed: whether this is a confirmed commit
-        :type confirmed: `bool`
-        
-        :param timeout: confirm timeout in seconds
-        :type timeout: `int`
-    
-    .. method:: discard_changes()
-    
-        Revert the candidate configuration to the currently running configuration. Any uncommitted
-        changes are discarded.
-    
-    .. method:: validate(source)
-        
-        Validate the contents of the specified configuration.
-        
-        :param source: name of the configuration datastore being validated or *<config>* element containing the configuration subtree to be validated
-        :type source: :ref:`srctarget_params`
-    
-    .. attribute:: async_mode
-        
-        Specify whether operations are executed asynchronously (:const:`True`)
-        or synchronously (:const:`False`) (the default).
-    
-    .. attribute:: raise_mode
-        
-        Specify which errors are raised as :exc:`~ncclient.operations.RPCError` exceptions.
-        Valid values:
-        
-        * ``"all"`` -- any kind of *rpc-error* (error or warning)
-        * ``"errors"`` -- where the *error-type* element says it is an error
-        * ``"none"`` -- neither
+    .. automethod:: copy_config(source, target)
+
+    .. automethod:: delete_config(target)
+
+    .. automethod:: lock(target)
         
-    .. attribute:: client_capabilities
-    
-        `~ncclient.capabilities.Capabilities` object representing the client's capabilities.
-    
-    .. attribute:: server_capabilities
-    
-        `~ncclient.capabilities.Capabilities` object representing the server's capabilities.
-    
-    .. attribute:: session_id
-    
-        *session-id* assigned by the NETCONF server.
+    .. automethod:: unlock(target)
+
+    .. automethod:: locked(target)
+
+    .. automethod:: get()
     
-    .. attribute:: connected
-        
-        Bolean value indicating whether currently connected to the NETCONF server.
+    .. automethod:: close_session()
+
+    .. automethod:: kill_session(session_id)
+
+    .. automethod:: commit(confirmed=False, timeout=None)
+
+    .. automethod:: discard_changes()
+
+    .. automethod:: validate(source)
+
+    .. autoattribute:: async_mode
+
+    .. autoattribute:: raise_mode
+
+    .. autoattribute:: client_capabilities
+
+    .. autoattribute:: server_capabilities
+
+    .. autoattribute:: session_id
+
+    .. autoattribute:: connected
 
 
 Special kinds of parameters
@@ -236,13 +88,9 @@ Some parameters can take on different types to keep the interface simple.
 Source and target parameters
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-Where an method takes a *source* or *target* argument, usually a datastore name or URL is expected.
-The latter depends on the ``:url`` capability and on whether the specific URL scheme is supported.
-Either must be specified as a `string`. For example, ``"running"``,
-``"ftp://user:pass@host/config"``.
+Where an method takes a *source* or *target* argument, usually a datastore name or URL is expected. The latter depends on the `:url` capability and on whether the specific URL scheme is supported. Either must be specified as a string. For example, `"running"`, `"ftp://user:pass@host/config"`.
 
-If the source may be a *<config>* element, e.g. as allowed for the *validate* RPC, it can also be
-specified as an XML string or an `~xml.etree.ElementTree.Element` object.
+If the source may be a `config` element, e.g. as allowed for the `validate` RPC, it can also be specified as an XML string or an :class:`~xml.etree.ElementTree.Element` object.
 
 .. _filter_params:
 
@@ -251,12 +99,11 @@ Filter parameters
 
 Where a method takes a *filter* argument, it can take on the following types:
 
-* A ``tuple`` of *(type, criteria)*.
+* A tuple of *(type, criteria)*.
     
-    Here *type* has to be one of ``"xpath"`` or ``"subtree"``.
+    Here *type* has to be one of `"xpath"` or `"subtree"`.
     
-    * For ``"xpath"`` the *criteria* should be a `string` containing the XPath expression.
-    * For ``"subtree"`` the *criteria* should be an XML string or an
-      `~xml.etree.ElementTree.Element` object containing the criteria.
+    * For `"xpath"` the *criteria* should be a string containing the XPath expression.
+    * For `"subtree"` the *criteria* should be an XML string or an :class:`~xml.etree.ElementTree.Element` object containing the criteria.
 
-* A *<filter>* element as an XML string or an `~xml.etree.ElementTree.Element` object.
+* A `<filter>` element as an XML string or an :class:`~xml.etree.ElementTree.Element` object.
index 6cafa2a..85e121c 100644 (file)
@@ -1,17 +1,21 @@
 :mod:`~ncclient.operations` -- Everything RPC
 =============================================
 
-Base classes
-------------
 
 .. module:: ncclient.operations
     :synopsis: Everything RPC
 
-.. autoclass:: RPC(session[, async=False, timeout=None, raise_mode="none"])
+.. autoclass:: RaiseMode
+    :members: NONE, ERRORS, ALL
+
+Base classes
+------------
+
+.. autoclass:: RPC(session, async=False, timeout=None, raise_mode="none")
     :members: DEPENDS, REPLY_CLS, _assert, _request, request, event, error, reply, raise_mode, is_async, timeout
 
 .. autoclass:: RPCReply
-    :members: xml, ok, error, errors
+    :members: xml, ok, error, errors, _parsing_hook
 
 .. autoexception:: RPCError
     :show-inheritance:
@@ -20,11 +24,7 @@ Base classes
 Operations
 ----------
 
-*TODO*
-
-The operation classes are currently undocumented. See documentation of `~ncclient.manager.Manager`
-for methods that utilize the operation classes. The parameters accepted by :meth:`~RPC.request` for
-these classes are the same.
+The operation classes are currently undocumented. See documentation of :class:`~ncclient.manager.Manager` for methods that utilize the operation classes. The parameters accepted by :meth:`~RPC.request` for these classes are the same.
 
 Replies with data
 -----------------
index f08716b..ea45209 100644 (file)
@@ -22,7 +22,7 @@ SSH session implementation
     :show-inheritance:
     :members: load_known_hosts, close, transport
 
-    .. automethod:: connect(host[, port=830, timeout=None, username=None, password=None, key_filename=None, allow_agent=True, look_for_keys=True])
+    .. automethod:: connect(host[, port=830, timeout=None, unknown_host_cb=default_unknown_host_cb, username=None, password=None, key_filename=None, allow_agent=True, look_for_keys=True])
 
 Errors
 ------
@@ -40,5 +40,4 @@ Errors
     :show-inheritance:
 
 .. autoexception:: SSHUnknownHostError
-    :show-inheritance:
-
+    :show-inheritance:
\ No newline at end of file
index a74bde9..a5a84b1 100644 (file)
@@ -1,7 +1,7 @@
 :mod:`~ncclient.xml_` -- XML handling
 =====================================
 
-.. module:: ncclient.xml_
+.. automodule:: ncclient.xml_
     :synopsis: XML handling
 
 .. autoexception:: XMLError
@@ -20,10 +20,7 @@ Namespaces
 
 .. autodata:: FLOWMON_1_0
 
-.. function:: register_namespace(prefix, uri)
-    
-    ElementTree's namespace map determines the prefixes for namespace URI's when serializing to XML.
-    This method allows modifying this map to specify a prefix for a namespace URI.
+.. autofunction:: register_namespace(prefix, uri)
 
 .. autofunction:: qualify
 
@@ -36,6 +33,4 @@ Conversion
 
 .. autofunction:: parse_root
 
-.. autofunction:: validated_element
-
-.. 
\ No newline at end of file
+.. autofunction:: validated_element
\ No newline at end of file
index 30b1d75..f9b053f 100644 (file)
@@ -23,21 +23,12 @@ def _abbreviate(uri):
     return []
 
 def schemes(url_uri):
-    """Given a URI that has a *scheme* query string (i.e. *:url* capability URI), will return a list
-    of supported schemes.
-    """
+    "Given a URI that has a *scheme* query string (i.e. `:url` capability URI), will return a list of supported schemes."
     return url_uri.partition("?scheme=")[2].split(",")
 
 class Capabilities:
 
-    """Represents the set of capabilities available to a NETCONF client or server. It is initialized
-    with a list of capability URI's. These can be iterated over.
-    
-    Presence of a capability can be checked with the *in* operation. In addition to the URI, for
-    capabilities of the form *urn:ietf:params:netconf:capability:$name:$version* their shorthand can
-    be used as a key. For example, for *urn:ietf:params:netconf:capability:candidate:1.0* the
-    shorthand would be *:candidate*. If version is significant, use *:candidate:1.0* as key.
-    """
+    "Represents the set of capabilities available to a NETCONF client or server. It is initialized with a list of capability URI's."
     
     def __init__(self, capabilities):
         self._dict = {}
index 758d1d9..3671d06 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-"This module is a thin layer of abstraction around the library. It exposes all core functionality."
+"""This module is a thin layer of abstraction around the library. It exposes all core functionality."""
 
 import capabilities
 import operations
@@ -35,7 +35,7 @@ CAPABILITIES = [
     "urn:liberouter:params:netconf:capability:power-control:1.0"
     "urn:ietf:params:netconf:capability:interleave:1.0"
 ]
-"A list of URI's representing the client's capabilities. This is used during the initial capability exchange. Modify this if you need to announce some capability not already included."
+"""A list of URI's representing the client's capabilities. This is used during the initial capability exchange. Modify this if you need to announce some capability not already included."""
 
 OPERATIONS = {
     "get": operations.Get,
@@ -53,53 +53,12 @@ OPERATIONS = {
     "poweroff_machine": operations.PoweroffMachine,
     "reboot_machine": operations.RebootMachine
 }
-"""Dictionary of method names and corresponding `~ncclient.operations.RPC` subclasses. It is used to lookup operations, e.g. "get_config" is mapped to `~ncclient.operations.GetConfig`. It is thus possible to add additional operations to the `Manager` API."""
+"""Dictionary of method names and corresponding :class:`~ncclient.operations.RPC` subclasses. It is used to lookup operations, e.g. `get_config` is mapped to :class:`~ncclient.operations.GetConfig`. It is thus possible to add additional operations to the :class:`Manager` API."""
 
 def connect_ssh(*args, **kwds):
-    """Initializes a NETCONF session over SSH, and creates a connected `Manager` instance. *host* must be specified, all the other arguments are optional and depend on the kind of host key verification and user authentication you want to complete.
-        
-    For the purpose of host key verification, on -NIX systems a user's :file:`~/.ssh/known_hosts` file is automatically considered. The *unknown_host_cb* argument specifies a callback that will be invoked when the server's host key cannot be verified. See :func:`~ncclient.transport.ssh.default_unknown_host_cb` for function signature.
-    
-    First, ``publickey`` authentication is attempted. If a specific *key_filename* is specified, it
-    will be loaded and authentication attempted using it. If *allow_agent* is :const:`True` and an
-    SSH agent is running, the keys provided by the agent will be tried. If *look_for_keys* is
-    :const:`True`, keys in the :file:`~/.ssh/id_rsa` and :file:`~.ssh/id_dsa` will be tried. In case
-    an encrypted key file is encountered, the *password* argument will be used as a decryption
-    passphrase.
-    
-    If ``publickey`` authentication fails and the *password* argument has been supplied, ``password`` / ``keyboard-interactive`` SSH authentication will be attempted.
-    
-    :param host: hostname or address on which to connect
-    :type host: `string`
-    
-    :param port: port on which to connect
-    :type port: `int`
-    
-    :param timeout: timeout for socket connect
-    :type timeout: `int`
-    
-    :param unknown_host_cb: optional; callback that is invoked when host key verification fails
-    :type unknown_host_cb: `function`
-    
-    :param username: username to authenticate with, if not specified the username of the logged-in user is used
-    :type username: `string`
-    
-    :param password: password for ``password`` authentication or passphrase for decrypting private key files
-    :type password: `string`
-    
-    :param key_filename: location of a private key file on the file system
-    :type key_filename: `string`
-    
-    :param allow_agent: whether to try connecting to SSH agent for keys
-    :type allow_agent: `bool`
-    
-    :param look_for_keys: whether to look in usual locations for keys
-    :type look_for_keys: `bool`
-    
-    :raises: :exc:`~ncclient.transport.SSHUnknownHostError`
-    :raises: :exc:`~ncclient.transport.AuthenticationError`
-    
-    :rtype: `Manager`
+    """Initialize a :class:`Manager` over the SSH transport. For documentation of arguments see :meth:`ncclient.transport.SSHSession.connect`.
+
+    The underlying :class:`ncclient.transport.SSHSession` is created with :data:`CAPABILITIES`. It is first instructed to :meth:`~ncclient.transport.SSHSession.load_known_hosts` and then  all the provided arguments are passed directly to its implementation of :meth:`~ncclient.transport.SSHSession.connect`.
     """
     session = transport.SSHSession(capabilities.Capabilities(CAPABILITIES))
     session.load_known_hosts()
@@ -110,6 +69,7 @@ connect = connect_ssh
 "Same as :func:`connect_ssh`, since SSH is the default (and currently, the only) transport."
 
 class OpExecutor(type):
+
     def __new__(cls, name, bases, attrs):
         def make_wrapper(op_cls):
             def wrapper(self, *args, **kwds):
@@ -122,17 +82,29 @@ class OpExecutor(type):
 
 class Manager(object):
 
-    __metaclass__ = OpExecutor
+    """For details on the expected behavior of the operations and their parameters refer to :rfc:`4741`.
+
+    Manager instances are also context managers so you can use it like this::
+
+        with manager.connect("host") as m:
+            # do your stuff
 
-    RAISE_NONE = 0
-    RAISE_ERRORS = 1
-    RAISE_ALL = 2
+    ... or like this::
 
-    def __init__(self, session):
+        m = manager.connect("host")
+        try:
+            # do your stuff
+        finally:
+            m.close_session()
+    """
+
+    __metaclass__ = OpExecutor
+
+    def __init__(self, session, timeout=30):
         self._session = session
         self._async_mode = False
-        self._timeout = None
-        self._raise_mode = self.RAISE_ALL
+        self._timeout = timeout
+        self._raise_mode = operations.RaiseMode.ALL
 
     def __enter__(self):
         return self
@@ -141,6 +113,13 @@ class Manager(object):
         self.close_session()
         return False
 
+    def __set_async_mode(self, mode):
+        self._async_mode = mode
+
+    def __set_raise_mode(self, mode):
+        assert(choice in (operations.RaiseMode.NONE, operations.RaiseMode.ERRORS, operations.RaiseMode.ALL))
+        self._raise_mode = mode
+
     def execute(self, cls, *args, **kwds):
         return cls(self._session,
                    async=self._async_mode,
@@ -148,31 +127,44 @@ class Manager(object):
                    raise_mode=self._raise_mode).request(*args, **kwds)
 
     def locked(self, target):
+        """Returns a context manager for a lock on a datastore, where *target* is the name of the configuration datastore to lock, e.g.::
+
+            with m.locked("running"):
+                # do your stuff
+
+        ... instead of::
+
+            m.lock("running")
+            try:
+                # do your stuff
+            finally:
+                m.unlock("running")
+        """
         return operations.LockContext(self._session, target)
 
     @property
     def client_capabilities(self):
+        ":class:`~ncclient.capabilities.Capabilities` object representing the client's capabilities."
         return self._session._client_capabilities
 
     @property
     def server_capabilities(self):
+        ":class:`~ncclient.capabilities.Capabilities` object representing the server's capabilities."
         return self._session._server_capabilities
 
     @property
     def session_id(self):
+        "`session-id` assigned by the NETCONF server."
         return self._session.id
 
     @property
     def connected(self):
+        "Whether currently connected to the NETCONF server."
         return self._session.connected
 
-    def set_async_mode(self, mode):
-        self._async_mode = mode
-
-    def set_raise_mode(self, mode):
-        assert(choice in (self.RAISE_NONE, self.RAISE_ERRORS, self.RAISE_ALL))
-        self._raise_mode = mode
+    async_mode = property(fget=lambda self: self._async_mode, fset=__set_async_mode)
+    "Specify whether operations are executed asynchronously (`True`) or synchronously (`False`) (the default)."
 
-    async_mode = property(fget=lambda self: self._async_mode, fset=set_async_mode)
 
-    raise_mode = property(fget=lambda self: self._raise_mode, fset=set_raise_mode)
+    raise_mode = property(fget=lambda self: self._raise_mode, fset=__set_raise_mode)
+    "Specify which errors are raised as :exc:`~ncclient.operations.RPCError` exceptions. Valid values are the constants defined in :class:`~ncclient.operations.RaiseMode`. The default value is :attr:`~ncclient.operations.RaiseMode.ALL`."
index df50258..443188d 100644 (file)
@@ -13,7 +13,7 @@
 # limitations under the License.
 
 from errors import OperationError, TimeoutExpiredError, MissingCapabilityError
-from rpc import RPC, RPCReply, RPCError
+from rpc import RPC, RPCReply, RPCError, RaiseMode
 
 # rfc4741 ops
 from retrieve import Get, GetConfig, GetReply
@@ -27,6 +27,7 @@ __all__ = [
     'RPC',
     'RPCReply',
     'RPCError',
+    'RaiseMode',
     'Get',
     'GetConfig',
     'GetReply',
index 28e9cfb..9794bb4 100644 (file)
@@ -19,15 +19,29 @@ from rpc import RPC
 import util
 
 import logging
+
 logger = logging.getLogger("ncclient.operations.edit")
 
 "Operations related to changing device configuration"
 
 class EditConfig(RPC):
+    "`edit-config` RPC"
 
-    "*<edit-config>* RPC"
-    
     def request(self, target, config, default_operation=None, test_option=None, error_option=None):
+        """Loads all or part of the specified *config* to the *target* configuration datastore.
+
+        *target* is the name of the configuration datastore being edited
+
+        *config* is the configuration, which must be rooted in the `config` element. It can be specified either as a string or an :class:`~xml.etree.ElementTree.Element`.
+
+        *default_operation* if specified must be one of { `"merge"`, `"replace"`, or `"none"` }
+
+        *test_option* if specified must be one of { `"test_then_set"`, `"set"` }
+
+        *error_option* if specified must be one of { `"stop-on-error"`, `"continue-on-error"`, `"rollback-on-error"` }
+
+        The `"rollback-on-error"` *error_option* depends on the `:rollback-on-error` capability.
+        """
         node = new_ele("edit-config")
         node.append(util.datastore_or_url("target", target, self._assert))
         if error_option is not None:
@@ -38,27 +52,37 @@ class EditConfig(RPC):
             self._assert(':validate')
             sub_ele(node, "test-option").text = test_option
         if default_operation is not None:
-            # TODO: check if it is a valid default-operation
+        # TODO: check if it is a valid default-operation
             sub_ele(node, "default-operation").text = default_operation
         node.append(validated_element(config, ("config", qualify("config"))))
         return self._request(node)
 
 
 class DeleteConfig(RPC):
-
-    "*<delete-config>* RPC"
+    "`delete-config` RPC"
 
     def request(self, target):
+        """Delete a configuration datastore.
+
+        :param target: name or URL of configuration datastore to delete
+        :type: :ref:`srctarget_params`"""
         node = new_ele("delete-config")
         node.append(util.datastore_or_url("target", target, self._assert))
         return self._request(node)
 
 
 class CopyConfig(RPC):
+    "`copy-config` RPC"
 
-    "*<copy-config>* RPC"
-    
     def request(self, source, target):
+        """Create or replace an entire configuration datastore with the contents of another complete
+        configuration datastore.
+
+        :param source: configuration datastore to use as the source of the copy operation or `config` element containing the configuration subtree to copy
+        :type source: :ref:`srctarget_params`
+
+        :param target: configuration datastore to use as the destination of the copy operation
+        :type target: :ref:`srctarget_params`"""
         node = new_ele("copy-config")
         node.append(util.datastore_or_url("target", target, self._assert))
         node.append(util.datastore_or_url("source", source, self._assert))
@@ -66,12 +90,15 @@ class CopyConfig(RPC):
 
 
 class Validate(RPC):
-
-    "*<validate>* RPC. Depends on the *:validate* capability."
+    "`validate` RPC. Depends on the `:validate` capability."
 
     DEPENDS = [':validate']
 
     def request(self, source):
+        """Validate the contents of the specified configuration.
+
+        :param source: name of the configuration datastore being validated or `config` element containing the configuration subtree to be validated
+        :type source: :ref:`srctarget_params`"""
         node = new_ele("validate")
         try:
             src = validated_element(source, ("config", qualify("config")))
@@ -83,12 +110,20 @@ class Validate(RPC):
 
 
 class Commit(RPC):
-
-    "*<commit>* RPC. Depends on the *:candidate* capability, and the *:confirmed-commit* "
+    "`commit` RPC. Depends on the `:candidate` capability, and the `:confirmed-commit`."
 
     DEPENDS = [':candidate']
-    
+
     def request(self, confirmed=False, timeout=None):
+        """Commit the candidate configuration as the device's new current configuration. Depends on the `:candidate` capability.
+
+        A confirmed commit (i.e. if *confirmed* is `True`) is reverted if there is no followup commit within the *timeout* interval. If no timeout is specified the confirm timeout defaults to 600 seconds (10 minutes). A confirming commit may have the *confirmed* parameter but this is not required. Depends on the `:confirmed-commit` capability.
+
+        :param confirmed: whether this is a confirmed commit
+        :type confirmed: bool
+
+        :param timeout: confirm timeout in seconds
+        :type timeout: int"""
         node = new_ele("commit")
         if confirmed:
             self._assert(":confirmed-commit")
@@ -99,10 +134,10 @@ class Commit(RPC):
 
 
 class DiscardChanges(RPC):
-
-    "*<discard-changes>* RPC. Depends on the *:candidate* capability."
+    "`discard-changes` RPC. Depends on the `:candidate` capability."
 
     DEPENDS = [":candidate"]
 
     def request(self):
+        """Revert the candidate configuration to the currently running configuration. Any uncommitted changes are discarded."""
         return self._request(new_ele("discard-changes"))
\ No newline at end of file
index 94f9f29..13f5bdb 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-'Locking-related NETCONF operations'
+"Locking-related NETCONF operations"
 
 from ncclient.xml_ import *
 
-from rpc import RPC
+from rpc import RaiseMode, RPC
 
-# TODO:
-# should have some way to parse session-id from a lock-denied error, and raise
-# a tailored exception
+# TODO: parse session-id from a lock-denied error, and raise a tailored exception?
 
 class Lock(RPC):
 
-    "*<lock>* RPC"
+    "`lock` RPC"
     
     def request(self, target):
+        """Allows the client to lock the configuration system of a device.
+
+        *target* is the name of the configuration datastore to lock
+        """
         node = new_ele("lock")
         sub_ele(sub_ele(node, "target"), target)
         return self._request(node)
@@ -34,9 +36,13 @@ class Lock(RPC):
 
 class Unlock(RPC):
 
-    "*<unlock>* RPC"
+    "`unlock` RPC"
     
     def request(self, target):
+        """Release a configuration lock, previously obtained with the lock operation.
+
+        *target* is the name of the configuration datastore to unlock
+        """
         node = new_ele("unlock")
         sub_ele(sub_ele(node, "target"), target)
         return self._request(node)
@@ -44,13 +50,11 @@ class Unlock(RPC):
 
 class LockContext:
 
-    """
-    A context manager for the :class:`Lock` / :class:`Unlock` pair of RPC's.
-    
-    RPC errors are always raised as exceptions.
-    
-    Initialise with (:class:`Session <ncclient.transport.Session>`) instance
-    and lock target.
+    """A context manager for the :class:`Lock` / :class:`Unlock` pair of RPC's.
+
+    Any `rpc-error` will be raised as an exception.
+
+    Initialise with (:class:`Session <ncclient.transport.Session>`) instance and lock target.
     """
 
     def __init__(self, session, target):
@@ -58,9 +62,9 @@ class LockContext:
         self.target = target
 
     def __enter__(self):
-        Lock(self.session).request(self.target)
+        Lock(self.session, raise_mode=RaiseMode.ERRORS).request(self.target)
         return self
 
     def __exit__(self, *args):
-        Unlock(self.session).request(self.target)
+        Unlock(self.session, raise_mode=RaiseMode.ERRORS).request(self.target)
         return False
index 90a0f9c..9d3d728 100644 (file)
@@ -30,7 +30,7 @@ class GetReply(RPCReply):
     
     @property
     def data_ele(self):
-        "*data* element as an `~xml.etree.ElementTree.Element`"
+        "*data* element as an :class:`~xml.etree.ElementTree.Element`"
         if not self._parsed:
             self.parse()
         return self._data
@@ -53,6 +53,11 @@ class Get(RPC):
     REPLY_CLS = GetReply
 
     def request(self, filter=None):
+        """Retrieve running configuration and device state information.
+
+        :param filter: portions of the device configuration to retrieve (by default entire configuration is retrieved)
+        :type filter: :ref:`filter_params`
+        """
         node = new_ele("get")
         if filter is not None:
             node.append(util.build_filter(filter))
@@ -66,6 +71,13 @@ class GetConfig(RPC):
     REPLY_CLS = GetReply
 
     def request(self, source, filter=None):
+        """Retrieve all or part of a specified configuration.
+
+        :param source: name of the configuration datastore being queried
+        :type source: string
+
+        :param filter: portions of the device configuration to retrieve (by default entire configuration is retrieved)
+        :type filter: :ref:`filter_params`"""
         node = new_ele("get-config")
         node.append(util.datastore_or_url("source", source, self._assert))
         if filter is not None:
index fd71602..0e7200e 100644 (file)
@@ -26,8 +26,7 @@ logger = logging.getLogger("ncclient.operations.rpc")
 
 class RPCError(OperationError):
 
-    """Represents an *rpc-error*. It is a type of :exc:`OperationError` and can be raised like any
-    other exception."""
+    "Represents an `rpc-error`. It is a type of :exc:`OperationError` and can be raised as such."
     
     tag_to_attr = {
         qualify("error-type"): "_type",
@@ -56,37 +55,37 @@ class RPCError(OperationError):
     
     @property
     def xml(self):
-        "*rpc-error* element as returned."
+        "The `rpc-error` element as returned in XML."
         return self._raw
     
     @property
     def type(self):
-        "`string` representing text of *error-type* element."
+        "The contents of the `error-type` element."
         return self._type
     
     @property
     def tag(self):
-        "`string` representing text of *error-tag* element."
+        "The contents of the `error-tag` element."
         return self._tag
     
     @property
     def severity(self):
-        "`string` representing text of *error-severity* element."
+        "The contents of the `error-severity` element."
         return self._severity
     
     @property
     def path(self):
-        "`string` or :const:`None`; representing text of *error-path* element."
+        "The contents of the `error-path` element if present or `None`."
         return self._path
     
     @property
     def message(self):
-        "`string` or :const:`None`; representing text of *error-message* element."
+        "The contents of the `error-message` element if present or `None`."
         return self._message
     
     @property
     def info(self):
-        "`string` (XML) or :const:`None`; representing *error-info* element."
+        "XML string or `None`; representing the `error-info` element."
         return self._info
 
 
@@ -128,6 +127,7 @@ class RPCReply:
         self._parsed = True
 
     def _parsing_hook(self, root):
+        "No-op by default. Gets given the *root* element."
         pass
     
     @property
@@ -142,7 +142,7 @@ class RPCReply:
     
     @property
     def error(self):
-        "Returns the first `RPCError` and :const:`None` if there were no errors."
+        "Returns the first :class:`RPCError` and `None` if there were no errors."
         self.parse()
         if self._errors:
             return self._errors[0]
@@ -151,8 +151,7 @@ class RPCReply:
     
     @property
     def errors(self):
-        """`list` of `RPCError` objects. Will be empty if there were no *rpc-error* elements in
-        reply."""
+        "List of `RPCError` objects. Will be empty if there were no *rpc-error* elements in reply."
         self.parse()
         return self._errors
 
@@ -207,21 +206,31 @@ class RPCReplyListener(SessionListener): # internal use
             self._id2rpc.clear()
 
 
+class RaiseMode(object):
+
+    NONE = 0
+    "Don't attempt to raise any type of `rpc-error` as :exc:`RPCError`."
+
+    ERRORS = 1
+    "Raise only when the `error-type` indicates it is an honest-to-god error."
+
+    ALL = 2
+    "Don't look at the `error-type`, always raise."
+
+
 class RPC(object):
     
     """Base class for all operations, directly corresponding to *rpc* requests. Handles making the
     request, and taking delivery of the reply."""
-    
+
     DEPENDS = []
-    """Subclasses can specify their dependencies on capabilities. List of URI's or abbreviated
-    names, e.g. ':writable-running'. These are verified at the time of instantiation. If the
-    capability is not available, a :exc:`MissingCapabilityError` is raised.
+    """Subclasses can specify their dependencies on capabilities. List of URI's or abbreviated names, e.g. ':writable-running'. These are verified at the time of instantiation. If the capability is not available, a :exc:`MissingCapabilityError` is raised.
     """
     
     REPLY_CLS = RPCReply
     "Subclasses can specify a different reply class, but it should be a subclass of `RPCReply`."
     
-    def __init__(self, session, async=False, timeout=None, raise_mode="none"):
+    def __init__(self, session, async=False, timeout=30, raise_mode=RaiseMode.NONE):
         self._session = session
         try:
             for cap in self.DEPENDS:
@@ -245,18 +254,13 @@ class RPC(object):
         return to_xml(ele)
 
     def _request(self, op):
-        """Implementations of :meth:`request` call this method to send the request and process the
-        reply.
+        """Implementations of :meth:`request` call this method to send the request and process the reply.
         
-        In synchronous mode, blocks until the reply is received and returns `RPCReply`. Depending on
-        the :attr:`raise_mode` a *rpc-error* element in the reply may lead to an :exc:`RPCError`
-        exception.
+        In synchronous mode, blocks until the reply is received and returns :class:`RPCReply`. Depending on the :attr:`raise_mode` a `rpc-error` element in the reply may lead to an :exc:`RPCError` exception.
         
-        In asynchronous mode, returns immediately, returning *self*. The :attr:`event` attribute
-        will be set when the reply has been received (see :attr:`reply`) or an error occured (see
-        :attr:`error`).
+        In asynchronous mode, returns immediately, returning *self*. The :attr:`event` attribute will be set when the reply has been received (see :attr:`reply`) or an error occured (see :attr:`error`).
         
-        :param op: operation to be requested
+        :param op: operation to b\e requested
         :type ops: `~xml.etree.ElementTree.Element`
         
         :rtype: `RPCReply` (sync) or `RPC` (async)
@@ -277,10 +281,9 @@ class RPC(object):
                 self._reply.parse()
                 if self._reply.error is not None:
                     # <rpc-error>'s [ RPCError ]
-                    if self._raise_mode == "all":
+                    if self._raise_mode == RaiseMode.ALL:
                         raise self._reply.error
-                    elif (self._raise_mode == "errors" and
-                          self._reply.error.type == "error"):
+                    elif (self._raise_mode == RaiseMode.ERRORS and self._reply.error.type == "error"):
                         raise self._reply.error
                 return self._reply
             else:
@@ -311,12 +314,12 @@ class RPC(object):
     
     @property
     def reply(self):
-        "`RPCReply` element if reply has been received or :const:`None`"
+        ":class:`RPCReply` element if reply has been received or `None`"
         return self._reply
     
     @property
     def error(self):
-        """:exc:`Exception` type if an error occured or :const:`None`.
+        """:exc:`Exception` type if an error occured or `None`.
         
         .. note::
             This represents an error which prevented a reply from being received. An *rpc-error*
@@ -341,36 +344,26 @@ class RPC(object):
         """
         return self._event
 
-    def set_async(self, async=True):
+    def __set_async(self, async=True):
         self._async = async
         if async and not session.can_pipeline:
             raise UserWarning('Asynchronous mode not supported for this device/session')
 
-    def set_raise_mode(self, mode):
+    def __set_raise_mode(self, mode):
         assert(choice in ("all", "errors", "none"))
         self._raise_mode = mode
 
-    def set_timeout(self, timeout):
+    def __set_timeout(self, timeout):
         self._timeout = timeout
 
-    raise_mode = property(fget=lambda self: self._raise_mode, fset=set_raise_mode)
-    """Depending on this exception raising mode, an *rpc-error* in the reply may be raised as
-    :exc:`RPCError` exceptions. Valid values:
+    raise_mode = property(fget=lambda self: self._raise_mode, fset=__set_raise_mode)
+    """Depending on this exception raising mode, an `rpc-error` in the reply may be raised as an :exc:`RPCError` exception. Valid values are the constants defined in :class:`RaiseMode`. """
     
-    * ``"all"`` -- any kind of *rpc-error* (error or warning)
-    * ``"errors"`` -- when the *error-type* element says it is an error
-    * ``"none"`` -- neither
-    """
-    
-    is_async = property(fget=lambda self: self._async, fset=set_async)
-    """Specifies whether this RPC will be / was requested asynchronously. By default RPC's are
-    synchronous.
-    """
+    is_async = property(fget=lambda self: self._async, fset=__set_async)
+    """Specifies whether this RPC will be / was requested asynchronously. By default RPC's are synchronous. """
     
-    timeout = property(fget=lambda self: self._timeout, fset=set_timeout)
-    """Timeout in seconds for synchronous waiting defining how long the RPC request will block on a
-    reply before raising :exc:`TimeoutExpiredError`. By default there is no timeout, represented by
-    :const:`None`.
+    timeout = property(fget=lambda self: self._timeout, fset=__set_timeout)
+    """Timeout in seconds for synchronous waiting defining how long the RPC request will block on a reply before raising :exc:`TimeoutExpiredError`.
     
     Irrelevant for asynchronous usage.
     """
index a06be6f..0afa307 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-'Session-related NETCONF operations'
+"Session-related NETCONF operations"
 
 from ncclient.xml_ import *
 
@@ -20,9 +20,10 @@ from rpc import RPC
 
 class CloseSession(RPC):
 
-    "*<close-session>* RPC. The connection to NETCONF server is also closed."
+    "`close-session` RPC. The connection to NETCONF server is also closed."
 
     def request(self):
+        "Request graceful termination of the NETCONF session, and also close the transport."
         try:
             return self._request(new_ele("close-session"))
         finally:
@@ -31,15 +32,13 @@ class CloseSession(RPC):
 
 class KillSession(RPC):
 
-    "*<kill-session>* RPC."
-    
+    "`kill-session` RPC."
+
     def request(self, session_id):
-        """
-        :arg session_id: *session-id* of NETCONF session to kill
-        :type session_id: `string`
+        """Force the termination of a NETCONF session (not the current one!)
+
+        *session_id* is the session identifier of the NETCONF session to be terminated as a string
         """
         node = new_ele("kill-session")
-        if not isinstance(session_id, basestring): # make sure
-            session_id = str(session_id)
         sub_ele(node, "session-id").text = session_id
         return self._request(node)
index 570fd47..d6d3ede 100644 (file)
@@ -131,12 +131,7 @@ class Session(Thread):
         raise NotImplementedError
 
     def send(self, message):
-        """Send the supplied *message* to NETCONF server.
-
-        :arg message: an XML document
-
-        :type message: `string`
-        """
+        """Send the supplied *message* (xml string) to NETCONF server."""
         if not self.connected:
             raise TransportError('Not connected to NETCONF server')
         logger.debug('queueing %s' % message)
@@ -161,8 +156,7 @@ class Session(Thread):
 
     @property
     def id(self):
-        """A `string` representing the `session-id`. If the session has not
-        been initialized it will be :const:`None`"""
+        """A string representing the `session-id`. If the session has not been initialized it will be `None`"""
         return self._id
 
 
@@ -176,15 +170,11 @@ class SessionListener(object):
     """
 
     def callback(self, root, raw):
-        """Called when a new XML document is received. The `root` argument
-        allows the callback to determine whether it wants to further process the
-        document.
+        """Called when a new XML document is received. The *root* argument allows the callback to determine whether it wants to further process the document.
 
-        :arg root: tuple of `(tag, attributes)` where `tag` is the qualified name of the root element and `attributes` is a dictionary of its attributes (also qualified names)
-        :type root: `tuple`
+        Here, *root* is a tuple of *(tag, attributes)* where *tag* is the qualified name of the root element and *attributes* is a dictionary of its attributes (also qualified names).
 
-        :arg raw: XML document
-        :type raw: `string`
+        *raw* will contain the XML document as a string.
         """
         raise NotImplementedError
 
index 2a69c86..880b42f 100644 (file)
@@ -32,19 +32,15 @@ MSG_DELIM = "]]>]]>"
 TICK = 0.1
 
 def default_unknown_host_cb(host, fingerprint):
-    """An `unknown host callback` returns :const:`True` if it finds the key acceptable, and
-    :const:`False` if not.
+    """An unknown host callback returns `True` if it finds the key acceptable, and `False` if not.
 
-    This default callback always returns :const:`False`, which would lead to :meth:`connect` raising
-    a :exc:`SSHUnknownHost` exception.
+    This default callback always returns `False`, which would lead to :meth:`connect` raising a :exc:`SSHUnknownHost` exception.
     
     Supply another valid callback if you need to verify the host key programatically.
 
-    :arg host: the hostname that needs to be verified
-    :type host: `string`
+    *host* is the hostname that needs to be verified
 
-    :arg fingerprint: a hex string representing the host key fingerprint, colon-delimited e.g. *4b:69:6c:72:6f:79:20:77:61:73:20:68:65:72:65:21*
-    :type fingerprint: `string`
+    *fingerprint* is a hex string representing the host key fingerprint, colon-delimited e.g. `"4b:69:6c:72:6f:79:20:77:61:73:20:68:65:72:65:21"`
     """
     return False
 
@@ -70,11 +66,7 @@ class SSHSession(Session):
         self._parsing_pos = 0
     
     def _parse(self):
-        """Messages ae delimited by MSG_DELIM. The buffer could have grown by a
-        maximum of BUF_SIZE bytes everytime this method is called. Retains state
-        across method calls and if a byte has been read it will not be
-        considered again.
-        """
+        "Messages ae delimited by MSG_DELIM. The buffer could have grown by a maximum of BUF_SIZE bytes everytime this method is called. Retains state across method calls and if a byte has been read it will not be considered again."
         delim = MSG_DELIM
         n = len(delim) - 1
         expect = self._parsing_state
@@ -115,10 +107,9 @@ class SSHSession(Session):
         self._parsing_pos = self._buffer.tell()
 
     def load_known_hosts(self, filename=None):
-        """Load host keys from a :file:`known_hosts`-style file. Can be called multiple times.
+        """Load host keys from an openssh :file:`known_hosts`-style file. Can be called multiple times.
 
-        If *filename* is not specified, looks in the default locations i.e.
-        :file:`~/.ssh/known_hosts` and :file:`~/ssh/known_hosts` for Windows.
+        If *filename* is not specified, looks in the default locations i.e. :file:`~/.ssh/known_hosts` and :file:`~/ssh/known_hosts` for Windows.
         """
         if filename is None:
             filename = os.path.expanduser('~/.ssh/known_hosts')
@@ -139,44 +130,40 @@ class SSHSession(Session):
             self._transport.close()
         self._connected = False
 
-    def connect(self, host, port=830, timeout=None,
-                unknown_host_cb=default_unknown_host_cb,
-                username=None, password=None,
-                key_filename=None, allow_agent=True, look_for_keys=True):
-        """Connect via SSH and initialize the NETCONF session. First attempts the publickey
-        authentication method and then password authentication.
+    # REMEMBER to update transport.rst if sig. changes, since it is hardcoded there
+    def connect(self, host, port=830, timeout=None, unknown_host_cb=default_unknown_host_cb,
+                username=None, password=None, key_filename=None, allow_agent=True, look_for_keys=True):
+        """Connect via SSH and initialize the NETCONF session. First attempts the publickey authentication method and then password authentication.
 
-        To disable attemting publickey authentication altogether, call with *allow_agent* and
-        *look_for_keys* as :const:`False`.
+        To disable attempting publickey authentication altogether, call with *allow_agent* and *look_for_keys* as `False`.
 
         :arg host: the hostname or IP address to connect to
-        :type host: `string`
+        :type host: string
 
         :arg port: by default 830, but some devices use the default SSH port of 22 so this may need to be specified
-        :type port: `int`
+        :type port: int
 
         :arg timeout: an optional timeout for socket connect
-        :type timeout: `int`
+        :type timeout: int
 
         :arg unknown_host_cb: called when the server host key is not recognized
-        :type unknown_host_cb: see :meth:`signature <ssh.default_unknown_host_cb>`
+        :type unknown_host_cb: see the signature of :func:`default_unknown_host_cb`
 
         :arg username: the username to use for SSH authentication
-        :type username: `string`
+        :type username: string
 
         :arg password: the password used if using password authentication, or the passphrase to use for unlocking keys that require it
-        :type password: `string`
+        :type password: string
 
         :arg key_filename: a filename where a the private key to be used can be found
-        :type key_filename: `string`
+        :type key_filename: string
 
         :arg allow_agent: enables querying SSH agent (if found) for keys
-        :type allow_agent: `bool`
+        :type allow_agent: bool
 
         :arg look_for_keys: enables looking in the usual locations for ssh keys (e.g. :file:`~/.ssh/id_*`)
-        :type look_for_keys: `bool`
+        :type look_for_keys: bool
         """
-
         if username is None:
             username = getpass.getuser()
         
@@ -306,13 +293,9 @@ class SSHSession(Session):
         q = self._q
         try:
             while True:
-                # select on a paramiko ssh channel object does not ever return
-                # it in the writable list, so it channel's don't exactly emulate
-                # the socket api
+                # select on a paramiko ssh channel object does not ever return it in the writable list, so channels don't exactly emulate the socket api
                 r, w, e = select([chan], [], [], TICK)
-                # will wakeup evey TICK seconds to check if something
-                # to send, more if something to read (due to select returning
-                # chan in readable list)
+                # will wakeup evey TICK seconds to check if something to send, more if something to read (due to select returning chan in readable list)
                 if r:
                     data = chan.recv(BUF_SIZE)
                     if data:
@@ -335,8 +318,5 @@ class SSHSession(Session):
 
     @property
     def transport(self):
-        """Underlying `paramiko.Transport
-        <http://www.lag.net/paramiko/docs/paramiko.Transport-class.html>`_
-        object. This makes it possible to call methods like set_keepalive on it.
-        """
+        "Underlying `paramiko.Transport <http://www.lag.net/paramiko/docs/paramiko.Transport-class.html>`_ object. This makes it possible to call methods like set_keepalive on it."
         return self._transport
index 7867b60..fef072e 100644 (file)
@@ -41,6 +41,7 @@ except AttributeError:
         from xml.etree import ElementTree
         # cElementTree uses ElementTree's _namespace_map, so that's ok
         ElementTree._namespace_map[uri] = prefix
+register_namespace.func_doc = "ElementTree's namespace map determines the prefixes for namespace URI's when serializing to XML. This method allows modifying this map to specify a prefix for a namespace URI."
 
 for (ns, pre) in {
     BASE_NS_1_0: 'nc',
@@ -51,41 +52,19 @@ for (ns, pre) in {
 }.items(): register_namespace(pre, ns)
 
 qualify = lambda tag, ns=BASE_NS_1_0: tag if ns is None else "{%s}%s" % (ns, tag)
-"""Qualify a tag name with a namespace, in :mod:`~xml.etree.ElementTree` fashion i.e. *{namespace}tagname*.
-
-:arg tag: name of the tag
-:type arg: `string`
-
-:arg ns: namespace to qualify with
-:type ns: `string`
-"""
+"""Qualify a *tag* name with a *namespace*, in :mod:`~xml.etree.ElementTree` fashion i.e. *{namespace}tagname*."""
 
 def to_xml(ele, encoding="UTF-8"):
-    """Convert an `~xml.etree.ElementTree.Element` to XML.
-    
-    :arg ele: the `~xml.etree.ElementTree.Element`
-    :arg encoding: character encoding
-    :rtype: `string`
-    """
+    "Convert and return the XML for an *ele* (:class:`~xml.etree.ElementTree.Element`) with specified *encoding*."
     xml = ET.tostring(ele, encoding)
     return xml if xml.startswith('<?xml') else '<?xml version="1.0" encoding="%s"?>%s' % (encoding, xml)
 
 def to_ele(x):
-    """Convert XML to `~xml.etree.ElementTree.Element`. If passed an `~xml.etree.ElementTree.Element` simply returns that.
-    
-    :arg x: the XML document or element
-    :type x: `string` or `~xml.etree.ElementTree.Element`
-    :rtype: `~xml.etree.ElementTree.Element`
-    """
+    "Convert and return the :class:`~xml.etree.ElementTree.Element` for the XML document *x*. If *x* is already an :class:`~xml.etree.ElementTree.Element` simply returns that."
     return x if ET.iselement(x) else ET.fromstring(x)
 
 def parse_root(raw):
-    """Efficiently parses the root element of an XML document.
-
-    :arg raw: XML document
-    :returns: a tuple of ``(tag, attrib)``, where *tag* is the (qualified) name of the element and *attrib* is a dictionary of its attributes.
-    :rtype: `tuple`
-    """
+    "Efficiently parses the root element of a *raw* XML document, returning a tuple of its qualified name and attribute dictionary."
     fp = StringIO(raw)
     for event, element in ET.iterparse(fp, events=('start',)):
         return (element.tag, element.attrib)
@@ -93,13 +72,11 @@ def parse_root(raw):
 def validated_element(x, tags=None, attrs=None):
     """Checks if the root element of an XML document or Element meets the supplied criteria.
     
-    :arg tags: allowable tag name or sequence of allowable alternatives
-    :type tags: `string` or sequence of strings
-    
-    :arg attrs: list of required attributes, each of which may be a sequence of several allowable alternatives
-    :type attrs: sequence of strings or sequence of sequences of strings
-    
-    :raises: `XMLError` if the requirements are not met
+    *tags* if specified is either a single allowable tag name or sequence of allowable alternatives
+
+    *attrs* if specified is a sequence of required attributes, each of which may be a sequence of several allowable alternatives
+
+    Raises :exc:`XMLError` if the requirements are not met.
     """
     ele = to_ele(x)
     if tags: