commit 159ae8864b7bbe2d3f03ae0e90d488d34d689fd1 Author: Damian Johnson atagar@torproject.org Date: Mon Jan 28 16:18:08 2019 -0800
Handle new @type annotations
Thanks to Karsten we've settled on @type annotations for several new document types...
https://trac.torproject.org/projects/tor/ticket/28615
Doing the needful on Stem's end to take advantage of these. --- stem/descriptor/__init__.py | 5 +++++ stem/descriptor/bandwidth_file.py | 2 +- stem/descriptor/networkstatus.py | 23 +++++----------------- test/unit/descriptor/bandwidth_file.py | 4 ++++ test/unit/descriptor/extrainfo_descriptor.py | 4 ++++ test/unit/descriptor/hidden_service_descriptor.py | 4 ++++ test/unit/descriptor/microdescriptor.py | 4 ++++ .../descriptor/networkstatus/detached_signature.py | 4 ++++ test/unit/descriptor/server_descriptor.py | 4 ++++ 9 files changed, 35 insertions(+), 19 deletions(-)
diff --git a/stem/descriptor/__init__.py b/stem/descriptor/__init__.py index 005830be..40df1391 100644 --- a/stem/descriptor/__init__.py +++ b/stem/descriptor/__init__.py @@ -438,6 +438,11 @@ def _parse_metrics_file(descriptor_type, major_version, minor_version, descripto
for desc in stem.descriptor.networkstatus._parse_file(descriptor_file, document_type, validate = validate, document_handler = document_handler, **kwargs): yield desc + elif descriptor_type == stem.descriptor.networkstatus.DetachedSignature.TYPE_ANNOTATION_NAME and major_version == 1: + document_type = stem.descriptor.networkstatus.DetachedSignature + + for desc in stem.descriptor.networkstatus._parse_file(descriptor_file, document_type, validate = validate, document_handler = document_handler, **kwargs): + yield desc elif descriptor_type == stem.descriptor.tordnsel.TorDNSEL.TYPE_ANNOTATION_NAME and major_version == 1: document_type = stem.descriptor.tordnsel.TorDNSEL
diff --git a/stem/descriptor/bandwidth_file.py b/stem/descriptor/bandwidth_file.py index 4601ad18..e2a420ef 100644 --- a/stem/descriptor/bandwidth_file.py +++ b/stem/descriptor/bandwidth_file.py @@ -195,7 +195,7 @@ class BandwidthFile(Descriptor): a default value, others are left as **None** if undefined """
- TYPE_ANNOTATION_NAME = 'bandwidth-file' # TODO: needs an official @type, https://trac.torproject.org/projects/tor/ticket/28615 + TYPE_ANNOTATION_NAME = 'bandwidth-file'
ATTRIBUTES = { 'timestamp': (None, _parse_timestamp), diff --git a/stem/descriptor/networkstatus.py b/stem/descriptor/networkstatus.py index dd43d5c2..44255f95 100644 --- a/stem/descriptor/networkstatus.py +++ b/stem/descriptor/networkstatus.py @@ -323,6 +323,9 @@ def _parse_file(document_file, document_type = None, validate = False, is_microd router_type = RouterStatusEntryMicroV3 if is_microdescriptor else RouterStatusEntryV3 elif document_type == BridgeNetworkStatusDocument: document_type, router_type = BridgeNetworkStatusDocument, RouterStatusEntryV2 + elif document_type == DetachedSignature: + yield document_type(document_file.read(), validate, **kwargs) + return else: raise ValueError("Document type %i isn't recognized (only able to parse v2, v3, and bridge)" % document_type)
@@ -1900,6 +1903,8 @@ class DetachedSignature(Descriptor): ***** mandatory attribute """
+ TYPE_ANNOTATION_NAME = 'detached-signature-3' + ATTRIBUTES = { 'consensus_digest': (None, _parse_consensus_digest_line), 'valid_after': (None, _parse_header_valid_after_line), @@ -1932,24 +1937,6 @@ class DetachedSignature(Descriptor): ('valid-until', _random_date()), ))
- @classmethod - def from_str(cls, content, **kwargs): - # Detached signatures don't have their own @type annotation, so to make - # our subclass from_str() work we need to do the type inferencing ourself. - - if 'descriptor_type' in kwargs: - raise ValueError("Detached signatures don't have their own @type annotation. As such providing a 'descriptor_type' argument with DetachedSignature.from_str() does not work. Please drop the 'descriptor_type' argument when using this method.") - - is_multiple = kwargs.pop('multiple', False) - results = list(_parse_file_detached_sigs(io.BytesIO(stem.util.str_tools._to_bytes(content)), **kwargs)) - - if is_multiple: - return results - elif len(results) == 1: - return results[0] - else: - raise ValueError("Descriptor.from_str() expected a single descriptor, but had %i instead. Please include 'multiple = True' if you want a list of results instead." % len(results)) - def __init__(self, raw_content, validate = False): super(DetachedSignature, self).__init__(raw_content, lazy_load = not validate) entries = _descriptor_components(raw_content, validate) diff --git a/test/unit/descriptor/bandwidth_file.py b/test/unit/descriptor/bandwidth_file.py index 5e75514c..e8684cf4 100644 --- a/test/unit/descriptor/bandwidth_file.py +++ b/test/unit/descriptor/bandwidth_file.py @@ -61,6 +61,10 @@ new_header=neat stuff
class TestBandwidthFile(unittest.TestCase): + def test_from_str(self): + sig = BandwidthFile.create() + self.assertEqual(sig, BandwidthFile.from_str(str(sig))) + def test_format_v1_0(self): """ Parse version 1.0 formatted files. diff --git a/test/unit/descriptor/extrainfo_descriptor.py b/test/unit/descriptor/extrainfo_descriptor.py index d459484b..6eea7fde 100644 --- a/test/unit/descriptor/extrainfo_descriptor.py +++ b/test/unit/descriptor/extrainfo_descriptor.py @@ -27,6 +27,10 @@ expect_invalid_attr_for_text = functools.partial(base_expect_invalid_attr_for_te
class TestExtraInfoDescriptor(unittest.TestCase): + def test_from_str(self): + sig = RelayExtraInfoDescriptor.create() + self.assertEqual(sig, RelayExtraInfoDescriptor.from_str(str(sig))) + def test_metrics_relay_descriptor(self): """ Parses and checks our results against an extrainfo descriptor from metrics. diff --git a/test/unit/descriptor/hidden_service_descriptor.py b/test/unit/descriptor/hidden_service_descriptor.py index 437366a2..e9ba012b 100644 --- a/test/unit/descriptor/hidden_service_descriptor.py +++ b/test/unit/descriptor/hidden_service_descriptor.py @@ -241,6 +241,10 @@ expect_invalid_attr_for_text = functools.partial(base_expect_invalid_attr_for_te
class TestHiddenServiceDescriptor(unittest.TestCase): + def test_from_str(self): + sig = HiddenServiceDescriptor.create() + self.assertEqual(sig, HiddenServiceDescriptor.from_str(str(sig))) + def test_for_duckduckgo_with_validation(self): """ Parse duckduckgo's descriptor. diff --git a/test/unit/descriptor/microdescriptor.py b/test/unit/descriptor/microdescriptor.py index 2afccc48..f8e03a12 100644 --- a/test/unit/descriptor/microdescriptor.py +++ b/test/unit/descriptor/microdescriptor.py @@ -37,6 +37,10 @@ w/1LVWFfhcBnsGi4JMGbmP+KUZG9A8kI9deSyJhfi35jA7UepiHHAgMBAAE=
class TestMicrodescriptor(unittest.TestCase): + def test_from_str(self): + sig = Microdescriptor.create() + self.assertEqual(sig, Microdescriptor.from_str(str(sig))) + def test_local_microdescriptors(self): """ Checks a small microdescriptor file with known contents. diff --git a/test/unit/descriptor/networkstatus/detached_signature.py b/test/unit/descriptor/networkstatus/detached_signature.py index 18d3c177..beba92ad 100644 --- a/test/unit/descriptor/networkstatus/detached_signature.py +++ b/test/unit/descriptor/networkstatus/detached_signature.py @@ -86,6 +86,10 @@ SkYvemmKnuFFmLHYKMjTy0YA5oTkmYgFao15gMeR4nNwuqwxwJ7YLEeCTW+D3avi
class TestDetachedSignature(unittest.TestCase): + def test_from_str(self): + sig = DetachedSignature.create() + self.assertEqual(sig, DetachedSignature.from_str(str(sig))) + def test_minimal(self): """ Parses a minimal detached signature. diff --git a/test/unit/descriptor/server_descriptor.py b/test/unit/descriptor/server_descriptor.py index 49cf327e..6b91d90f 100644 --- a/test/unit/descriptor/server_descriptor.py +++ b/test/unit/descriptor/server_descriptor.py @@ -53,6 +53,10 @@ expect_invalid_attr_for_text = functools.partial(base_expect_invalid_attr_for_te
class TestServerDescriptor(unittest.TestCase): + def test_from_str(self): + sig = RelayDescriptor.create() + self.assertEqual(sig, RelayDescriptor.from_str(str(sig))) + def test_with_tarfile_path(self): """ Fetch server descriptors via parse_file() for a tarfile path.
tor-commits@lists.torproject.org