commit 62f34c67bcaaa7205b09cc7cf6201d78447c0a39 Author: Damian Johnson atagar@torproject.org Date: Sat Apr 14 15:51:16 2012 -0700
Expanding attributes for read/write-history
Parsing and validating read-history and write-history attributes. These are depricated fields, but still found on archived and extra-info descriptors. This includes a unit test to exercise the additions. --- stem/descriptor/server_descriptor.py | 64 +++++++++++++++++++++++++--- test/unit/descriptor/server_descriptor.py | 27 ++++++++++++ 2 files changed, 84 insertions(+), 7 deletions(-)
diff --git a/stem/descriptor/server_descriptor.py b/stem/descriptor/server_descriptor.py index 9b74e2b..6892381 100644 --- a/stem/descriptor/server_descriptor.py +++ b/stem/descriptor/server_descriptor.py @@ -202,10 +202,18 @@ class ServerDescriptorV3(stem.descriptor.Descriptor): average_bandwidth (int) - rate of traffic relay is willing to relay in bytes/s (*) burst_bandwidth (int) - rate of traffic relay is willing to burst to in bytes/s (*) observed_bandwidth (int) - estimated capacity of the relay based on usage in bytes/s (*) - read_history (str) - (deprecated) always unset - write_history (str) - (deprecated) always unset eventdns (bool) - (deprecated) always unset (*)
+ read_history (str) - (deprecated) read-history line, always unset + read_history_end (datetime.datetime) - (deprecated) end of the sampling interval + read_history_interval (int) - (deprecated) seconds per interval + read_history_values (list) - (deprecated) bytes read during each interval (*) + + write_history (str) - (deprecated) write-history line, always unset + write_history_end (datetime.datetime) - (deprecated) end of the sampling interval + write_history_interval (int) - (deprecated) seconds per interval + write_history_values (list) - (deprecated) bytes written during each interval (*) + (*) required fields, others are left as None if undefined """
@@ -254,9 +262,18 @@ class ServerDescriptorV3(stem.descriptor.Descriptor): self.average_bandwidth = None self.burst_bandwidth = None self.observed_bandwidth = None + self.eventdns = True + self.read_history = None + self.read_history_end = None + self.read_history_interval = None + self.read_history_values = [] + self.write_history = None - self.eventdns = True + self.write_history_end = None + self.write_history_interval = None + self.write_history_values = [] + self._unrecognized_lines = []
self._annotation_lines = annotations if annotations else [] @@ -474,12 +491,45 @@ class ServerDescriptorV3(stem.descriptor.Descriptor): raise ValueError("Protocols line did not match the expected pattern: %s" % line) elif keyword == "family": self.family = value.split(" ") - elif keyword == "read-history": - self.read_history = value - elif keyword == "write-history": - self.write_history = value elif keyword == "eventdns": self.eventdns = value == "1" + elif keyword in ("read-history", "write-history"): + is_read = keyword == "read-history" + + if is_read: self.read_history = value + else: self.write_history = value + + value_match = re.match("^(.*) (([0-9]+) s) (.*)$", value) + + if not value_match: + if not validate: continue + raise ValueError("Malformed %s line: %s" % (keyword, line)) + + end_value, interval_value, history_values = value_match.groups() + + try: + end_datetime = datetime.datetime.strptime(end_value, "%Y-%m-%d %H:%M:%S") + + if is_read: self.read_history_end = end_datetime + else: self.write_history_end = end_datetime + except ValueError: + if validate: + raise ValueError("%s line's time wasn't parseable: %s" % (keyword, line)) + + if interval_value.isdigit(): + if is_read: self.read_history_interval = int(interval_value) + else: self.write_history_interval = int(interval_value) + elif validate: + raise ValueError("%s line's interval wasn't a number: %s" % (keyword, line)) + + for sampling in history_values.split(","): + if sampling.isdigit(): + if is_read: self.read_history_values.append(int(sampling)) + else: self.write_history_values.append(int(sampling)) + else: + if validate: + raise ValueError("%s line has non-numeric values: %s" % (keyword, line)) + else: break else: self._unrecognized_lines.append(line)
diff --git a/test/unit/descriptor/server_descriptor.py b/test/unit/descriptor/server_descriptor.py index 89a28c6..5c4cfce 100644 --- a/test/unit/descriptor/server_descriptor.py +++ b/test/unit/descriptor/server_descriptor.py @@ -222,6 +222,33 @@ class TestServerDescriptor(unittest.TestCase): desc_text = _make_descriptor({"published": "2012-01-01"}) self._expect_invalid_attr(desc_text, "published")
+ def test_read_and_write_history(self): + """ + Parses a read-history and write-history entry. This is now a depricated + field for relay server descriptors but is still found in archives and + extra-info descriptors. + """ + + for field in ("read-history", "write-history"): + value = "2005-12-16 18:00:48 (900 s) 81,8848,8927,8927,83,8848" + desc_text = _make_descriptor({"opt %s" % field: value}) + desc = RelayDescriptorV3(desc_text) + + if field == "read-history": + attr = (desc.read_history, desc.read_history_end, + desc.read_history_interval, desc.read_history_values) + else: + attr = (desc.write_history, desc.write_history_end, + desc.write_history_interval, desc.write_history_values) + + expected_end = datetime.datetime(2005, 12, 16, 18, 0, 48) + expected_values = [81, 8848, 8927, 8927, 83, 8848] + + self.assertEquals(value, attr[0]) + self.assertEquals(expected_end, attr[1]) + self.assertEquals(900, attr[2]) + self.assertEquals(expected_values, attr[3]) + def test_annotations(self): """ Checks that content before a descriptor are parsed as annotations.
tor-commits@lists.torproject.org