[tor-commits] [stem/master] Support multiple extra entries on versions

atagar at torproject.org atagar at torproject.org
Thu Sep 21 19:23:48 UTC 2017


commit bac3947224b96b5bba98f5e1a5e12ad6acc20a96
Author: Damian Johnson <atagar at torproject.org>
Date:   Thu Sep 21 12:23:19 2017 -0700

    Support multiple extra entries on versions
    
    https://trac.torproject.org/projects/tor/ticket/22110
    https://gitweb.torproject.org/torspec.git/commit/?id=b50917d
---
 docs/change_log.rst  |  1 +
 stem/version.py      | 29 +++++++++++++++++------------
 test/unit/version.py | 11 +++++++++++
 3 files changed, 29 insertions(+), 12 deletions(-)

diff --git a/docs/change_log.rst b/docs/change_log.rst
index 2e421c4f..415a8bfe 100644
--- a/docs/change_log.rst
+++ b/docs/change_log.rst
@@ -62,6 +62,7 @@ The following are only available within Stem's `git repository
   * Added :func:`~stem.manual.database` to get a cursor for the manual cache
   * Failed to parse torrcs without a port on ipv6 exit policy entries
   * Resilient to 'Tor' prefix in 'GETINFO version' result (:spec:`c5ff1b1`)
+  * Added a **all_extra** parameter to :class:`stem.version.Version` and support for multiple parenthetical entries (:trac:`22110`, :spec:`b50917d`)
   * Closing controller connection faster when under heavy event load
   * More succinct trace level logging
 
diff --git a/stem/version.py b/stem/version.py
index 4f0ffb9c..87070093 100644
--- a/stem/version.py
+++ b/stem/version.py
@@ -94,6 +94,8 @@ except ImportError:
 # cache for the get_system_tor_version function
 VERSION_CACHE = {}
 
+VERSION_PATTERN = re.compile(r'^([0-9]+)\.([0-9]+)\.([0-9]+)(\.[0-9]+)?(-\S*)?(( \(\S*\))*)$')
+
 
 def get_system_tor_version(tor_cmd = 'tor'):
   """
@@ -156,13 +158,17 @@ class Version(object):
   <https://gitweb.torproject.org/torspec.git/tree/version-spec.txt>`_,
   such as "0.1.4" or "0.2.2.23-alpha (git-7dcd105be34a4f44)".
 
+  .. versionchanged:: 1.6.0
+     Added all_extra parameter..
+
   :var int major: major version
   :var int minor: minor version
   :var int micro: micro version
   :var int patch: patch level (**None** if undefined)
   :var str status: status tag such as 'alpha' or 'beta-dev' (**None** if undefined)
-  :var str extra: extra information without its parentheses such as
+  :var str extra: first extra information without its parentheses such as
     'git-8be6058d8f31e578' (**None** if undefined)
+  :var list all_extra: all extra information entries, without their parentheses
   :var str git_commit: git commit id (**None** if it wasn't provided)
 
   :param str version_str: version to be parsed
@@ -172,11 +178,11 @@ class Version(object):
 
   def __init__(self, version_str):
     self.version_str = version_str
-    version_parts = re.match(r'^([0-9]+)\.([0-9]+)\.([0-9]+)(\.[0-9]+)?(-\S*)?( \(\S*\))?$', version_str)
+    version_parts = VERSION_PATTERN.match(version_str)
     self._hash = None
 
     if version_parts:
-      major, minor, micro, patch, status, extra = version_parts.groups()
+      major, minor, micro, patch, status, extra_str, _ = version_parts.groups()
 
       # The patch and status matches are optional (may be None) and have an extra
       # proceeding period or dash if they exist. Stripping those off.
@@ -187,20 +193,19 @@ class Version(object):
       if status:
         status = status[1:]
 
-      if extra:
-        extra = extra[2:-1]
-
       self.major = int(major)
       self.minor = int(minor)
       self.micro = int(micro)
       self.patch = patch
       self.status = status
-      self.extra = extra
-
-      if extra and re.match('^git-[0-9a-f]{16}$', extra):
-        self.git_commit = extra[4:]
-      else:
-        self.git_commit = None
+      self.all_extra = [entry[1:-1] for entry in extra_str.strip().split()] if extra_str else []
+      self.extra = self.all_extra[0] if self.all_extra else None
+      self.git_commit = None
+
+      for extra in self.all_extra:
+        if extra and re.match('^git-[0-9a-f]{16}$', extra):
+          self.git_commit = extra[4:]
+          break
     else:
       raise ValueError("'%s' isn't a properly formatted tor version" % version_str)
 
diff --git a/test/unit/version.py b/test/unit/version.py
index 2518a41b..f8c51f95 100644
--- a/test/unit/version.py
+++ b/test/unit/version.py
@@ -81,6 +81,16 @@ class TestVersion(unittest.TestCase):
     self.assertRaises(ValueError, stem.version.Version, '12.3')
     self.assertRaises(ValueError, stem.version.Version, '1.-2.3')
 
+  def test_with_multiple_extra(self):
+    """
+    Parse a version with multiple 'extra' fields.
+    """
+
+    version = Version('0.1.2 (release) (git-73ff13ab3cc9570d)')
+    self.assert_versions_match(version, 0, 1, 2, None, None, 'release')
+    self.assertEqual(['release', 'git-73ff13ab3cc9570d'], version.all_extra)
+    self.assertEqual('73ff13ab3cc9570d', version.git_commit)
+
   def test_comparison(self):
     """
     Tests comparision between Version instances.
@@ -224,6 +234,7 @@ class TestVersion(unittest.TestCase):
     self.assertEqual(extra, version.extra)
 
     if extra is None:
+      self.assertEqual([], version.all_extra)
       self.assertEqual(None, version.git_commit)
 
   def assert_version_is_greater(self, first_version, second_version):



More information about the tor-commits mailing list