[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [stem/master] Parsing the known-flags attribute
commit 0e4f8bfbdcf1bc9e427748dd37b53ad6b4a32d93
Author: Damian Johnson <atagar@xxxxxxxxxxxxxx>
Date: Sun Sep 9 15:13:32 2012 -0700
Parsing the known-flags attribute
Only changes are...
* Moving the Flag enum to stem.descriptor.Flag since it's something that users
will commonly use. As a rule of thumb I'd like users to only need
'stem.descriptor' unless they're doing something fancy. However, this is just
a temporary move - I plan to move Flag to is own module, like Version.
* Excluding empty strings from our known_flags attribute (our prior behavior
was to parse things like " " into ['', '', '', '']). The spec doesn't set
any constraints on what a flag can be so I suppose technically one could be
the empty string, though this'll never be the case. Still waffling back and
forth about if this should cause a validation error or not...
---
stem/descriptor/__init__.py | 17 +++++++++++++++
stem/descriptor/networkstatus.py | 27 +++++------------------
test/integ/descriptor/networkstatus.py | 3 +-
test/unit/descriptor/networkstatus/document.py | 24 ++++++++++++++++++++-
test/unit/descriptor/networkstatus/entry.py | 3 +-
5 files changed, 50 insertions(+), 24 deletions(-)
diff --git a/stem/descriptor/__init__.py b/stem/descriptor/__init__.py
index 688e1b6..b921058 100644
--- a/stem/descriptor/__init__.py
+++ b/stem/descriptor/__init__.py
@@ -27,12 +27,29 @@ import re
import datetime
import collections
+import stem.util.enum
+
KEYWORD_CHAR = "a-zA-Z0-9-"
WHITESPACE = " \t"
KEYWORD_LINE = re.compile("^([%s]+)(?:[%s]+(.*))?$" % (KEYWORD_CHAR, WHITESPACE))
PGP_BLOCK_START = re.compile("^-----BEGIN ([%s%s]+)-----$" % (KEYWORD_CHAR, WHITESPACE))
PGP_BLOCK_END = "-----END %s-----"
+Flag = stem.util.enum.Enum(
+ ("AUTHORITY", "Authority"),
+ ("BADEXIT", "BadExit"),
+ ("EXIT", "Exit"),
+ ("FAST", "Fast"),
+ ("GUARD", "Guard"),
+ ("HSDIR", "HSDir"),
+ ("NAMED", "Named"),
+ ("RUNNING", "Running"),
+ ("STABLE", "Stable"),
+ ("UNNAMED", "Unnamed"),
+ ("V2DIR", "V2Dir"),
+ ("VALID", "Valid"),
+)
+
def parse_file(path, descriptor_file):
"""
Provides an iterator for the descriptors within a given file.
diff --git a/stem/descriptor/networkstatus.py b/stem/descriptor/networkstatus.py
index eca3b71..beafe89 100644
--- a/stem/descriptor/networkstatus.py
+++ b/stem/descriptor/networkstatus.py
@@ -52,7 +52,6 @@ except:
import stem.descriptor
import stem.version
import stem.exit_policy
-import stem.util.enum
import stem.util.tor_tools
from stem.descriptor import _read_until_keywords, _peek_keyword, _strptime
@@ -61,21 +60,6 @@ from stem.descriptor import _read_keyword_line, _read_keyword_line_str, _get_pse
_bandwidth_weights_regex = re.compile(" ".join(["W%s=\d+" % weight for weight in ["bd",
"be", "bg", "bm", "db", "eb", "ed", "ee", "eg", "em", "gb", "gd", "gg", "gm", "mb", "md", "me", "mg", "mm"]]))
-Flag = stem.util.enum.Enum(
- ("AUTHORITY", "Authority"),
- ("BADEXIT", "BadExit"),
- ("EXIT", "Exit"),
- ("FAST", "Fast"),
- ("GUARD", "Guard"),
- ("HSDIR", "HSDir"),
- ("NAMED", "Named"),
- ("RUNNING", "Running"),
- ("STABLE", "Stable"),
- ("UNNAMED", "Unnamed"),
- ("V2DIR", "V2Dir"),
- ("VALID", "Valid"),
-)
-
# Network status document are either a 'vote' or 'consensus', with different
# mandatory fields for each. Both though require that their fields appear in a
# specific order. This is an ordered listing of the following...
@@ -383,6 +367,11 @@ class NetworkStatusDocument(stem.descriptor.Descriptor):
except ValueError:
if validate:
raise ValueError("Network status document's '%s' line had '%s', which isn't a parseable tor version: %s" % (keyword, entry, line))
+ elif keyword == "known-flags":
+ # "known-flags" FlagList
+
+ # simply fetches the entries, excluding empty strings
+ self.known_flags = [entry for entry in value.split(" ") if entry]
# doing this validation afterward so we know our 'is_consensus' and
# 'is_vote' attributes
@@ -408,14 +397,10 @@ class NetworkStatusDocument(stem.descriptor.Descriptor):
_read_keyword_line("voting-delay", content, False, True)
_read_keyword_line("client-versions", content, False, True)
_read_keyword_line("server-versions", content, False, True)
+ _read_keyword_line("known-flags", content, False, True)
vote = self.is_vote
- flags_content = _read_keyword_line("known-flags", content, validate)
-
- if flags_content:
- self.known_flags = flags_content.split(" ")
-
read_keyword_line("params", True)
if self.params:
self.params = dict([(param.split("=")[0], int(param.split("=")[1])) for param in self.params.split(" ")])
diff --git a/test/integ/descriptor/networkstatus.py b/test/integ/descriptor/networkstatus.py
index 9087b22..d77a36f 100644
--- a/test/integ/descriptor/networkstatus.py
+++ b/test/integ/descriptor/networkstatus.py
@@ -11,6 +11,7 @@ import unittest
import stem.exit_policy
import stem.version
+import stem.descriptor
import stem.descriptor.networkstatus
import test.integ.descriptor
@@ -47,7 +48,7 @@ class TestNetworkStatus(unittest.TestCase):
# check if there's any unknown flags
for flag in desc.flags:
- if not flag in stem.descriptor.networkstatus.Flag:
+ if not flag in stem.descriptor.Flag:
# TODO: this should be a special 'new capability' check later
# rather than failing the tests
raise ValueError("Unrecognized flag type: %s, found on relay %s (%s)" % (flag, desc.fingerprint, desc.nickname))
diff --git a/test/unit/descriptor/networkstatus/document.py b/test/unit/descriptor/networkstatus/document.py
index 032c095..5e3ec4b 100644
--- a/test/unit/descriptor/networkstatus/document.py
+++ b/test/unit/descriptor/networkstatus/document.py
@@ -6,7 +6,8 @@ import datetime
import unittest
import stem.version
-from stem.descriptor.networkstatus import HEADER_STATUS_DOCUMENT_FIELDS, FOOTER_STATUS_DOCUMENT_FIELDS, Flag, NetworkStatusDocument, DirectorySignature
+from stem.descriptor import Flag
+from stem.descriptor.networkstatus import HEADER_STATUS_DOCUMENT_FIELDS, FOOTER_STATUS_DOCUMENT_FIELDS, NetworkStatusDocument, DirectorySignature
NETWORK_STATUS_DOCUMENT_ATTR = {
"network-status-version": "3",
@@ -354,4 +355,25 @@ class TestNetworkStatusDocument(unittest.TestCase):
document = NetworkStatusDocument(content, False)
self.assertEquals(expected_value, getattr(document, attr))
+
+ def test_known_flags(self):
+ """
+ Parses some known-flag entries. Just exercising the field, there's not much
+ to test here.
+ """
+
+ test_values = (
+ ("", []),
+ (" ", []),
+ ("BadExit", [Flag.BADEXIT]),
+ ("BadExit ", [Flag.BADEXIT]),
+ ("BadExit ", [Flag.BADEXIT]),
+ ("BadExit Fast", [Flag.BADEXIT, Flag.FAST]),
+ ("BadExit Unrecognized Fast", [Flag.BADEXIT, "Unrecognized", Flag.FAST]),
+ )
+
+ for test_value, expected_value in test_values:
+ content = get_network_status_document({"known-flags": test_value})
+ document = NetworkStatusDocument(content)
+ self.assertEquals(expected_value, document.known_flags)
diff --git a/test/unit/descriptor/networkstatus/entry.py b/test/unit/descriptor/networkstatus/entry.py
index 195600c..7c9e051 100644
--- a/test/unit/descriptor/networkstatus/entry.py
+++ b/test/unit/descriptor/networkstatus/entry.py
@@ -5,7 +5,8 @@ Unit tests for the RouterStatusEntry of stem.descriptor.networkstatus.
import datetime
import unittest
-from stem.descriptor.networkstatus import Flag, RouterStatusEntry, _decode_fingerprint
+from stem.descriptor import Flag
+from stem.descriptor.networkstatus import RouterStatusEntry, _decode_fingerprint
from stem.version import Version
from stem.exit_policy import MicrodescriptorExitPolicy
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits