[tor-commits] [stem/master] Update docstrings in stem/descriptor/remote.py

atagar at torproject.org atagar at torproject.org
Thu Jul 16 01:28:59 UTC 2020


commit 9310094a8844531aeadc53caa2df5ca503fb3d34
Author: Illia Volochii <illia.volochii at gmail.com>
Date:   Sun May 17 19:30:17 2020 +0300

    Update docstrings in stem/descriptor/remote.py
---
 stem/descriptor/remote.py | 213 ++++++++++++++++++++++++++++++++++++----------
 1 file changed, 167 insertions(+), 46 deletions(-)

diff --git a/stem/descriptor/remote.py b/stem/descriptor/remote.py
index 4e1ad034..d7a833a4 100644
--- a/stem/descriptor/remote.py
+++ b/stem/descriptor/remote.py
@@ -238,23 +238,18 @@ class AsyncQuery(object):
   advanced usage.
 
   To block on the response and get results either call
-  :func:`~stem.descriptor.remote.Query.run` or iterate over the Query. The
-  :func:`~stem.descriptor.remote.Query.run` method pass along any errors that
-  arise...
+  :func:`~stem.descriptor.remote.AsyncQuery.run` or iterate over the Query. The
+  :func:`~stem.descriptor.remote.AsyncQuery.run` method pass along any errors
+    that arise...
 
   ::
 
-    from stem.descriptor.remote import Query
-
-    query = Query(
-      '/tor/server/all',
-      timeout = 30,
-    )
+    from stem.descriptor.remote import AsyncQuery
 
     print('Current relays:')
 
     try:
-      for desc in Query('/tor/server/all', 'server-descriptor 1.0').run():
+      for desc in await AsyncQuery('/tor/server/all', 'server-descriptor 1.0').run():
         print(desc.fingerprint)
     except Exception as exc:
       print('Unable to retrieve the server descriptors: %s' % exc)
@@ -265,7 +260,7 @@ class AsyncQuery(object):
 
     print('Current relays:')
 
-    for desc in Query('/tor/server/all', 'server-descriptor 1.0'):
+    async for desc in AsyncQuery('/tor/server/all', 'server-descriptor 1.0'):
       print(desc.fingerprint)
 
   In either case exceptions are available via our 'error' attribute.
@@ -298,39 +293,6 @@ class AsyncQuery(object):
   For legacy reasons if our resource has a '.z' suffix then our **compression**
   argument is overwritten with Compression.GZIP.
 
-  .. versionchanged:: 1.7.0
-     Added support for downloading from ORPorts.
-
-  .. versionchanged:: 1.7.0
-     Added the compression argument.
-
-  .. versionchanged:: 1.7.0
-     Added the reply_headers attribute.
-
-     The class this provides changed between Python versions. In python2
-     this was called httplib.HTTPMessage, whereas in python3 the class was
-     renamed to http.client.HTTPMessage.
-
-  .. versionchanged:: 1.7.0
-     Avoid downloading from tor26. This directory authority throttles its
-     DirPort to such an extent that requests either time out or take on the
-     order of minutes.
-
-  .. versionchanged:: 1.7.0
-     Avoid downloading from Bifroest. This is the bridge authority so it
-     doesn't vote in the consensus, and apparently times out frequently.
-
-  .. versionchanged:: 1.8.0
-     Serge has replaced Bifroest as our bridge authority. Avoiding descriptor
-     downloads from it instead.
-
-  .. versionchanged:: 1.8.0
-     Defaulting to gzip compression rather than plaintext downloads.
-
-  .. versionchanged:: 1.8.0
-     Using :class:`~stem.descriptor.__init__.Compression` for our compression
-     argument.
-
   :var str resource: resource being fetched, such as '/tor/server/all'
   :var str descriptor_type: type of descriptors being fetched (for options see
     :func:`~stem.descriptor.__init__.parse_file`), this is guessed from the
@@ -562,7 +524,145 @@ class AsyncQuery(object):
 
 
 class Query(stem.util.AsyncClassWrapper):
