[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