[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [stem/master] Class and function for Tor Versions
commit 69083da95c5ab536adcd23f19a424ed9395015bb
Author: Damian Johnson <atagar@xxxxxxxxxxxxxx>
Date: Thu Oct 6 09:52:04 2011 -0700
Class and function for Tor Versions
Starting with a simple (but non-trivial) class that will be needed for handling
PROTOCOLINFO responses. This is partly to establish conventions for
documentation and unit tests.
---
run_tests.py | 13 ++++++
stem/__init__.py | 6 +++
stem/__init__.pyc | Bin 0 -> 228 bytes
stem/run_tests.py | 13 ++++++
stem/types.py | 99 +++++++++++++++++++++++++++++++++++++++++++
stem/types.pyc | Bin 0 -> 3406 bytes
test/__init__.py | 6 +++
test/__init__.pyc | Bin 0 -> 237 bytes
test/version.py | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++++
test/version.pyc | Bin 0 -> 3982 bytes
10 files changed, 258 insertions(+), 0 deletions(-)
diff --git a/run_tests.py b/run_tests.py
old mode 100644
new mode 100755
index e69de29..0fe6365
--- a/run_tests.py
+++ b/run_tests.py
@@ -0,0 +1,13 @@
+#!/usr/bin/env python
+
+"""
+Runs unit and integration tests.
+"""
+
+import unittest
+import test.version
+
+if __name__ == '__main__':
+ suite = unittest.TestLoader().loadTestsFromTestCase(test.version.TestVerionFunctions)
+ unittest.TextTestRunner(verbosity=2).run(suite)
+
diff --git a/stem/__init__.py b/stem/__init__.py
new file mode 100644
index 0000000..01c350c
--- /dev/null
+++ b/stem/__init__.py
@@ -0,0 +1,6 @@
+"""
+Library for working with the tor process.
+"""
+
+__all__ = ["types"]
+
diff --git a/stem/__init__.pyc b/stem/__init__.pyc
new file mode 100644
index 0000000..43c6f7d
Binary files /dev/null and b/stem/__init__.pyc differ
diff --git a/stem/run_tests.py b/stem/run_tests.py
new file mode 100644
index 0000000..ad52f9c
--- /dev/null
+++ b/stem/run_tests.py
@@ -0,0 +1,13 @@
+#!/usr/bin/env python
+
+"""
+Runs unit and integration tests.
+"""
+
+import unittest
+import test.types
+
+if __name__ == '__main__':
+ suite = unittest.TestLoader().loadTestsFromTestCase(test.types.TestVerionFunctions)
+ unittest.TextTestRunner(verbosity=2).run(suite)
+
diff --git a/stem/types.py b/stem/types.py
new file mode 100644
index 0000000..0f7030b
--- /dev/null
+++ b/stem/types.py
@@ -0,0 +1,99 @@
+"""
+Classes for miscellaneous tor object. This includes...
+
+types.Version - Tor versioning information.
+ * get_version(versionStr)
+ Converts a version string to a types.Version instance.
+"""
+
+import re
+
+class Version:
+ """
+ Comparable tor version, as per the 'new version' of the version-spec...
+ https://gitweb.torproject.org/torspec.git/blob/HEAD:/version-spec.txt
+
+ Attributes:
+ major (int) - major version
+ minor (int) - minor version
+ micro (int) - micro version
+ patch (int) - optional patch level (None if undefined)
+ status (str) - optional status tag without the preceding dash such as
+ 'alpha', 'beta-dev', etc (None if undefined)
+ """
+
+ def __init__(self, major, minor, micro, patch = None, status = None):
+ self.major = major
+ self.minor = minor
+ self.micro = micro
+ self.patch = patch
+ self.status = status
+
+ def __str__(self):
+ """
+ Provides the normal representation for the version, for instance:
+ "0.2.2.23-alpha"
+ """
+
+ suffix = ""
+
+ if self.patch:
+ suffix += ".%i" % self.patch
+
+ if self.status:
+ suffix += "-%s" % self.status
+
+ return "%i.%i.%i%s" % (self.major, self.minor, self.micro, suffix)
+
+ def __cmp__(self, other):
+ """
+ Simple comparision of versions. An undefined patch level is treated as zero
+ and status tags are compared lexically (as per the version spec).
+ """
+
+ if not isinstance(other, Version):
+ raise ValueError("types.Version can only be compared with other Version instances")
+
+ for attr in ("major", "minor", "micro", "patch"):
+ myVersion = max(0, self.__dict__[attr])
+ otherVersion = max(0, other.__dict__[attr])
+
+ if myVersion > otherVersion: return 1
+ elif myVersion < otherVersion: return -1
+
+ myStatus = self.status if self.status else ""
+ otherStatus = other.status if other.status else ""
+
+ return cmp(myStatus, otherStatus)
+
+def get_version(versionStr):
+ """
+ Parses a version string, providing back a types.Version instance.
+
+ Arguments:
+ versionStr (str) - string representing a tor version (ex. "0.2.2.23-alpha")
+
+ Returns:
+ types.Version instance
+
+ Throws:
+ ValueError if input isn't a valid tor version
+ """
+
+ if not isinstance(versionStr, str):
+ raise ValueError("argument is not a string")
+
+ m = re.match(r'^([0-9]+).([0-9]+).([0-9]+)(.[0-9]+)?(-\S*)?$', versionStr)
+
+ if m:
+ major, minor, micro, patch, status = m.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.
+
+ if patch: patch = int(patch[1:])
+ if status: status = status[1:]
+
+ return Version(int(major), int(minor), int(micro), patch, status)
+ else: raise ValueError("'%s' isn't a properly formatted tor version" % versionStr)
+
diff --git a/stem/types.pyc b/stem/types.pyc
new file mode 100644
index 0000000..27a5bb1
Binary files /dev/null and b/stem/types.pyc differ
diff --git a/test/__init__.py b/test/__init__.py
new file mode 100644
index 0000000..6d651bb
--- /dev/null
+++ b/test/__init__.py
@@ -0,0 +1,6 @@
+"""
+Unit and integration tests for the stem library.
+"""
+
+__all__ = ["version"]
+
diff --git a/test/__init__.pyc b/test/__init__.pyc
new file mode 100644
index 0000000..6b41a10
Binary files /dev/null and b/test/__init__.pyc differ
diff --git a/test/version.py b/test/version.py
new file mode 100644
index 0000000..fd32886
--- /dev/null
+++ b/test/version.py
@@ -0,0 +1,121 @@
+"""
+Unit tests for types functions and classes.
+"""
+
+import unittest
+import stem.types
+
+class TestVerionFunctions(unittest.TestCase):
+ """
+ Tests methods and functions related to 'types.Version'.
+ """
+
+ def test_parsing(self):
+ """
+ Tests parsing by the 'get_version' function.
+ """
+
+ # valid versions with various number of compontents to the version
+ version = stem.types.get_version("0.1.2.3-tag")
+ self.assert_versions_match(version, 0, 1, 2, 3, "tag")
+
+ version = stem.types.get_version("0.1.2.3")
+ self.assert_versions_match(version, 0, 1, 2, 3, None)
+
+ version = stem.types.get_version("0.1.2-tag")
+ self.assert_versions_match(version, 0, 1, 2, None, "tag")
+
+ version = stem.types.get_version("0.1.2")
+ self.assert_versions_match(version, 0, 1, 2, None, None)
+
+ # checks an empty tag
+ version = stem.types.get_version("0.1.2.3-")
+ self.assert_versions_match(version, 0, 1, 2, 3, "")
+
+ version = stem.types.get_version("0.1.2-")
+ self.assert_versions_match(version, 0, 1, 2, None, "")
+
+ # checks invalid version strings
+ self.assertRaises(ValueError, stem.types.get_version, "")
+ self.assertRaises(ValueError, stem.types.get_version, "1.2.3.4nodash")
+ self.assertRaises(ValueError, stem.types.get_version, "1.2.3.a")
+ self.assertRaises(ValueError, stem.types.get_version, "1.2.a.4")
+ self.assertRaises(ValueError, stem.types.get_version, "12.3")
+ self.assertRaises(ValueError, stem.types.get_version, "1.-2.3")
+
+ def test_comparison(self):
+ """
+ Tests comparision between Version instances.
+ """
+
+ # check for basic incrementing in each portion
+ self.assert_version_is_greater("1.1.2.3-tag", "0.1.2.3-tag")
+ self.assert_version_is_greater("0.2.2.3-tag", "0.1.2.3-tag")
+ self.assert_version_is_greater("0.1.3.3-tag", "0.1.2.3-tag")
+ self.assert_version_is_greater("0.1.2.4-tag", "0.1.2.3-tag")
+ self.assert_version_is_greater("0.1.2.3-ugg", "0.1.2.3-tag")
+ self.assert_version_is_equal("0.1.2.3-tag", "0.1.2.3-tag")
+
+ # checks that a missing patch level equals zero
+ self.assert_version_is_equal("0.1.2", "0.1.2.0")
+ self.assert_version_is_equal("0.1.2-tag", "0.1.2.0-tag")
+
+ # checks for missing patch or status
+ self.assert_version_is_greater("0.1.2.3-tag", "0.1.2.3")
+ self.assert_version_is_greater("0.1.2.3-tag", "0.1.2-tag")
+ self.assert_version_is_greater("0.1.2.3-tag", "0.1.2")
+
+ self.assert_version_is_equal("0.1.2.3", "0.1.2.3")
+ self.assert_version_is_equal("0.1.2", "0.1.2")
+
+ def test_string(self):
+ """
+ Tests the Version -> string conversion.
+ """
+
+ # checks conversion with various numbers of arguments
+
+ self.assert_string_matches("0.1.2.3-tag")
+ self.assert_string_matches("0.1.2.3")
+ self.assert_string_matches("0.1.2")
+
+ def assert_versions_match(self, version, major, minor, micro, patch, status):
+ """
+ Asserts that the values for a types.Version instance match the given
+ values.
+ """
+
+ self.assertEqual(version.major, major)
+ self.assertEqual(version.minor, minor)
+ self.assertEqual(version.micro, micro)
+ self.assertEqual(version.patch, patch)
+ self.assertEqual(version.status, status)
+
+ def assert_version_is_greater(self, firstVersion, secondVersion):
+ """
+ Asserts that the parsed version of the first version is greate than the
+ second (also checking the inverse).
+ """
+
+ version1 = stem.types.get_version(firstVersion)
+ version2 = stem.types.get_version(secondVersion)
+ self.assertEqual(version1 > version2, True)
+ self.assertEqual(version1 < version2, False)
+
+ def assert_version_is_equal(self, firstVersion, secondVersion):
+ """
+ Asserts that the parsed version of the first version equals the second.
+ """
+
+ version1 = stem.types.get_version(firstVersion)
+ version2 = stem.types.get_version(secondVersion)
+ self.assertEqual(version1, version2)
+
+ def assert_string_matches(self, version):
+ """
+ Parses the given version string then checks that its string representation
+ matches the input.
+ """
+
+ self.assertEqual(version, str(stem.types.get_version(version)))
+
diff --git a/test/version.pyc b/test/version.pyc
new file mode 100644
index 0000000..c459fa7
Binary files /dev/null and b/test/version.pyc differ
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits