commit 0b1c13553f842088fd5f5ae21600d28e25e6b633 Author: Damian Johnson atagar@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)
tor-commits@lists.torproject.org