From 71e86d904d62328e710bff0f36fc30fd7945260e Mon Sep 17 00:00:00 2001 From: Vincent Esposito Date: Mon, 30 Nov 2020 17:15:38 +0100 Subject: [PATCH 1/5] Improve version handling to be on par with imcsdk --- ucsmsdk/ucscoremeta.py | 89 +++++++++++++++++++++++++++++++++++------- 1 file changed, 75 insertions(+), 14 deletions(-) diff --git a/ucsmsdk/ucscoremeta.py b/ucsmsdk/ucscoremeta.py index 7681047e..729b3f0b 100644 --- a/ucsmsdk/ucscoremeta.py +++ b/ucsmsdk/ucscoremeta.py @@ -42,17 +42,18 @@ def __init__(self, version): return None self.__version = version + self.__major = None + self.__minor = None + self.__mr = None + self.__patch = None + self.__spin = None match_pattern = re.compile("^(?P[1-9][0-9]{0,2})\." "(?P(([0-9])|([1-9][0-9]{0,1})))\(" "(?P(([0-9])|([1-9][0-9]{0,2})))\." "(?P(([0-9])|([1-9][0-9]{0,4})))\)$") match_obj = re.match(match_pattern, version) - if match_obj: - self.__major = match_obj.group("major") - self.__minor = match_obj.group("minor") - self.__mr = match_obj.group("mr") - self.__patch = match_obj.group("patch") + if self._set_versions(match_obj): return match_pattern = re.compile("^(?P[1-9][0-9]{0,2})\." @@ -60,23 +61,69 @@ def __init__(self, version): "(?P(([0-9])|([1-9][0-9]{0,2})))" "(?P[a-z])\)$") match_obj = re.match(match_pattern, version) - if match_obj: - self.__major = match_obj.group("major") - self.__minor = match_obj.group("minor") - self.__mr = match_obj.group("mr") - self.__patch = match_obj.group("patch") + if self._set_versions(match_obj): return match_pattern = re.compile("^(?P[1-9][0-9]{0,2})\." "(?P(([0-9])|([1-9][0-9]{0,1})))\(" "(?P(([0-9])|([1-9][0-9]{0,2})))\)$") match_obj = re.match(match_pattern, version) - if match_obj: - self.__major = match_obj.group("major") - self.__minor = match_obj.group("minor") - self.__mr = match_obj.group("mr") + if self._set_versions(match_obj): return + # handle spin builds "2.0(13aS1))" + match_pattern = re.compile("^(?P[1-9][0-9]{0,2})\." + "(?P(([0-9])|([1-9][0-9]{0,1})))\(" + "(?P(([0-9])|([1-9][0-9]{0,2})))" + "(?P[a-z])" + "(?PS[1-9][0-9]{0,2})\)$") + match_obj = re.match(match_pattern, version) + if self._set_versions(match_obj): + return + + # handle spin builds "3.0(1S10))" + match_pattern = re.compile("^(?P[1-9][0-9]{0,2})\." + "(?P(([0-9])|([1-9][0-9]{0,1})))\(" + "(?P(([0-9])|([1-9][0-9]{0,2})))" + "(?PS[1-9][0-9]{0,2})\)$") + match_obj = re.match(match_pattern, version) + if self._set_versions(match_obj): + return + + # handle de special builds "66.77(67.1582251418)" + match_pattern = re.compile("^(?P[1-9][0-9]{0,2})\." + "(?P(([0-9])|([1-9][0-9]{0,2})))\(" + "(?P(([0-9])|([1-9][0-9]{0,2})))\." + "(?P(([0-9])|([1-9][0-9]{0,})))\)$") + match_obj = re.match(match_pattern, version) + if self._set_versions(match_obj): + return + + def _set_versions(self, match_obj): + if not match_obj: + return False + + match_dict = match_obj.groupdict() + self.__major = match_dict.get("major") + self.__minor = match_dict.get("minor") + self.__mr = match_dict.get("mr") + self.__patch = match_dict.get("patch") + self.__spin = match_dict.get("spin") + + # for spin builds 4.0(1S52), the patch version will be None + # In this scenario assume the version to be highest patch z + if self.__spin is not None and self.__patch is None: + self.__patch = 'z' + elif self.__patch is not None and self.__mr is not None and self.__patch.isdigit() and self.__mr.isdigit(): + log.debug("Interim version encountered: %s. MR version has been bumped up." % self.version) + self.__mr = str(int(self.__mr) + 1) + self.__patch = 'a' + elif self.__patch is not None and self.__patch.isalpha() and self.__spin: + log.debug("Interim version encountered: %s. patch version has been bumped up." % self.version) + self.__patch = str(chr(ord(self.__patch) + 1)) + + return True + @property def major(self): """Getter Method of UcsVersion Class""" @@ -102,6 +149,17 @@ def version(self): """Getter Method of UcsVersion Class""" return self.__version + def _compare(self, version1, version2): + if version1 == version2: + return 0 + if not version1: + return -1 + if not version2: + return 1 + + func = (ord, int)[version1.isdigit() and version2.isdigit()] + return func(version1) - func(version2) + def compare_to(self, version): """Method to compare UcsVersion.""" if version is None or not isinstance(version, UcsVersion): @@ -130,6 +188,9 @@ def __le__(self, version): def __eq__(self, version): return self.compare_to(version) == 0 + def __ne__(self, version): + return self.compare_to(version) != 0 + def __str__(self): return self.__version From e698a43416ba55725b5d694ab456e96c38fb906e Mon Sep 17 00:00:00 2001 From: Vincent Esposito Date: Mon, 30 Nov 2020 17:52:17 +0100 Subject: [PATCH 2/5] Fix version comparison method --- ucsmsdk/ucscoremeta.py | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/ucsmsdk/ucscoremeta.py b/ucsmsdk/ucscoremeta.py index 729b3f0b..ca170eaf 100644 --- a/ucsmsdk/ucscoremeta.py +++ b/ucsmsdk/ucscoremeta.py @@ -144,6 +144,11 @@ def patch(self): """Getter Method of UcsVersion Class""" return self.__patch + @property + def spin(self): + """Getter Method of UcsVersion Class""" + return self.__spin + @property def version(self): """Getter Method of UcsVersion Class""" @@ -165,13 +170,17 @@ def compare_to(self, version): if version is None or not isinstance(version, UcsVersion): return 1 - if self.__major != version.major: - return ord(self.__major) - ord(version.major) - if self.__minor != version.minor: - return ord(self.__minor) - ord(version.minor) - if self.__mr != version.mr: - return ord(self.__mr) - ord(version.mr) - return ord(self.__patch) - ord(version.patch) + ret = 0 + versions = [(self.__major, version.major), + (self.__minor, version.minor), + (self.__mr, version.mr), + (self.__patch, version.patch), + (self.__spin, version.spin)] + for item in versions: + ret = self._compare(item[0], item[1]) + if ret: + return ret + return ret def __gt__(self, version): return self.compare_to(version) > 0 From 4c87360d598ee215c44e4b1db4116b2e82ff6703 Mon Sep 17 00:00:00 2001 From: Vincent Esposito Date: Sat, 27 Mar 2021 11:53:03 +0100 Subject: [PATCH 3/5] Improve version handling to support engineering builds like 4.2(0.175a) --- ucsmsdk/ucscoremeta.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/ucsmsdk/ucscoremeta.py b/ucsmsdk/ucscoremeta.py index ca170eaf..f7ed19b2 100644 --- a/ucsmsdk/ucscoremeta.py +++ b/ucsmsdk/ucscoremeta.py @@ -47,6 +47,7 @@ def __init__(self, version): self.__mr = None self.__patch = None self.__spin = None + self.__build = None match_pattern = re.compile("^(?P[1-9][0-9]{0,2})\." "(?P(([0-9])|([1-9][0-9]{0,1})))\(" @@ -99,6 +100,16 @@ def __init__(self, version): if self._set_versions(match_obj): return + # handle engineering builds "4.2(0.175a)" + match_pattern = re.compile("^(?P[1-9][0-9]{0,2})\." + "(?P(([0-9])|([1-9][0-9]{0,2})))\(" + "(?P(([0-9])|([1-9][0-9]{0,2})))\." + "(?P(([0-9])|([1-9][0-9]{0,})))" + "(?P[a-z])\)$") + match_obj = re.match(match_pattern, version) + if self._set_versions(match_obj): + return + def _set_versions(self, match_obj): if not match_obj: return False @@ -109,6 +120,7 @@ def _set_versions(self, match_obj): self.__mr = match_dict.get("mr") self.__patch = match_dict.get("patch") self.__spin = match_dict.get("spin") + self.__build = match_dict.get("build") # for spin builds 4.0(1S52), the patch version will be None # In this scenario assume the version to be highest patch z @@ -149,6 +161,11 @@ def spin(self): """Getter Method of UcsVersion Class""" return self.__spin + @property + def build(self): + """Getter Method of UcsVersion Class""" + return self.__build + @property def version(self): """Getter Method of UcsVersion Class""" @@ -174,6 +191,7 @@ def compare_to(self, version): versions = [(self.__major, version.major), (self.__minor, version.minor), (self.__mr, version.mr), + (self.__build, version.build), (self.__patch, version.patch), (self.__spin, version.spin)] for item in versions: From bde1461a363730539c3d8a36eeee0ff949f770d4 Mon Sep 17 00:00:00 2001 From: Vincent Esposito Date: Fri, 18 Jun 2021 23:09:19 +0200 Subject: [PATCH 4/5] Fix version comparison + add unit test --- tests/unit_tests/common/test_ucsversion.py | 109 +++++++++++++++++++++ ucsmsdk/ucscoremeta.py | 9 +- 2 files changed, 113 insertions(+), 5 deletions(-) create mode 100644 tests/unit_tests/common/test_ucsversion.py diff --git a/tests/unit_tests/common/test_ucsversion.py b/tests/unit_tests/common/test_ucsversion.py new file mode 100644 index 00000000..6e40efd5 --- /dev/null +++ b/tests/unit_tests/common/test_ucsversion.py @@ -0,0 +1,109 @@ +# Copyright 2015 Cisco Systems, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from nose.tools import assert_equal +from ucsmsdk.ucsmeta import VersionMeta +from ucsmsdk.ucscoremeta import UcsVersion + + +def test_nightly_version1(): + version1 = UcsVersion("2.0(13aS6)") + version2 = UcsVersion("3.0(1S10)") + assert_equal((version1 < version2), True) + + +def test_nightly_version2(): + version1 = UcsVersion("2.0(13aS6)") + version2 = UcsVersion("2.0(1S10)") + assert_equal((version1 > version2), True) + + +def test_nightly_version3(): + # 2.0(2cS6) will be considered as 2.0(2d) internally + version1 = UcsVersion("2.0(2cS6)") + version2 = UcsVersion("2.0(2c)") + assert_equal((version1 == version2), False) + + +def test_nightly_version4(): + version1 = UcsVersion("2.0(2cS6)") + version2 = UcsVersion("2.0(3)") + assert_equal((version1 < version2), True) + + +def test_spin_version1(): + # version interpreted as 4.0(2b) + version1 = UcsVersion("4.0(2aS3)") + version2 = UcsVersion("4.0(2b)") + assert_equal((version1 == version2), True) + + +def test_spin_version2(): + # version interpreted as 4.0(234c) + version1 = UcsVersion("4.0(234bS3)") + version2 = UcsVersion("4.0(234c)") + assert_equal((version1 == version2), True) + + +def test_spin_version3(): + # version interpreted as 4.0(2z) + version1 = UcsVersion("4.0(2S3)") + version2 = UcsVersion("4.0(2z)") + assert_equal((version1 == version2), True) + + +def test_spin_version4(): + # version interpreted as 4.0(234z) + version1 = UcsVersion("4.0(234S3)") + version2 = UcsVersion("4.0(234z)") + assert_equal((version1 == version2), True) + + +def test_patch_version1(): + # version interpreted as 4.0(235a) + version1 = UcsVersion("4.0(234.5)") + version2 = UcsVersion("4.0(235a)") + assert_equal((version1 == version2), True) + + +def test_build_version1(): + # 4.2(0.175a) is an engineering build that will later become 4.2(1a) + version1 = UcsVersion("4.2(0.175a)") + version2 = UcsVersion("4.2(1a)") + assert_equal((version1 < version2), True) + + +def test_build_version2(): + version1 = UcsVersion("4.2(0.175a)") + version2 = UcsVersion("4.2(0.258a)") + assert_equal((version1 < version2), True) + + +def test_gt_same_major_version(): + version1 = VersionMeta.Version211a + version2 = VersionMeta.Version211e + assert_equal((version1 < version2), True) + + +def test_gt_different_major_version(): + version1 = VersionMeta.Version404a + version2 = VersionMeta.Version412b + assert_equal((version1 < version2), True) + + +def test_patch_versions(): + # when we don't see a patch version we use z + # so 2.0(12) will be considered as 2.0(12z) + version1 = UcsVersion("2.0(12b)") + version2 = UcsVersion("2.0(12)") + assert_equal((version1 > version2), False) diff --git a/ucsmsdk/ucscoremeta.py b/ucsmsdk/ucscoremeta.py index f7ed19b2..43a15924 100644 --- a/ucsmsdk/ucscoremeta.py +++ b/ucsmsdk/ucscoremeta.py @@ -124,13 +124,13 @@ def _set_versions(self, match_obj): # for spin builds 4.0(1S52), the patch version will be None # In this scenario assume the version to be highest patch z - if self.__spin is not None and self.__patch is None: + if self.__patch is None: self.__patch = 'z' - elif self.__patch is not None and self.__mr is not None and self.__patch.isdigit() and self.__mr.isdigit(): + elif self.__patch.isdigit() and self.__mr.isdigit(): log.debug("Interim version encountered: %s. MR version has been bumped up." % self.version) self.__mr = str(int(self.__mr) + 1) self.__patch = 'a' - elif self.__patch is not None and self.__patch.isalpha() and self.__spin: + elif self.__patch.isalpha() and self.__spin: log.debug("Interim version encountered: %s. patch version has been bumped up." % self.version) self.__patch = str(chr(ord(self.__patch) + 1)) @@ -192,8 +192,7 @@ def compare_to(self, version): (self.__minor, version.minor), (self.__mr, version.mr), (self.__build, version.build), - (self.__patch, version.patch), - (self.__spin, version.spin)] + (self.__patch, version.patch)] for item in versions: ret = self._compare(item[0], item[1]) if ret: From 03bc1e19b8582c68d3a94a20a939a48fe91332f8 Mon Sep 17 00:00:00 2001 From: Vincent Esposito Date: Thu, 19 Aug 2021 16:09:53 +0200 Subject: [PATCH 5/5] Add support for other spin builds formats + associated unit tests --- tests/unit_tests/common/test_ucsversion.py | 14 ++++++++++++++ ucsmsdk/ucscoremeta.py | 19 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/tests/unit_tests/common/test_ucsversion.py b/tests/unit_tests/common/test_ucsversion.py index 6e40efd5..d2c84665 100644 --- a/tests/unit_tests/common/test_ucsversion.py +++ b/tests/unit_tests/common/test_ucsversion.py @@ -89,6 +89,20 @@ def test_build_version2(): assert_equal((version1 < version2), True) +def test_spin_version5(): + # version interpreted as 4.2(2a) + version1 = UcsVersion("4.2(1.2021052301)") + version2 = UcsVersion("4.2(2a)") + assert_equal((version1 == version2), True) + + +def test_spin_version6(): + # version interpreted as 4.2(1b) + version1 = UcsVersion("4.2(1a.2021052301)") + version2 = UcsVersion("4.2(1b)") + assert_equal((version1 == version2), True) + + def test_gt_same_major_version(): version1 = VersionMeta.Version211a version2 = VersionMeta.Version211e diff --git a/ucsmsdk/ucscoremeta.py b/ucsmsdk/ucscoremeta.py index 43a15924..9d3aa851 100644 --- a/ucsmsdk/ucscoremeta.py +++ b/ucsmsdk/ucscoremeta.py @@ -110,6 +110,25 @@ def __init__(self, version): if self._set_versions(match_obj): return + # handle spin builds "4.2(1.2021052301)" + match_pattern = re.compile("^(?P[1-9][0-9]{0,2})\." + "(?P(([0-9])|([1-9][0-9]{0,1})))\(" + "(?P(([0-9])|([1-9][0-9]{0,2})))\." + "(?P\d{0,4}\d{0,2}\d{0,2}\d{0,2})\)$") + match_obj = re.match(match_pattern, version) + if self._set_versions(match_obj): + return + + # handle patch spin builds "4.2(1a.2021052301)" + match_pattern = re.compile("^(?P[1-9][0-9]{0,2})\." + "(?P(([0-9])|([1-9][0-9]{0,1})))\(" + "(?P(([0-9])|([1-9][0-9]{0,2})))" + "(?P[a-z])\." + "(?P\d{0,4}\d{0,2}\d{0,2}\d{0,2})\)$") + match_obj = re.match(match_pattern, version) + if self._set_versions(match_obj): + return + def _set_versions(self, match_obj): if not match_obj: return False