[tor-commits] [stem/master] Helper function for parsing timestamp/intervals

atagar at torproject.org atagar at torproject.org
Mon May 14 00:14:27 UTC 2012


commit b8e08ce69d30d10cfa6879b7205f62e988fea0e1
Author: Damian Johnson <atagar at torproject.org>
Date:   Tue May 8 09:53:13 2012 -0700

    Helper function for parsing timestamp/intervals
    
    Several extra-info descriptor lines are of the form...
    'YYYY-MM-DD HH:MM:SS (NSEC s) *'
    
    So making a helper function to parse it. Using it for the server descriptor's
    read/write-history entries and it improves code readability quite a bit...
---
 stem/descriptor/extrainfo_descriptor.py |   35 +++++++++++++++++++
 stem/descriptor/server_descriptor.py    |   57 ++++++++++++------------------
 2 files changed, 58 insertions(+), 34 deletions(-)

diff --git a/stem/descriptor/extrainfo_descriptor.py b/stem/descriptor/extrainfo_descriptor.py
index e13787f..ca34ca1 100644
--- a/stem/descriptor/extrainfo_descriptor.py
+++ b/stem/descriptor/extrainfo_descriptor.py
@@ -21,6 +21,7 @@ ExtraInfoDescriptor - Tor extra-info descriptor.
   +- get_unrecognized_lines - lines with unrecognized content
 """
 
+import re
 import datetime
 
 import stem.descriptor
@@ -99,6 +100,40 @@ def parse_file(descriptor_file, validate = True):
       yield ExtraInfoDescriptor("".join(extrainfo_content), validate)
     else: break # done parsing file
 
+def _parse_timestamp_and_interval(keyword, content):
+  """
+  Parses a 'YYYY-MM-DD HH:MM:SS (NSEC s) *' entry.
+  
+  Arguments:
+    keyword (str) - line's keyword
+    content (str) - line content to be parsed
+  
+  Returns:
+    tuple of the form...
+    (timestamp (datetime), interval (int), remaining content (str))
+  
+  Raises:
+    ValueError if the content is malformed
+  """
+  
+  line = "%s %s" % (keyword, content)
+  content_match = re.match("^(.*) \(([0-9]+) s\)( .*)?$", content)
+  
+  if not content_match:
+    raise ValueError("Malformed %s line: %s" % (keyword, line))
+  
+  timestamp_str, interval, remainder = content_match.groups()
+  if remainder: remainder = remainder[1:] # remove leading space
+  
+  if not interval.isdigit():
+    raise ValueError("%s line's interval wasn't a number: %s" % (keyword, line))
+  
+  try:
+    timestamp = datetime.datetime.strptime(timestamp_str, "%Y-%m-%d %H:%M:%S")
+    return timestamp, int(interval), remainder
+  except ValueError:
+    raise ValueError("%s line's timestamp wasn't parseable: %s" % (keyword, line))
+
 class ExtraInfoDescriptor(stem.descriptor.Descriptor):
   """
   Extra-info descriptor document.
diff --git a/stem/descriptor/server_descriptor.py b/stem/descriptor/server_descriptor.py
index 8513b86..2a9d72f 100644
--- a/stem/descriptor/server_descriptor.py
+++ b/stem/descriptor/server_descriptor.py
@@ -29,6 +29,7 @@ import hashlib
 import datetime
 
 import stem.descriptor
+import stem.descriptor.extrainfo_descriptor
 import stem.version
 import stem.util.connection
 import stem.util.tor_tools
@@ -467,43 +468,31 @@ class ServerDescriptor(stem.descriptor.Descriptor):
       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")
+          timestamp, interval, remainder = \
+            stem.descriptor.extrainfo_descriptor._parse_timestamp_and_interval(keyword, value)
           
-          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))
-        
-        if history_values != '':
-          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))
+          try:
+            if remainder:
+              history_values = [int(entry) for entry in remainder.split(",")]
             else:
-              if validate:
-                raise ValueError("%s line has non-numeric values: %s" % (keyword, line))
-              else: break
+              history_values = []
+          except ValueError:
+            raise ValueError("%s line has non-numeric values: %s" % (keyword, line))
+          
+          if keyword == "read-history":
+            self.read_history = value
+            self.read_history_end = timestamp
+            self.read_history_interval = interval
+            self.read_history_values = history_values
+          else:
+            self.write_history = value
+            self.write_history_end = timestamp
+            self.write_history_interval = interval
+            self.write_history_values = history_values
+        except ValueError, exc:
+          if not validate: continue
+          else: raise exc
       else:
         self._unrecognized_lines.append(line)
     





More information about the tor-commits mailing list