commit 06498d8b61ad5f01c04c7011c70892a9846d4c27
Author: Damian Johnson <atagar(a)torproject.org>
Date: Tue Jan 31 07:46:53 2012 -0800
Adding ControlLine peek_key method
Method to allow us to switch on the key/value mapping while parsing a line.
This isn't needed yet (the only parsing done at this point is PROTOCOLINFO
responses and that only uses positional entries). However, it's crossed my
mind a few times that this will be needed later.
---
stem/socket.py | 18 ++++++++++++++++++
test/unit/socket/control_line.py | 7 +++++++
2 files changed, 25 insertions(+), 0 deletions(-)
diff --git a/stem/socket.py b/stem/socket.py
index 889713d..1b481ce 100644
--- a/stem/socket.py
+++ b/stem/socket.py
@@ -28,6 +28,7 @@ ControlLine - String subclass with methods for parsing controller responses.
|- is_empty - checks if the remaining content is empty
|- is_next_quoted - checks if the next entry is a quoted value
|- is_next_mapping - checks if the next entry is a KEY=VALUE mapping
+ |- peek_key - provides the key of the next entry
|- pop - removes and returns the next entry
+- pop_mapping - removes and returns the next entry as a KEY=VALUE mapping
@@ -487,6 +488,23 @@ class ControlLine(str):
else:
return False # doesn't start with a key
+ def peek_key(self):
+ """
+ Provides the key of the next entry, providing None if it isn't a key/value
+ mapping.
+
+ Returns:
+ str with the next entry's key
+ """
+
+ remainder = self._remainder
+ key_match = KEY_ARG.match(remainder)
+
+ if key_match:
+ return key_match.groups()[0]
+ else:
+ return None
+
def pop(self, quoted = False, escaped = False):
"""
Parses the next space separated entry, removing it and the space from our
diff --git a/test/unit/socket/control_line.py b/test/unit/socket/control_line.py
index 6e59f43..7752147 100644
--- a/test/unit/socket/control_line.py
+++ b/test/unit/socket/control_line.py
@@ -52,6 +52,7 @@ class TestControlLine(unittest.TestCase):
self.assertFalse(line.is_empty())
self.assertFalse(line.is_next_quoted())
self.assertFalse(line.is_next_mapping())
+ self.assertEquals(None, line.peek_key())
self.assertRaises(ValueError, line.pop_mapping)
self.assertEquals(line.pop(), 'PROTOCOLINFO')
@@ -59,6 +60,7 @@ class TestControlLine(unittest.TestCase):
self.assertFalse(line.is_empty())
self.assertFalse(line.is_next_quoted())
self.assertFalse(line.is_next_mapping())
+ self.assertEquals(None, line.peek_key())
self.assertRaises(ValueError, line.pop_mapping)
self.assertEquals(line.pop(), '1')
@@ -66,6 +68,7 @@ class TestControlLine(unittest.TestCase):
self.assertTrue(line.is_empty())
self.assertFalse(line.is_next_quoted())
self.assertFalse(line.is_next_mapping())
+ self.assertEquals(None, line.peek_key())
self.assertRaises(IndexError, line.pop_mapping)
self.assertRaises(IndexError, line.pop)
@@ -73,6 +76,7 @@ class TestControlLine(unittest.TestCase):
self.assertTrue(line.is_empty())
self.assertFalse(line.is_next_quoted())
self.assertFalse(line.is_next_mapping())
+ self.assertEquals(None, line.peek_key())
def test_pop_mapping(self):
"""
@@ -90,6 +94,7 @@ class TestControlLine(unittest.TestCase):
self.assertTrue(line.is_next_mapping(key = "Tor"))
self.assertTrue(line.is_next_mapping(key = "Tor", quoted = True))
self.assertTrue(line.is_next_mapping(quoted = True))
+ self.assertEquals("Tor", line.peek_key())
# try popping this as a non-quoted mapping
self.assertEquals(line.pop_mapping(), ('Tor', '"0.2.1.30'))
@@ -98,6 +103,7 @@ class TestControlLine(unittest.TestCase):
self.assertFalse(line.is_next_quoted())
self.assertFalse(line.is_next_mapping())
self.assertRaises(ValueError, line.pop_mapping)
+ self.assertEquals(None, line.peek_key())
# try popping this as a quoted mapping
line = stem.socket.ControlLine(version_entry)
@@ -106,6 +112,7 @@ class TestControlLine(unittest.TestCase):
self.assertTrue(line.is_empty())
self.assertFalse(line.is_next_quoted())
self.assertFalse(line.is_next_mapping())
+ self.assertEquals(None, line.peek_key())
def test_escapes(self):
"""