[tor-commits] [stem/master] Controller documentation vanished from the website

atagar at torproject.org atagar at torproject.org
Mon Nov 24 21:04:48 UTC 2014


commit 45fd74dddcd53b4b43b66aa682243066558dba80
Author: Damian Johnson <atagar at torproject.org>
Date:   Mon Nov 24 13:04:34 2014 -0800

    Controller documentation vanished from the website
    
    Our @with_defaults decorator broke Sphinx's automodule magic, causing the
    Controller's documentation to mostly vanish from our API docs.
    
    This includes two ingredients to fix...
    
     * Using functools.wrap() so our decorator doesn't hide the docstring. This got
       our documentation back but the signatures were still borked, reporting that
       everything was my_method(*args, *kwargs).
    
     * Explicitly define the method signatures. Trick courtesy of...
    
       https://stackoverflow.com/questions/3687046/python-sphinx-autodoc-and-decorated-members
---
 docs/change_log.rst |    2 ++
 stem/control.py     |   55 +++++++++++++++++++++++++++++++++++++++++++++------
 2 files changed, 51 insertions(+), 6 deletions(-)

diff --git a/docs/change_log.rst b/docs/change_log.rst
index 5a3ca34..30c01a1 100644
--- a/docs/change_log.rst
+++ b/docs/change_log.rst
@@ -101,6 +101,8 @@ among numerous other improvements and fixes.
   * The :func:`~stem.control.Controller.add_event_listener` method couldn't accept event types that Stem didn't already recognize
   * The :class:`~stem.exit_policy.ExitPolicy` class couldn't be pickled
   * Tor instances spawned with :func:`~stem.process.launch_tor` and :func:`~stem.process.launch_tor_with_config` could hang due to unread stdout content, we now close stdout and stderr once tor finishes bootstrapping (:trac:`9862`)
+  * The :func:`~stem.control.Controller.get_exit_policy` method errored if tor couldn't determine our external address
+  * The Controller's methods for retrieving descriptors could raise unexpected ValueErrors if tor didn't have any descriptors available
 
  * **Descriptors**
 
diff --git a/stem/control.py b/stem/control.py
index 1079629..431e360 100644
--- a/stem/control.py
+++ b/stem/control.py
@@ -221,6 +221,7 @@ If you're fine with allowing your script to raise exceptions then this can be mo
 
 import calendar
 import collections
+import functools
 import inspect
 import io
 import os
@@ -365,18 +366,19 @@ def with_default(yields = False):
 
   def decorator(func):
     def get_default(func, args, kwargs):
-      arg_names = inspect.getargspec(func).args
+      arg_names = inspect.getargspec(func).args[1:]  # drop 'self'
       default_position = arg_names.index('default') if 'default' in arg_names else None
 
-      if default_position and default_position < len(args):
+      if default_position is not None and default_position < len(args):
         return args[default_position]
       else:
         return kwargs.get('default', UNDEFINED)
 
     if not yields:
-      def wrapped(*args, **kwargs):
+      @functools.wraps(func)
+      def wrapped(self, *args, **kwargs):
         try:
-          return func(*args, **kwargs)
+          return func(self, *args, **kwargs)
         except Exception as exc:
           default = get_default(func, args, kwargs)
 
@@ -385,9 +387,10 @@ def with_default(yields = False):
           else:
             return default
     else:
-      def wrapped(*args, **kwargs):
+      @functools.wraps(func)
+      def wrapped(self, *args, **kwargs):
         try:
-          for val in func(*args, **kwargs):
+          for val in func(self, *args, **kwargs):
             yield val
         except Exception as exc:
           default = get_default(func, args, kwargs)
@@ -944,6 +947,8 @@ class Controller(BaseController):
   @with_default()
   def get_info(self, params, default = UNDEFINED, get_bytes = False):
     """
+    get_info(params, default = UNDEFINED, get_bytes = False)
+
     Queries the control socket for the given GETINFO option. If provided a
     default then that's returned if the GETINFO option is undefined or the
     call fails for any reason (error response, control port closed, initiated,
@@ -1064,6 +1069,8 @@ class Controller(BaseController):
   @with_default()
   def get_version(self, default = UNDEFINED):
     """
+    get_version(default = UNDEFINED)
+
     A convenience method to get tor version that current controller is
     connected to.
 
@@ -1090,6 +1097,8 @@ class Controller(BaseController):
   @with_default()
   def get_exit_policy(self, default = UNDEFINED):
     """
+    get_exit_policy(default = UNDEFINED)
+
     Effective ExitPolicy for our relay. This accounts for
     ExitPolicyRejectPrivate and default policies.
 
@@ -1127,6 +1136,8 @@ class Controller(BaseController):
   @with_default()
   def get_ports(self, listener_type, default = UNDEFINED):
     """
+    get_ports(listener_type, default = UNDEFINED)
+
     Provides the local ports where tor is listening for the given type of
     connections. This is similar to
     :func:`~stem.control.Controller.get_listeners`, but doesn't provide
