Diff
Modified: trunk/Tools/ChangeLog (225015 => 225016)
--- trunk/Tools/ChangeLog 2017-11-18 14:09:50 UTC (rev 225015)
+++ trunk/Tools/ChangeLog 2017-11-18 15:17:02 UTC (rev 225016)
@@ -1,3 +1,54 @@
+2017-11-18 Jonathan Bedard <[email protected]>
+
+ webkitpy: Better name-version mapping (Part 1)
+ https://bugs.webkit.org/show_bug.cgi?id=179621
+ <rdar://problem/35589585>
+
+ Reviewed by David Kilzer.
+
+ Mapping version numbers to version names should occur in a central location.
+ This has a few advantages. First, it makes iterating through versions easier.
+ Second, it allows for apple_additions to define an additional set of name
+ mappings. Lastly, it will allow, in a future patch, for us to track version
+ instead of version name, only mapping version to version name when required.
+
+ * Scripts/webkitpy/common/system/platforminfo.py:
+ (PlatformInfo.__init__):
+ (PlatformInfo._determine_os_name): Use VersionNameMap instead of custom functions
+ mapping version to name.
+ (PlatformInfo._determine_linux_version): Deleted.
+ (PlatformInfo._determine_mac_version): Deleted.
+ (PlatformInfo._determine_win_version): Deleted.
+ * Scripts/webkitpy/common/system/platforminfo_unittest.py:
+ (TestPlatformInfo.test_os_name_and_wrappers):
+ (TestPlatformInfo.test_os_version):
+ (TestPlatformInfo.test_display_name):
+ (TestPlatformInfo.test_total_bytes_memory):
+ * Scripts/webkitpy/common/version.py:
+ (Version.contained_in): Add partial version mapping.
+ * Scripts/webkitpy/common/version_name_map.py: Added.
+ (VersionNameMap): Holds a mapping of version name to version object.
+ (VersionNameMap.map): Don't re-create VersionNameMap every time.
+ (VersionNameMap.__init__): Initialize mapping, use platform to
+ define the default system platform.
+ (VersionNameMap._automap_to_major_version): Some operating systems, such
+ as iOS, have a naming scheme based on their major version and os name.
+ Automatically generate such mappings.
+ (VersionNameMap.to_name): Given a version object, platform name and
+ table, find the closest matching version name.
+ (VersionNameMap.strip_name_formatting): Remove spaces and extract the major version,
+ if a version string is included in the name.
+ (VersionNameMap.from_name): Return an os name and version given a version name.
+ * Scripts/webkitpy/common/version_name_map_unittest.py: Added.
+ (VersionMapTestCase):
+ (VersionMapTestCase.test_default_system_platform):
+ (VersionMapTestCase.test_mac_version_by_name):
+ (VersionMapTestCase.test_ios_version_by_name):
+ (VersionMapTestCase.test_mac_name_by_version):
+ (VersionMapTestCase.test_ios_name_by_version):
+ * Scripts/webkitpy/common/version_unittest.py:
+ (VersionTestCase.test_contained_in):
+
2017-11-17 John Wilander <[email protected]>
Storage Access API: UI process should update network process about granted access
Modified: trunk/Tools/Scripts/webkitpy/common/system/platforminfo.py (225015 => 225016)
--- trunk/Tools/Scripts/webkitpy/common/system/platforminfo.py 2017-11-18 14:09:50 UTC (rev 225015)
+++ trunk/Tools/Scripts/webkitpy/common/system/platforminfo.py 2017-11-18 15:17:02 UTC (rev 225016)
@@ -31,6 +31,7 @@
import sys
from webkitpy.common.version import Version
+from webkitpy.common.version_name_map import VersionNameMap
from webkitpy.common.system.executive import Executive
@@ -51,14 +52,21 @@
self._executive = executive
self._platform_module = platform_module
self.os_name = self._determine_os_name(sys_module.platform)
- if self.os_name == 'linux':
- self.os_version = self._determine_linux_version()
- if self.os_name == 'freebsd' or self.os_name == 'openbsd' or self.os_name == 'netbsd' or self.os_name == 'ios':
- self.os_version = platform_module.release()
+ self.os_version = None
+
if self.os_name.startswith('mac'):
- self.os_version = self._determine_mac_version(Version(platform_module.mac_ver()[0]))
- if self.os_name.startswith('win'):
- self.os_version = self._determine_win_version(self._win_version(sys_module))
+ self.os_version = VersionNameMap.map(self).to_name(Version(platform_module.mac_ver()[0]), table='public')
+ elif self.os_name.startswith('win'):
+ self.os_version = VersionNameMap.map(self).to_name(self._win_version(sys_module), table='public')
+ elif self.os_name == 'freebsd':
+ self.os_version = VersionNameMap.map(self).to_name(platform_module.release().split('-')[0], table='public')
+ else:
+ # Most other platforms (namely Linux and iOS) return conforming version strings.
+ self.os_version = VersionNameMap.map(self).to_name(Version(platform_module.release()), table='public')
+
+ assert self.os_version is not None
+ self.os_version = self.os_version.lower().replace(' ', '')
+
self._is_cygwin = sys_module.platform == 'cygwin'
def is_mac(self):
@@ -164,40 +172,6 @@
return 'haiku'
raise AssertionError('unrecognized platform string "%s"' % sys_platform)
- def _determine_mac_version(self, mac_version):
- version_strings = {
- 5: 'leopard',
- 6: 'snowleopard',
- 7: 'lion',
- 8: 'mountainlion',
- 9: 'mavericks',
- 10: 'yosemite',
- 11: 'elcapitan',
- 12: 'sierra',
- 13: 'highsierra',
- }
- assert mac_version.minor >= min(version_strings.keys())
- return version_strings.get(mac_version.minor, 'future')
-
- def _determine_linux_version(self):
- # FIXME: we ignore whatever the real version is and pretend it's lucid for now.
- return 'lucid'
-
- def _determine_win_version(self, win_version):
- if self._platform_module.release() == '10':
- return 'win10'
- if win_version.major == 0 and win_version.minor == 0:
- if win_version[2] > 10000:
- return 'win10'
- if win_version == Version([6, 1, 7600]):
- return '7sp0'
- if win_version.major == 6 and win_version.minor == 0:
- return 'vista'
- if win_version.major == 5 and win_version.minor == 1:
- return 'xp'
- assert win_version[0] > 6 or win_version[1] >= 1, 'Unrecognized Windows version: "{}"'.format(win_version)
- return 'future'
-
def _win_version(self, sys_module):
if hasattr(sys_module, 'getwindowsversion'):
return Version(sys_module.getwindowsversion()[0:3])
Modified: trunk/Tools/Scripts/webkitpy/common/system/platforminfo_unittest.py (225015 => 225016)
--- trunk/Tools/Scripts/webkitpy/common/system/platforminfo_unittest.py 2017-11-18 14:09:50 UTC (rev 225015)
+++ trunk/Tools/Scripts/webkitpy/common/system/platforminfo_unittest.py 2017-11-18 15:17:02 UTC (rev 225016)
@@ -87,13 +87,13 @@
self.assertIsNone(info.total_bytes_memory())
def test_os_name_and_wrappers(self):
- info = self.make_info(fake_sys('linux2'))
+ info = self.make_info(fake_sys('linux2'), fake_platform('', '10.4'))
self.assertTrue(info.is_linux())
self.assertFalse(info.is_mac())
self.assertFalse(info.is_win())
self.assertFalse(info.is_freebsd())
- info = self.make_info(fake_sys('linux3'))
+ info = self.make_info(fake_sys('linux3'), fake_platform('', '10.4'))
self.assertTrue(info.is_linux())
self.assertFalse(info.is_mac())
self.assertFalse(info.is_win())
@@ -122,7 +122,7 @@
self.assertFalse(info.is_native_win())
self.assertFalse(info.is_freebsd())
- info = self.make_info(fake_sys('freebsd8'))
+ info = self.make_info(fake_sys('freebsd8'), fake_platform('', '8.3-PRERELEASE'))
self.assertEqual(info.os_name, 'freebsd')
self.assertFalse(info.is_linux())
self.assertFalse(info.is_mac())
@@ -144,19 +144,20 @@
self.assertEqual(self.make_info(fake_sys('darwin'), fake_platform('10.13.0')).os_version, 'highsierra')
self.assertEqual(self.make_info(fake_sys('darwin'), fake_platform('10.14.0')).os_version, 'future')
- self.assertEqual(self.make_info(fake_sys('linux2')).os_version, 'lucid')
+ self.assertEqual(self.make_info(fake_sys('linux2'), fake_platform('', '10.4')).os_version, 'lucid')
- self.assertEqual(self.make_info(fake_sys('freebsd8'), fake_platform('', '8.3-PRERELEASE')).os_version, '8.3-PRERELEASE')
- self.assertEqual(self.make_info(fake_sys('freebsd9'), fake_platform('', '9.0-RELEASE')).os_version, '9.0-RELEASE')
+ self.assertEqual(self.make_info(fake_sys('freebsd8'), fake_platform('', '8.3-PRERELEASE')).os_version, 'freebsd8')
+ self.assertEqual(self.make_info(fake_sys('freebsd9'), fake_platform('', '9.0-RELEASE')).os_version, 'freebsd9')
self.assertRaises(AssertionError, self.make_info, fake_sys('win32', tuple([5, 0, 1234])))
- self.assertEqual(self.make_info(fake_sys('win32', tuple([6, 2, 1234]))).os_version, 'future')
+ self.assertEqual(self.make_info(fake_sys('win32', tuple([10, 0, 14393]))).os_version, 'win10')
+ self.assertEqual(self.make_info(fake_sys('win32', tuple([6, 2, 1234]))).os_version, '8')
self.assertEqual(self.make_info(fake_sys('win32', tuple([6, 1, 7600]))).os_version, '7sp0')
self.assertEqual(self.make_info(fake_sys('win32', tuple([6, 0, 1234]))).os_version, 'vista')
self.assertEqual(self.make_info(fake_sys('win32', tuple([5, 1, 1234]))).os_version, 'xp')
self.assertRaises(AssertionError, self.make_info, fake_sys('win32'), executive=fake_executive('5.0.1234'))
- self.assertEqual(self.make_info(fake_sys('cygwin'), executive=fake_executive('6.2.1234')).os_version, 'future')
+ self.assertEqual(self.make_info(fake_sys('cygwin'), executive=fake_executive('6.2.1234')).os_version, '8')
self.assertEqual(self.make_info(fake_sys('cygwin'), executive=fake_executive('6.1.7600')).os_version, '7sp0')
self.assertEqual(self.make_info(fake_sys('cygwin'), executive=fake_executive('6.0.1234')).os_version, 'vista')
self.assertEqual(self.make_info(fake_sys('cygwin'), executive=fake_executive('5.1.1234')).os_version, 'xp')
@@ -168,10 +169,10 @@
info = self.make_info(fake_sys('win32', tuple([6, 1, 7600])))
self.assertNotEquals(info.display_name(), '')
- info = self.make_info(fake_sys('linux2'))
+ info = self.make_info(fake_sys('linux2'), fake_platform('', '10.4'))
self.assertNotEquals(info.display_name(), '')
- info = self.make_info(fake_sys('freebsd9'))
+ info = self.make_info(fake_sys('freebsd9'), fake_platform('', '9.0-RELEASE'))
self.assertNotEquals(info.display_name(), '')
def test_total_bytes_memory(self):
@@ -181,8 +182,8 @@
info = self.make_info(fake_sys('win32', tuple([6, 1, 7600])))
self.assertIsNone(info.total_bytes_memory())
- info = self.make_info(fake_sys('linux2'))
+ info = self.make_info(fake_sys('linux2'), fake_platform('', '10.4'))
self.assertIsNone(info.total_bytes_memory())
- info = self.make_info(fake_sys('freebsd9'))
+ info = self.make_info(fake_sys('freebsd9'), fake_platform('', '9.0-RELEASE'))
self.assertIsNone(info.total_bytes_memory())
Modified: trunk/Tools/Scripts/webkitpy/common/version.py (225015 => 225016)
--- trunk/Tools/Scripts/webkitpy/common/version.py 2017-11-18 14:09:50 UTC (rev 225015)
+++ trunk/Tools/Scripts/webkitpy/common/version.py 2017-11-18 15:17:02 UTC (rev 225016)
@@ -92,6 +92,16 @@
raise ValueError('Version key must be major, minor, tiny, micro or nano')
raise ValueError('Expected version key to be string or integer')
+ # 11.2 is contained in 11, but 11 is not contained in 11.2
+ def contained_in(self, version):
+ does_match = True
+ for i in xrange(len(self)):
+ if self[i] != version[i]:
+ does_match = False
+ if not does_match and version[i] != 0:
+ return False
+ return True
+
def __str__(self):
len_to_print = 1
for i in xrange(len(self)):
Added: trunk/Tools/Scripts/webkitpy/common/version_name_map.py (0 => 225016)
--- trunk/Tools/Scripts/webkitpy/common/version_name_map.py (rev 0)
+++ trunk/Tools/Scripts/webkitpy/common/version_name_map.py 2017-11-18 15:17:02 UTC (rev 225016)
@@ -0,0 +1,146 @@
+# Copyright (C) 2017 Apple Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import re
+
+from webkitpy.common.memoized import memoized
+from webkitpy.common.version import Version
+
+
+class VersionNameMap(object):
+
+ # Allows apple_additions to define a custom mapping
+ @staticmethod
+ @memoized
+ def map(platform=None):
+ return VersionNameMap(platform=platform)
+
+ def __init__(self, platform=None):
+ if platform is None:
+ from webkitpy.common.system.systemhost import SystemHost
+ platform = SystemHost().platform
+ self.mapping = {}
+
+ self.default_system_platform = platform.os_name
+ self.mapping['public'] = {
+ 'mac': {
+ 'Leopard': Version('10.5'),
+ 'Snow Leopard': Version('10.6'),
+ 'Lion': Version('10.7'),
+ 'Mountain Lion': Version('10.8'),
+ 'Mavericks': Version('10.9'),
+ 'Yosemite': Version('10.10'),
+ 'El Capitan': Version('10.11'),
+ 'Sierra': Version('10.12'),
+ 'High Sierra': Version('10.13'),
+ 'Future': Version('10.14'),
+ },
+ 'ios': self._automap_to_major_version('iOS', minimum=Version('10'), maximum=Version('11')),
+ 'win': {
+ 'Win10': Version('10'),
+ '8.1': Version('6.3'),
+ '8': Version('6.2'),
+ '7sp0': Version('6.1.7600'),
+ 'Vista': Version('6'),
+ 'XP': Version('5.1'),
+ },
+ 'linux': {
+ 'Lucid': Version('10.4'),
+ 'Maverick': Version('10.10'),
+ 'Natty': Version('11.4'),
+ 'Precise': Version('12.4'),
+ 'Quantal': Version('12.10'),
+ 'Raring': Version('13.4'),
+ 'Saucy': Version('13.10'),
+ 'Trusty': Version('14.4'),
+ 'Utopic': Version('14.10'),
+ 'Vivid': Version('15.04'),
+ 'Wily': Version('15.10'),
+ 'Xenial': Version('16.4'),
+ 'Yakkety': Version('16.10'),
+ 'Zesty': Version('17.4'),
+ 'Artful': Version('17.10'),
+ 'Bionic': Version('18.04'),
+ },
+ 'freebsd': {
+ 'Free BSD 8': Version('8'),
+ 'Free BSD 9': Version('9'),
+ }
+ }
+
+ @classmethod
+ def _automap_to_major_version(cls, prefix, minimum=Version('1'), maximum=Version('1')):
+ result = {}
+ assert minimum <= maximum
+ for i in xrange((maximum.major + 1) - minimum.major):
+ result['{} {}'.format(prefix, str(Version(str(minimum.major + i))))] = Version(str(minimum.major + i))
+ return result
+
+ def to_name(self, version, platform=None, table='public'):
+ platform = self.default_system_platform if platform is None else platform
+ assert table in self.mapping
+ assert platform in self.mapping[table]
+ closest_match = (None, None)
+ version = Version(version)
+ for os_name, os_version in self.mapping[table][platform].iteritems():
+ if version == os_version:
+ return os_name
+ elif version.contained_in(os_version):
+ if closest_match[1] and closest_match[1].contained_in(os_version):
+ continue
+ closest_match = (os_name, os_version)
+ return closest_match[0]
+
+ @staticmethod
+ def strip_name_formatting(name):
+ # <OS> major.minor.tiny should map to <OS> major
+ if ' ' in name:
+ try:
+ name = '{}{}'.format(''.join(name.split(' ')[:-1]), Version(name.split(' ')[-1]).major)
+ except ValueError:
+ pass
+ else:
+ try:
+ split = re.split(r'\d', name)
+ name = '{}{}'.format(split[0], Version(name[(len(split) - 1):]).major)
+ except ValueError:
+ pass
+
+ # Strip out any spaces, make everything lower-case
+ result = name.replace(' ', '').lower()
+ return result
+
+ def from_name(self, name):
+ # Exact match
+ for _, map in self.mapping.iteritems():
+ for os_name, os_map in map.iteritems():
+ if name in os_map:
+ return (os_name, os_map[name])
+
+ # It's not an exact match, let's try unifying formatting
+ unformatted = self.strip_name_formatting(name)
+ for _, map in self.mapping.iteritems():
+ for os_name, os_map in map.iteritems():
+ for version_name, version in os_map.iteritems():
+ if self.strip_name_formatting(version_name) == unformatted:
+ return (os_name, version)
+ return (None, None)
Added: trunk/Tools/Scripts/webkitpy/common/version_name_map_unittest.py (0 => 225016)
--- trunk/Tools/Scripts/webkitpy/common/version_name_map_unittest.py (rev 0)
+++ trunk/Tools/Scripts/webkitpy/common/version_name_map_unittest.py 2017-11-18 15:17:02 UTC (rev 225016)
@@ -0,0 +1,63 @@
+# Copyright (C) 2017 Apple Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import unittest
+
+from webkitpy.common.system.systemhost import SystemHost
+from webkitpy.common.version import Version
+from version_name_map import VersionNameMap
+
+
+class VersionMapTestCase(unittest.TestCase):
+
+ def test_default_system_platform(self):
+ host = SystemHost()
+ map = VersionNameMap(platform=host.platform)
+ self.assertEqual(map.default_system_platform, host.platform.os_name)
+
+ def test_mac_version_by_name(self):
+ map = VersionNameMap()
+ self.assertEqual(('mac', Version('10.12')), map.from_name('Sierra'))
+ self.assertEqual(('mac', Version('10.12')), map.from_name('sierra'))
+ self.assertEqual(('mac', Version('10.11')), map.from_name('El Capitan'))
+ self.assertEqual(('mac', Version('10.11')), map.from_name('elcapitan'))
+ self.assertEqual(('mac', Version('10.11')), map.from_name('el Capitan'))
+
+ def test_ios_version_by_name(self):
+ map = VersionNameMap()
+ self.assertEqual(('ios', Version(11)), map.from_name('iOS 11'))
+ self.assertEqual(('ios', Version(11)), map.from_name('ios11'))
+ self.assertEqual(('ios', Version(11)), map.from_name('iOS 11.2'))
+ self.assertEqual(('ios', Version(11)), map.from_name('ios11.2'))
+ self.assertEqual(('ios', Version(11)), map.from_name('iOS11.2'))
+
+ def test_mac_name_by_version(self):
+ map = VersionNameMap()
+ self.assertEqual('Sierra', map.to_name(version=Version('10.12'), platform='mac'))
+ self.assertEqual('El Capitan', map.to_name(version=Version('10.11'), platform='mac'))
+ self.assertEqual('El Capitan', map.to_name(version=Version('10.11.3'), platform='mac'))
+
+ def test_ios_name_by_version(self):
+ map = VersionNameMap()
+ self.assertEqual('iOS 11', map.to_name(version=Version('11'), platform='ios'))
+ self.assertEqual('iOS 10', map.to_name(version=Version('10'), platform='ios'))
+ self.assertEqual('iOS 10', map.to_name(version=Version('10.3'), platform='ios'))
Modified: trunk/Tools/Scripts/webkitpy/common/version_unittest.py (225015 => 225016)
--- trunk/Tools/Scripts/webkitpy/common/version_unittest.py 2017-11-18 14:09:50 UTC (rev 225015)
+++ trunk/Tools/Scripts/webkitpy/common/version_unittest.py 2017-11-18 15:17:02 UTC (rev 225016)
@@ -125,6 +125,22 @@
self.assertEqual(str(Version('1.2')), '1.2')
self.assertEqual(str(Version('0.0.3')), '0.0.3')
+ def test_contained_in(self):
+ self.assertTrue(Version('11.1').contained_in(Version('11')))
+ self.assertTrue(Version('11.1.2').contained_in(Version('11.1')))
+ self.assertFalse(Version('11').contained_in(Version('11.1')))
+ self.assertFalse(Version('11').contained_in(Version('11.1.2')))
+ self.assertFalse(Version('11.1').contained_in(Version('11.1.2')))
+ self.assertTrue(Version('11').contained_in(Version('11')))
+ self.assertTrue(Version('11.1').contained_in(Version('11.1')))
+ self.assertTrue(Version('11.1.2').contained_in(Version('11.1.2')))
+ self.assertTrue(Version('11').contained_in(Version('11.0')))
+ self.assertTrue(Version('11.0').contained_in(Version('11')))
+ self.assertTrue(Version('11').contained_in(Version('11.0.0')))
+ self.assertTrue(Version('11.0.0').contained_in(Version('11')))
+ self.assertTrue(Version('11.1').contained_in(Version('11.1.0')))
+ self.assertTrue(Version('11.1.0').contained_in(Version('11.1')))
+
def test_compare_versions(self):
self.assertEqual(Version('1.2.3'), Version('1.2.3'))
self.assertGreater(Version('1.2.4'), Version('1.2.3'))