[tor-commits] [stem/master] Handle new @type annotations

atagar at torproject.org atagar at torproject.org
Tue Jan 29 01:17:33 UTC 2019


commit 159ae8864b7bbe2d3f03ae0e90d488d34d689fd1
Author: Damian Johnson <atagar at 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.



More information about the tor-commits mailing list