@@ -1150,6 +1161,8 @@ class Controller(BaseController):
   @with_default()
   def get_listeners(self, listener_type, default = UNDEFINED):
     """
+    get_listeners(listener_type, default = UNDEFINED)
+
     Provides the addresses and ports where tor is listening for connections of
     the given type. This is similar to
     :func:`~stem.control.Controller.get_ports` but includes listener addresses
@@ -1238,6 +1251,8 @@ class Controller(BaseController):
   @with_default()
   def get_accounting_stats(self, default = UNDEFINED):
     """
+    get_accounting_stats(default = UNDEFINED)
+
     Provides stats related to our relaying limitations if AccountingMax was set
     in our torrc. This provides a **namedtuple** with the following
     attributes...
@@ -1311,6 +1326,8 @@ class Controller(BaseController):
   @with_default()
   def get_protocolinfo(self, default = UNDEFINED):
     """
+    get_protocolinfo(default = UNDEFINED)
+
     A convenience method to get the protocol info of the controller.
 
     :param object default: response if the query fails
@@ -1332,6 +1349,8 @@ class Controller(BaseController):
   @with_default()
   def get_user(self, default = UNDEFINED):
     """
+    get_user(default = UNDEFINED)
+
     Provides the user tor is running as. This often only works if tor is
     running locally. Also, most of its checks are platform dependent, and hence
     are not entirely reliable.
@@ -1363,6 +1382,8 @@ class Controller(BaseController):
   @with_default()
   def get_pid(self, default = UNDEFINED):
     """
+    get_pid(default = UNDEFINED)
+
     Provides the process id of tor. This often only works if tor is running
     locally. Also, most of its checks are platform dependent, and hence are not
     entirely reliable.
@@ -1415,6 +1436,8 @@ class Controller(BaseController):
   @with_default()
   def get_microdescriptor(self, relay = None, default = UNDEFINED):
     """
+    get_microdescriptor(relay = None, default = UNDEFINED)
+
     Provides the microdescriptor for the relay with the given fingerprint or
     nickname. If the relay identifier could be either a fingerprint *or*
     nickname then it's queried as a fingerprint.
@@ -1463,6 +1486,8 @@ class Controller(BaseController):
   @with_default(yields = True)
   def get_microdescriptors(self, default = UNDEFINED):
     """
+    get_microdescriptors(default = UNDEFINED)
+
     Provides an iterator for all of the microdescriptors that tor presently
     knows about.
 
@@ -1505,6 +1530,8 @@ class Controller(BaseController):
   @with_default()
   def get_server_descriptor(self, relay = None, default = UNDEFINED):
     """
+    get_server_descriptor(relay = None, default = UNDEFINED)
+
     Provides the server descriptor for the relay with the given fingerprint or
     nickname. If the relay identifier could be either a fingerprint *or*
     nickname then it's queried as a fingerprint.
@@ -1564,6 +1591,8 @@ class Controller(BaseController):
   @with_default(yields = True)
   def get_server_descriptors(self, default = UNDEFINED):
     """
+    get_server_descriptors(default = UNDEFINED)
+
     Provides an iterator for all of the server descriptors that tor presently
     knows about.
 
@@ -1609,6 +1638,8 @@ class Controller(BaseController):
   @with_default()
   def get_network_status(self, relay = None, default = UNDEFINED):
     """
+    get_network_status(relay = None, default = UNDEFINED)
+
     Provides the router status entry for the relay with the given fingerprint
     or nickname. If the relay identifier could be either a fingerprint *or*
     nickname then it's queried as a fingerprint.
@@ -1677,6 +1708,8 @@ class Controller(BaseController):
   @with_default(yields = True)
   def get_network_statuses(self, default = UNDEFINED):
     """
+    get_network_statuses(default = UNDEFINED)
+
     Provides an iterator for all of the router status entries that tor
     presently knows about.
 
@@ -2033,6 +2066,8 @@ class Controller(BaseController):
   @with_default()
   def get_hidden_service_conf(self, default = UNDEFINED):
     """
+    get_hidden_service_conf(default = UNDEFINED)
+
     This provides a mapping of hidden service directories to their
     attribute's key/value pairs. All hidden services are assured to have a
     'HiddenServicePort', but other entries may or may not exist.
@@ -2501,6 +2536,8 @@ class Controller(BaseController):
   @with_default()
   def get_circuit(self, circuit_id, default = UNDEFINED):
     """
+    get_circuit(circuit_id, default = UNDEFINED)
+
     Provides a circuit presently available from tor.
 
     :param int circuit_id: circuit to be fetched
@@ -2524,6 +2561,8 @@ class Controller(BaseController):
   @with_default()
   def get_circuits(self, default = UNDEFINED):
     """
+    get_circuits(default = UNDEFINED)
+
     Provides tor's currently available circuits.
 
     :param object default: response if the query fails
@@ -2706,6 +2745,8 @@ class Controller(BaseController):
   @with_default()
   def get_streams(self, default = UNDEFINED):
     """
+    get_streams(default = UNDEFINED)
+
     Provides the list of streams tor is currently handling.
 
     :param object default: response if the query fails
@@ -2843,6 +2884,8 @@ class Controller(BaseController):
   @with_default()
   def get_effective_rate(self, default = UNDEFINED, burst = False):
     """
+    get_effective_rate(default = UNDEFINED, burst = False)
+
     Provides the maximum rate this relay is configured to relay in bytes per
     second. This is based on multiple torrc parameters if they're set...
 



More information about the tor-commits mailing list