import unittest import logging class Vendor(object): def __init__(self, vendor="Linaro"): if not vendor: raise TypeError("Vendor requires a vendor string.") if isinstance(vendor, basestring): self.vendor = vendor else: raise TypeError("Input 'vendor' must be of type basestring.") def __str__(self): return self.vendor def lower(self): return self.vendor.lower() class Version(object): # @major - required int or str representation of int. # @minor - optional int or str representation of int, otherwise None. # If None, then minor will not be output. # @point - optional int or str representation of int, otherwise None. # If None, then point will not be output. def __init__(self, major, minor=None, point=None): if isinstance(major, int) or isinstance(major, basestring): # This will throw an exception if 'major' is an empty string. self.major = int(major) else: raise TypeError("major must be of type int, string.") if isinstance(minor, int) or isinstance(minor, basestring): # This will throw an exception if 'minor' is an empty string. self.minor = int(minor) elif not minor: self.minor = None else: raise TypeError("minor must be of type int, string, or None.") if isinstance(point, int) or isinstance(point, basestring): # This is illegal, as it'd mess up the output and make it look like # there's a minor that's really a point. if not minor and point: raise RuntimeError( "minor must be specified if point is specified.") # This will throw an exception if 'minor' is an empty string. self.point = int(point) elif not point: self.point = None else: raise TypeError("point must be of type int, string, or None.") def __str__(self): ver = str(self.major) if self.minor: ver = ver + u'.' + str(self.minor) if self.point: ver = ver + u'.' + str(self.point) return ver # TODO: I'm sure there's a more pythonic way to do this but this is # quick and dirty. # %M - Major # %m - Minor # %p - Point # delimiter - Delimiter character to use in output: space or dash. # TODO: Use a dictionary with replace def strfversion(self, formatstr, delimiter='.'): toks = [str(x) for x in formatstr.split('%') if x.strip()] delstoks = len(toks) verstoks = 0 if self.major: verstoks = verstoks + 1 if self.minor: verstoks = verstoks + 1 if self.point: verstoks = verstoks + 1 if delstoks > verstoks: numtoks = verstoks - 1 else: numtoks = delstoks - 1 vers = u'' for tok in toks: if tok == 'M': vers = vers + str(self.major) elif tok == 'm': vers = vers + str(self.minor) elif tok == 'p': if self.point: vers = vers + str(self.point) if numtoks > 0: vers = vers + delimiter numtoks = numtoks - 1 return vers # Helper function which returns a Version. def versionFromStr(version): if not isinstance(version, basestring): raise TypeError('input must be of type basestring') major = version.split('.', 1)[0] # split('.',1) will return index error on "5" but will return empty string on "5." # Any empty string is not a valid input into Version. if major == u'': major = None try: minor = version.split('.', 2)[1] except IndexError: minor = None if minor == u'': minor = None try: point = version.split('.', 3)[2] except IndexError: point = None if point == u'': point = None return Version(major, minor, point) class Package(object): # @package - default = GCC # @version - required. Either a string representing a version or a Version # instance. def __init__(self, package="GCC", version=None): if not package or package == u'': raise TypeError("Package requires 'package' as a non-empty string") if isinstance(package, basestring): self.package = package else: raise TypeError("Input 'package' must be of type basestring.") if not version: raise RuntimeError("Package requires a version.") elif isinstance(version, Version): self.version = version else: self.version = versionFromStr(version) def get_package(self): return self.package def get_version(self): return str(self.version) def __str__(self): return self.package + u'-' + str(self.version) def lower(self): return self.package.lower() + u'-' + str(self.version) # TODO: Create format function which can change the separator to ' ' or to # '-'. def packageFromStr(package=None): if not isinstance(package, basestring): raise TypeError('packageFromStr requires a string as input') # Get the part before the version numbers. That's the package try: package_name = package.rsplit('-', 1)[0] except IndexError: raise RuntimeError('string must be -') try: package_version = package.rsplit('-', 1)[1] except IndexError: raise ValueError('string must be -') if package_name == u'': raise TypeError("Couldn't parse a package name from input string") if package_version == u'': raise TypeError("Couldn't parse a package version from input string") # This will throw exceptions if the input are malformed. package = Package(package_name, package_version) return package class Vers(object): def __init__(self, val=None): if val is None: self.val = 0 return if isinstance(val, int) or isinstance(val, basestring): # This should raise an exception if the string can't be converted # to an int. If val is already an int it's a nop. intval = int(val) if intval < 0: raise ValueError('Input val must not be negative') self.val = intval else: raise TypeError("Input val must be of type int or string.") def increment(self): self.val = self.val + 1 # Return the "-" string or an empty string. def __str__(self): # Don't return if self.val is None or self.val == 0: return "" else: return "-" + str(self.val) class Spin(Vers): def __init__(self, spin=None): try: super(Spin, self).__init__(spin) except ValueError: raise ValueError('Input spin must not be negative') class Rc(Vers): def __init__(self, rc=None): try: super(Rc, self).__init__(rc) except ValueError: raise ValueError('Input rc must not be negative') # The string representation differs slighty from Spin def __str__(self): # Don't return if self.val is None or self.val == 0: return "" else: return "-rc" + str(self.val) class TestVersion(unittest.TestCase): def test_no_major(self): with self.assertRaises(TypeError): version = Version(major=None) with self.assertRaises(TypeError): version = Version() def test_empty_major(self): with self.assertRaises(ValueError): version = Version(major="") def test_empty_minor(self): with self.assertRaises(ValueError): version = Version(major=5, minor="") def test_empty_point(self): with self.assertRaises(ValueError): version = Version(major=5, minor=3, point="") def test_non_int_major(self): with self.assertRaises(ValueError): version = Version('A') def test_int_major(self): version = Version(5) self.assertEqual(str(version), "5") version2 = Version(major=5) self.assertEqual(str(version2), "5") def test_intstr_major(self): version = Version("5") self.assertEqual(str(version), "5") version2 = Version(major="5") self.assertEqual(str(version2), "5") def test_non_int_minor(self): with self.assertRaises(ValueError): version = Version(major="5", minor="A") def test_int_minor(self): version = Version(major=5, minor=3) self.assertEqual(str(version), "5.3") def test_intstr_minor(self): version = Version(major="5", minor="3") self.assertEqual(str(version), "5.3") def test_no_minor(self): version = Version(major="5", minor=None) self.assertEqual(str(version), "5") def test_point_no_minor(self): with self.assertRaises(RuntimeError): version = Version(major=5, minor=None, point=1) def test_int_point(self): version = Version(major=5, minor=3, point=1) self.assertEqual(str(version), "5.3.1") def test_non_int_point(self): with self.assertRaises(ValueError): version = Version(major=5, minor=3, point="A") def test_intstr_point(self): version = Version(major="5", minor="3", point="1") self.assertEqual(str(version), "5.3.1") def test_no_point(self): version = Version(major="5", minor="3", point=None) self.assertEqual(str(version), "5.3") def test_strfversion(self): version = Version(major="5", minor="3", point="1") self.assertEqual(version.strfversion("%M%m%p", delimiter='-'), "5-3-1") self.assertEqual(version.strfversion("%M%m%p"), "5.3.1") class TestVendor(unittest.TestCase): def test_vendor_default(self): vendor = Vendor() self.assertEqual(str(vendor), "Linaro") self.assertEqual(vendor.lower(), "linaro") def test_none_input(self): with self.assertRaises(TypeError): vendor = Vendor(vendor=None) def test_nonstring_input(self): with self.assertRaises(TypeError): vendor = Vendor(vendor=int(1)) def test_str_input(self): vendor = Vendor("TestVendor") self.assertEqual(str(vendor), "TestVendor") self.assertEqual(vendor.lower(), "testvendor") class TestPackage(unittest.TestCase): def test_package_no_version(self): with self.assertRaises(RuntimeError): # We require a version. package = Package() def test_package_default(self): package = Package(version="5.3.1") self.assertEqual(str(package), "GCC-5.3.1") self.assertEqual(package.lower(), "gcc-5.3.1") self.assertEqual(package.package, "GCC") def test_none_package(self): with self.assertRaises(TypeError): package = Package(package=None, version="5.3.1") def test_none_version(self): with self.assertRaises(RuntimeError): package = Package(package="GCC", version=None) def test_with_Version(self): version = Version(5, 3, 1) package = Package(version=version) self.assertEqual(str(package), "GCC-5.3.1") self.assertEqual(package.lower(), "gcc-5.3.1") def test_package_version(self): version = Version(5, 3, 1) package = Package(version=version) self.assertEqual(str(package.version), "5.3.1") self.assertEqual(package.get_version(), "5.3.1") self.assertEqual(package.get_package(), "GCC") def test_str_input(self): package = Package("TestPackage", version="5.3.1") self.assertEqual(str(package), "TestPackage-5.3.1") self.assertEqual(package.lower(), "testpackage-5.3.1") def test_empty_package_name(self): with self.assertRaises(TypeError): package = Package(package="", version="5.3.1") class TestSpin(unittest.TestCase): def test_spin_val(self): spin = Spin(1) self.assertEqual(spin.val, 1) def test_spin_val_str(self): spin = Spin(1) self.assertEqual(str(spin), "-1") def test_spin_increment_val(self): spin = Spin(1) spin.increment() self.assertEqual(spin.val, 2) def test_spin_increment_str(self): spin = Spin(1) spin.increment() self.assertEqual(str(spin), "-2") def test_zero_spin(self): spin = Spin(0) self.assertEqual(spin.val, 0) def test_zero_spin_str(self): spin = Spin(0) self.assertEqual(str(spin), "") def test_none_spin(self): spin = Spin(None) self.assertEqual(spin.val, 0) def test_none_spin_increment(self): spin = Spin(None) spin.increment() self.assertEqual(spin.val, 1) def test_none_spin_str(self): spin = Spin(None) self.assertEqual(str(spin), "") def test_default_spin(self): spin = Spin() self.assertEqual(spin.val, 0) def test_default_spin_str(self): spin = Spin() self.assertEqual(str(spin), "") def test_negative_val(self): with self.assertRaises(ValueError): spin = Spin(-1) def test_default_spin_str(self): spin = Spin() self.assertEqual(str(spin), "") def test_spin_string_input(self): spin = Spin("9") self.assertEqual(spin.val, 9) self.assertEqual(str(spin), "-9") def test_spin_negative_string_input(self): with self.assertRaises(ValueError): spin = Spin("-9") def test_float_type(self): with self.assertRaises(TypeError): spin = Spin(7.0) class TestRc(unittest.TestCase): def test_rc_val(self): rc = Rc(1) self.assertEqual(rc.val, 1) def test_rc_str(self): rc = Rc(1) self.assertEqual(str(rc), "-rc1") def test_negative_val(self): with self.assertRaises(ValueError): rc = Rc(-1) def test_zero_rc_str(self): rc = Rc(0) self.assertEqual(str(rc), "") def test_none_rc_str(self): rc = Rc(None) self.assertEqual(str(rc), "") def test_default_rc_str(self): rc = Rc() self.assertEqual(str(rc), "") def test_rc_increment_val(self): rc = Rc(1) rc.increment() self.assertEqual(rc.val, 2) def test_rc_increment_str(self): rc = Rc(1) rc.increment() self.assertEqual(str(rc), "-rc2") def test_none_rc_increment_str(self): rc = Rc(None) rc.increment() self.assertEqual(str(rc), "-rc1") def test_default_rc_str(self): rc = Rc() self.assertEqual(str(rc), "") def test_rc_string_input(self): rc = Rc("9") self.assertEqual(rc.val, 9) self.assertEqual(str(rc), "-rc9") def test_rc_negative_string_input(self): with self.assertRaises(ValueError): rc = Rc("-9") def test_float_type(self): with self.assertRaises(TypeError): rc = Rc(7.0) class TestPackageFromString(unittest.TestCase): def test_none(self): with self.assertRaises(TypeError): package = packageFromStr(package=None) def test_empty_str_package(self): with self.assertRaises(ValueError): package = packageFromStr(package=u"") def test_with_package(self): package = Package("GCC", "5.3.1") with self.assertRaises(TypeError): package = packageFromStr(package=package) def test_with_no_package_name(self): with self.assertRaises(TypeError): package = packageFromStr(package="-5.3.1") with self.assertRaises(ValueError): package = packageFromStr(package="5.3.1") def test_with_no_package_version(self): with self.assertRaises(TypeError): package = packageFromStr(package="GCC-") with self.assertRaises(ValueError): package = packageFromStr(package="GCC") def test_with_space(self): with self.assertRaises(ValueError): package = packageFromStr(package="GCC 5.3.1") def test_correct_usage(self): package = packageFromStr(package="GCC-5.3.1") self.assertEqual(str(package), "GCC-5.3.1") self.assertEqual(package.lower(), "gcc-5.3.1") self.assertEqual(package.package, "GCC") self.assertEqual(str(package.version), "5.3.1") self.assertEqual(package.version.major, 5) self.assertEqual(package.version.minor, 3) self.assertEqual(package.version.point, 1) class TestVersionFromStr(unittest.TestCase): def test_extra_dot(self): version = versionFromStr("5.3.1.4") self.assertEqual(version.major, 5) self.assertEqual(version.minor, 3) self.assertEqual(version.point, 1) def test_major_minor_point(self): version = versionFromStr("5.3.1") self.assertEqual(version.major, 5) self.assertEqual(version.minor, 3) self.assertEqual(version.point, 1) def test_major_minor_dot(self): version = versionFromStr("5.3.") self.assertEqual(version.major, 5) self.assertEqual(version.minor, 3) self.assertEqual(version.point, None) def test_major_minor(self): version = versionFromStr("5.3") self.assertEqual(version.major, 5) self.assertEqual(version.minor, 3) self.assertEqual(version.point, None) def test_major_dot(self): version = versionFromStr("5.") self.assertEqual(version.major, 5) self.assertEqual(version.minor, None) self.assertEqual(version.point, None) def test_major(self): version = versionFromStr("5") self.assertEqual(version.major, 5) self.assertEqual(version.minor, None) self.assertEqual(version.point, None) def test_empty(self): with self.assertRaises(TypeError): version = versionFromStr("") def test_non_int_major(self): with self.assertRaises(ValueError): version = versionFromStr("a.b.c") def test_non_int_minor(self): with self.assertRaises(ValueError): version = versionFromStr("5.b.1") def test_non_int_point(self): with self.assertRaises(ValueError): version = versionFromStr("5.3.a") def test_non_string(self): version = Version(5, 3, 1) with self.assertRaises(TypeError): version = versionFromStr(version) def test_none(self): with self.assertRaises(TypeError): version = versionFromStr(version=None) if __name__ == '__main__': # logging.basicConfig(level="INFO") unittest.main()