-  def __init__(self, resource, descriptor_type = None, endpoints = None, compression = (Compression.GZIP,), retries = 2, fall_back_to_authority = False, timeout = None, start = True, block = False, validate = False, document_handler = stem.descriptor.DocumentHandler.ENTRIES, **kwargs):
+  """
+  Asynchronous request for descriptor content from a directory authority or
+  mirror. These can either be made through the
+  :class:`~stem.descriptor.remote.DescriptorDownloader` or directly for more
+  advanced usage.
+
+  To block on the response and get results either call
+  :func:`~stem.descriptor.remote.Query.run` or iterate over the Query. The
+  :func:`~stem.descriptor.remote.Query.run` method pass along any errors that
+  arise...
+
+  ::
+
+    from stem.descriptor.remote import Query
+
+    print('Current relays:')
+
+    try:
+      for desc in Query('/tor/server/all', 'server-descriptor 1.0').run():
+        print(desc.fingerprint)
+    except Exception as exc:
+      print('Unable to retrieve the server descriptors: %s' % exc)
+
+  ... while iterating fails silently...
+
+  ::
+
+    print('Current relays:')
+
+    for desc in Query('/tor/server/all', 'server-descriptor 1.0'):
+      print(desc.fingerprint)
+
+  In either case exceptions are available via our 'error' attribute.
+
+  Tor provides quite a few different descriptor resources via its directory
+  protocol (see section 4.2 and later of the `dir-spec
+  <https://gitweb.torproject.org/torspec.git/tree/dir-spec.txt>`_).
+  Commonly useful ones include...
+
+  =============================================== ===========
+  Resource                                        Description
+  =============================================== ===========
+  /tor/server/all                                 all present server descriptors
+  /tor/server/fp/<fp1>+<fp2>+<fp3>                server descriptors with the given fingerprints
+  /tor/extra/all                                  all present extrainfo descriptors
+  /tor/extra/fp/<fp1>+<fp2>+<fp3>                 extrainfo descriptors with the given fingerprints
+  /tor/micro/d/<hash1>-<hash2>                    microdescriptors with the given hashes
+  /tor/status-vote/current/consensus              present consensus
+  /tor/status-vote/current/consensus-microdesc    present microdescriptor consensus
+  /tor/status-vote/next/bandwidth                 bandwidth authority heuristics for the next consenus
+  /tor/status-vote/next/consensus-signatures      detached signature, used for making the next consenus
+  /tor/keys/all                                   key certificates for the authorities
+  /tor/keys/fp/<v3ident1>+<v3ident2>              key certificates for specific authorities
+  =============================================== ===========
+
+  **ZSTD** compression requires `zstandard
+  <https://pypi.org/project/zstandard/>`_, and **LZMA** requires the `lzma
+  module <https://docs.python.org/3/library/lzma.html>`_.
+
+  For legacy reasons if our resource has a '.z' suffix then our **compression**
+  argument is overwritten with Compression.GZIP.
+
+  .. versionchanged:: 1.7.0
+     Added support for downloading from ORPorts.
+
+  .. versionchanged:: 1.7.0
+     Added the compression argument.
+
+  .. versionchanged:: 1.7.0
+     Added the reply_headers attribute.
+
+     The class this provides changed between Python versions. In python2
+     this was called httplib.HTTPMessage, whereas in python3 the class was
+     renamed to http.client.HTTPMessage.
+
+  .. versionchanged:: 1.7.0
+     Avoid downloading from tor26. This directory authority throttles its
+     DirPort to such an extent that requests either time out or take on the
+     order of minutes.
+
+  .. versionchanged:: 1.7.0
+     Avoid downloading from Bifroest. This is the bridge authority so it
+     doesn't vote in the consensus, and apparently times out frequently.
+
+  .. versionchanged:: 1.8.0
+     Serge has replaced Bifroest as our bridge authority. Avoiding descriptor
+     downloads from it instead.
+
+  .. versionchanged:: 1.8.0
+     Defaulting to gzip compression rather than plaintext downloads.
+
+  .. versionchanged:: 1.8.0
+     Using :class:`~stem.descriptor.__init__.Compression` for our compression
+     argument.
+
+  :var str resource: resource being fetched, such as '/tor/server/all'
+  :var str descriptor_type: type of descriptors being fetched (for options see
+    :func:`~stem.descriptor.__init__.parse_file`), this is guessed from the
+    resource if **None**
+
+  :var list endpoints: :class:`~stem.DirPort` or :class:`~stem.ORPort` of the
+    authority or mirror we're querying, this uses authorities if undefined
+  :var list compression: list of :data:`stem.descriptor.Compression`
+    we're willing to accept, when none are mutually supported downloads fall
+    back to Compression.PLAINTEXT
+  :var int retries: number of times to attempt the request if downloading it
+    fails
+  :var bool fall_back_to_authority: when retrying request issues the last
+    request to a directory authority if **True**
+
+  :var str content: downloaded descriptor content
+  :var Exception error: exception if a problem occured
+  :var bool is_done: flag that indicates if our request has finished
+
+  :var float start_time: unix timestamp when we first started running
+  :var http.client.HTTPMessage reply_headers: headers provided in the response,
+    **None** if we haven't yet made our request
+  :var float runtime: time our query took, this is **None** if it's not yet
+    finished
+
+  :var bool validate: checks the validity of the descriptor's content if
+    **True**, skips these checks otherwise
+  :var stem.descriptor.__init__.DocumentHandler document_handler: method in
+    which to parse a :class:`~stem.descriptor.networkstatus.NetworkStatusDocument`
+  :var dict kwargs: additional arguments for the descriptor constructor
+
+  Following are only applicable when downloading from a
+  :class:`~stem.DirPort`...
+
+  :var float timeout: duration before we'll time out our request
+  :var str download_url: last url used to download the descriptor, this is
+    unset until we've actually made a download attempt
+
+  :param start: start making the request when constructed (default is **True**)
+  :param block: only return after the request has been completed, this is
+    the same as running **query.run(True)** (default is **False**)
+  """
+
+  def __init__(self, resource: str, descriptor_type: Optional[str] = None, endpoints: Optional[Sequence[stem.Endpoint]] = None, compression: Union[stem.descriptor._Compression, Sequence[stem.descriptor._Compression]] = (Compression.GZIP,), retries: int = 2, fall_back_to_authority: bool = False, timeout: Optional[float] = None, start: bool = True, block: bool = False, validate: bool = False, document_handler: stem.descriptor.DocumentHandler = stem.descriptor.DocumentHandler.ENTRIES, **kwargs: Any) -> None:
     self._thread_for_wrapped_class = stem.util.ThreadForWrappedAsyncClass()
     self._thread_for_wrapped_class.start()
     self._wrapped_instance: AsyncQuery = self._init_async_class(
@@ -582,9 +682,30 @@ class Query(stem.util.AsyncClassWrapper):
     )
 
   def start(self) -> None:
+    """
+    Starts downloading the scriptors if we haven't started already.
+    """
+
     self._call_async_method_soon('start')
 
-  def run(self, suppress = False):
+  def run(self, suppress: bool = False) -> List['stem.descriptor.Descriptor']:
+    """
+    Blocks until our request is complete then provides the descriptors. If we
+    haven't yet started our request then this does so.
+
+    :param suppress: avoids raising exceptions if **True**
+
+    :returns: list for the requested :class:`~stem.descriptor.__init__.Descriptor` instances
+
+    :raises:
+      Using the iterator can fail with the following if **suppress** is
+      **False**...
+
+        * **ValueError** if the descriptor contents is malformed
+        * :class:`~stem.DownloadTimeout` if our request timed out
+        * :class:`~stem.DownloadFailed` if our request fails
+    """
+
     return self._execute_async_method('run', suppress)
 
   def __iter__(self):





More information about the tor-commits mailing list