[tor-commits] [stem/master] Initial pass at the DescriptorDownloader

atagar at torproject.org atagar at torproject.org
Mon Jul 22 03:10:17 UTC 2013


commit 0b1c13553f842088fd5f5ae21600d28e25e6b633
Author: Damian Johnson <atagar at torproject.org>
Date:   Mon Jul 15 08:43:41 2013 -0700

    Initial pass at the DescriptorDownloader
    
    Implementation of the DescriptorDownloader's _query() helper method which will
    be the basis of its other methods. On reflection I should move retry
    fruntionality and probably caching down to the Query class.
---
 stem/descriptor/remote.py      |   60 +++++++++++++++++++++++++++++++++++++++-
 test/unit/descriptor/remote.py |    2 +-
 2 files changed, 60 insertions(+), 2 deletions(-)

diff --git a/stem/descriptor/remote.py b/stem/descriptor/remote.py
index 3db72ea..464e7cd 100644
--- a/stem/descriptor/remote.py
+++ b/stem/descriptor/remote.py
@@ -40,6 +40,7 @@ itself...
 """
 
 import io
+import random
 import sys
 import threading
 import time
@@ -194,4 +195,61 @@ class Query(object):
 
 
 class DescriptorDownloader(object):
-  pass
+  """
+  Configurable class through which descriptors can be downloaded. This provides
+  caching, retries, and other capabilities to make downloading descriptors easy
+  and efficient.
+
+  Queries can be made in either a blocking or non-blocking fashion. If
+  non-blocking then retries cannot be performed (since we do not know at the
+  time of the request if it succeeded or failed).
+
+  For more advanced use cases you can use the
+  :class:`~stem.descriptor.remote.Query` class directly.
+
+  :var bool block: blocks until requests have been concluded if **True**,
+    otherwise provides the query as soon as its been issued
+  :var int retries: number of times to attempt the request if it fails
+  :var float timeout: duration before we'll time out our request, no timeout is
+    applied if **None**
+  :var bool start_when_requested: issues requests when our methods are called
+    if **True**, otherwise provides non-running
+    :class:`~stem.descriptor.remote.Query` instances
+  :var bool fall_back_to_authority: when retrying request issues the last
+    request to a directory authority if **True**
+  """
+
+  def __init__(self, block = True, retries = 2, timeout = None, start_when_requested = True, fall_back_to_authority = True):
+    self.block = block
+    self.retries = retries
+    self.timeout = timeout
+    self.start_when_requested = start_when_requested
+    self.fall_back_to_authority = fall_back_to_authority
+    self._directories = DIRECTORY_AUTHORITIES.values()
+
+  def _query(self, resource, descriptor_type, retries):
+    """
+    Issues a request for the given resource.
+    """
+
+    if self.fall_back_to_authority and retries == 0:
+      address, dirport = random.choice(DIRECTORY_AUTHORITIES.values())
+    else:
+      address, dirport = random.choice(self._directories)
+
+    query = Query(
+      address,
+      dirport,
+      resource,
+      descriptor_type,
+      timeout = self.timeout,
+      start = self.start_when_requested,
+    )
+
+    if self.block:
+      query.run(True)
+
+      if query.error and retries > 0:
+        return self.query(resource, descriptor_type, retries - 1)
+
+    return query
diff --git a/test/unit/descriptor/remote.py b/test/unit/descriptor/remote.py
index 079937b..ab2276e 100644
--- a/test/unit/descriptor/remote.py
+++ b/test/unit/descriptor/remote.py
@@ -81,7 +81,7 @@ class TestDescriptorDownloader(unittest.TestCase):
     self.assertEqual('moria1', desc.nickname)
     self.assertEqual('128.31.0.34', desc.address)
     self.assertEqual('9695DFC35FFEB861329B9F1AB04C46397020CE31', desc.fingerprint)
-    self.assertEqual(TEST_DESCRIPTOR, desc.get_bytes())
+    self.assertEqual(TEST_DESCRIPTOR.strip(), desc.get_bytes())
 
     urlopen_mock.assert_called_once_with(expeced_url, timeout = None)
 





More information about the tor-commits mailing list