From 89d255961103235a68c1e784d969d34884701c0d Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Fri, 24 Mar 2017 12:23:40 -0700 Subject: [PATCH 01/12] Fixes to uptime string parser --- napalm_base/utils/string_parsers.py | 43 +++++++++++++++++------------ 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/napalm_base/utils/string_parsers.py b/napalm_base/utils/string_parsers.py index f0446d1f..0c2f464a 100644 --- a/napalm_base/utils/string_parsers.py +++ b/napalm_base/utils/string_parsers.py @@ -75,29 +75,34 @@ def hyphen_range(string): def convert_uptime_string_seconds(uptime): - ''' - Convert uptime strings to seconds. The string can be formatted various ways, eg. - 1 hour, 56 minutes - ''' - regex1 = (r"((?P\d+) week(s)?,\s+)?((?P\d+) day(s)?,\s+)?((?P\d+) " - r"hour(s)?,\s+)?((?P\d+) minute(s)?)") - regex_1 = re.compile(regex1) - regex_2 = re.compile(r"((?P\d+)):((?P\d+)):((?P\d+))") - regex3 = (r"((?P\d+)w)?((?P\d+)d)?((?P\d+)h)?" - r"((?P\d+)m)?((?P\d+)s)?") - regex_3 = re.compile(regex3) - regex_list = [regex_1, regex_2, regex_3] - uptime_dict = dict() + '''Convert uptime strings to seconds. The string can be formatted various ways.''' + regex_list = [ + # n years, n weeks, n days, n hours, n minutes where each of the fields except minutes + # is optional. Additionally, can be either singular or plural + (r"((?P\d+) year(s)?,\s+)?((?P\d+) week(s)?,\s+)?" + r"((?P\d+) day(s)?,\s+)?((?P\d+) " + r"hour(s)?,\s+)?((?P\d+) minute(s)?)"), + # n days, HH:MM:SS where each field is required (except for days) + (r"((?P\d+) day(s)?,\s+)?" + r"((?P\d+)):((?P\d+)):((?P\d+))"), + # 7w6d5h4m3s where each field is uptional + (r"((?P\d+)w)?((?P\d+)d)?((?P\d+)h)?" + r"((?P\d+)m)?((?P\d+)s)?"), + ] + regex_list = [re.compile(x) for x in regex_list] + + uptime_dict = {} for regex in regex_list: - uptime_dict = regex.search(uptime) - if uptime_dict is not None: + match = regex.search(uptime) + if match: uptime_dict = uptime_dict.groupdict() break - uptime_dict = dict() - uptime_seconds = 0 + uptime_seconds = 0 for unit, value in uptime_dict.items(): if value is not None: + if unit == 'years': + uptime_seconds += int(value) * 31536000 if unit == 'weeks': uptime_seconds += int(value) * 604800 elif unit == 'days': @@ -110,4 +115,8 @@ def convert_uptime_string_seconds(uptime): uptime_seconds += int(value) else: raise Exception('Unrecognized unit "{}" in uptime:{}'.format(unit, uptime)) + + if not uptime_dict: + raise Exception('Unrecognized uptime string:{}'.format(uptime)) + return uptime_seconds From 92b6c452e09951fa988e8080131a9e741a56d9ff Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Fri, 24 Mar 2017 12:25:28 -0700 Subject: [PATCH 02/12] Cleanup pylama --- napalm_base/utils/string_parsers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/napalm_base/utils/string_parsers.py b/napalm_base/utils/string_parsers.py index 0c2f464a..5cf24ebd 100644 --- a/napalm_base/utils/string_parsers.py +++ b/napalm_base/utils/string_parsers.py @@ -77,7 +77,7 @@ def hyphen_range(string): def convert_uptime_string_seconds(uptime): '''Convert uptime strings to seconds. The string can be formatted various ways.''' regex_list = [ - # n years, n weeks, n days, n hours, n minutes where each of the fields except minutes + # n years, n weeks, n days, n hours, n minutes where each of the fields except minutes # is optional. Additionally, can be either singular or plural (r"((?P\d+) year(s)?,\s+)?((?P\d+) week(s)?,\s+)?" r"((?P\d+) day(s)?,\s+)?((?P\d+) " From 926c5daaad3f0ee2a40124310186c4e5bfe13009 Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Fri, 31 Mar 2017 09:10:20 -0700 Subject: [PATCH 03/12] Fix bug with string parsers --- napalm_base/utils/string_parsers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/napalm_base/utils/string_parsers.py b/napalm_base/utils/string_parsers.py index 5cf24ebd..f9ba6f86 100644 --- a/napalm_base/utils/string_parsers.py +++ b/napalm_base/utils/string_parsers.py @@ -95,7 +95,7 @@ def convert_uptime_string_seconds(uptime): for regex in regex_list: match = regex.search(uptime) if match: - uptime_dict = uptime_dict.groupdict() + uptime_dict = match.groupdict() break uptime_seconds = 0 From 82769e47b1c1d2a3a9bd93217654ec9ebe1a56b5 Mon Sep 17 00:00:00 2001 From: David Barroso Date: Sat, 8 Apr 2017 13:28:53 +0200 Subject: [PATCH 04/12] Making testing configuration changes pytest compatible --- napalm_base/test/base.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/napalm_base/test/base.py b/napalm_base/test/base.py index 1760198d..0fc17a67 100644 --- a/napalm_base/test/base.py +++ b/napalm_base/test/base.py @@ -27,6 +27,16 @@ class TestConfigNetworkDriver(object): + @classmethod + def setup_class(cls): + """Added for py.test/nosetests compatibility""" + cls.setUpClass() + + @classmethod + def teardown_class(cls): + """Added for py.test/nosetests compatibility""" + cls.tearDownClass() + @classmethod def tearDownClass(cls): cls.device.load_replace_candidate(filename='%s/initial.conf' % cls.vendor) From f365240e6ad43c893ace7c82a50cf6fa525b0d89 Mon Sep 17 00:00:00 2001 From: David Barroso Date: Sat, 8 Apr 2017 16:51:34 +0200 Subject: [PATCH 05/12] Check if connection is alive before closing --- napalm_base/base.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/napalm_base/base.py b/napalm_base/base.py index bd648f9d..25b5a77c 100644 --- a/napalm_base/base.py +++ b/napalm_base/base.py @@ -66,11 +66,10 @@ def __del__(self): is released (unlocked). """ try: - self.close() - except OSError as e: - # Ignore if socket was already closed - if 'is closed' in str(e): - pass + if self.is_alive()["is_alive"]: + self.close() + except NotImplementedError: + pass @staticmethod def __raise_clean_exception(exc_type, exc_value, exc_traceback): From ab621a63cf172059ab1ea02bee532a06c553c2e1 Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Fri, 24 Mar 2017 12:23:40 -0700 Subject: [PATCH 06/12] Fixes to uptime string parser --- napalm_base/utils/string_parsers.py | 43 +++++++++++++++++------------ 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/napalm_base/utils/string_parsers.py b/napalm_base/utils/string_parsers.py index f0446d1f..0c2f464a 100644 --- a/napalm_base/utils/string_parsers.py +++ b/napalm_base/utils/string_parsers.py @@ -75,29 +75,34 @@ def hyphen_range(string): def convert_uptime_string_seconds(uptime): - ''' - Convert uptime strings to seconds. The string can be formatted various ways, eg. - 1 hour, 56 minutes - ''' - regex1 = (r"((?P\d+) week(s)?,\s+)?((?P\d+) day(s)?,\s+)?((?P\d+) " - r"hour(s)?,\s+)?((?P\d+) minute(s)?)") - regex_1 = re.compile(regex1) - regex_2 = re.compile(r"((?P\d+)):((?P\d+)):((?P\d+))") - regex3 = (r"((?P\d+)w)?((?P\d+)d)?((?P\d+)h)?" - r"((?P\d+)m)?((?P\d+)s)?") - regex_3 = re.compile(regex3) - regex_list = [regex_1, regex_2, regex_3] - uptime_dict = dict() + '''Convert uptime strings to seconds. The string can be formatted various ways.''' + regex_list = [ + # n years, n weeks, n days, n hours, n minutes where each of the fields except minutes + # is optional. Additionally, can be either singular or plural + (r"((?P\d+) year(s)?,\s+)?((?P\d+) week(s)?,\s+)?" + r"((?P\d+) day(s)?,\s+)?((?P\d+) " + r"hour(s)?,\s+)?((?P\d+) minute(s)?)"), + # n days, HH:MM:SS where each field is required (except for days) + (r"((?P\d+) day(s)?,\s+)?" + r"((?P\d+)):((?P\d+)):((?P\d+))"), + # 7w6d5h4m3s where each field is uptional + (r"((?P\d+)w)?((?P\d+)d)?((?P\d+)h)?" + r"((?P\d+)m)?((?P\d+)s)?"), + ] + regex_list = [re.compile(x) for x in regex_list] + + uptime_dict = {} for regex in regex_list: - uptime_dict = regex.search(uptime) - if uptime_dict is not None: + match = regex.search(uptime) + if match: uptime_dict = uptime_dict.groupdict() break - uptime_dict = dict() - uptime_seconds = 0 + uptime_seconds = 0 for unit, value in uptime_dict.items(): if value is not None: + if unit == 'years': + uptime_seconds += int(value) * 31536000 if unit == 'weeks': uptime_seconds += int(value) * 604800 elif unit == 'days': @@ -110,4 +115,8 @@ def convert_uptime_string_seconds(uptime): uptime_seconds += int(value) else: raise Exception('Unrecognized unit "{}" in uptime:{}'.format(unit, uptime)) + + if not uptime_dict: + raise Exception('Unrecognized uptime string:{}'.format(uptime)) + return uptime_seconds From e22583a53695ac40e533a980a8ded65b73842d52 Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Fri, 24 Mar 2017 12:25:28 -0700 Subject: [PATCH 07/12] Cleanup pylama --- napalm_base/utils/string_parsers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/napalm_base/utils/string_parsers.py b/napalm_base/utils/string_parsers.py index 0c2f464a..5cf24ebd 100644 --- a/napalm_base/utils/string_parsers.py +++ b/napalm_base/utils/string_parsers.py @@ -77,7 +77,7 @@ def hyphen_range(string): def convert_uptime_string_seconds(uptime): '''Convert uptime strings to seconds. The string can be formatted various ways.''' regex_list = [ - # n years, n weeks, n days, n hours, n minutes where each of the fields except minutes + # n years, n weeks, n days, n hours, n minutes where each of the fields except minutes # is optional. Additionally, can be either singular or plural (r"((?P\d+) year(s)?,\s+)?((?P\d+) week(s)?,\s+)?" r"((?P\d+) day(s)?,\s+)?((?P\d+) " From 231de975fa8237a28093ba27503ec58060dc5c6c Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Fri, 31 Mar 2017 09:10:20 -0700 Subject: [PATCH 08/12] Fix bug with string parsers --- napalm_base/utils/string_parsers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/napalm_base/utils/string_parsers.py b/napalm_base/utils/string_parsers.py index 5cf24ebd..f9ba6f86 100644 --- a/napalm_base/utils/string_parsers.py +++ b/napalm_base/utils/string_parsers.py @@ -95,7 +95,7 @@ def convert_uptime_string_seconds(uptime): for regex in regex_list: match = regex.search(uptime) if match: - uptime_dict = uptime_dict.groupdict() + uptime_dict = match.groupdict() break uptime_seconds = 0 From c4c7dc2eacd6c6040da43476f441a9b834a99bff Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Sat, 8 Apr 2017 08:58:16 -0700 Subject: [PATCH 09/12] Fixing bugs in string parsers; adding unit test for string parser time conversion --- napalm_base/utils/string_parsers.py | 4 ++-- test/unit/TestHelpers.py | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/napalm_base/utils/string_parsers.py b/napalm_base/utils/string_parsers.py index f9ba6f86..b300e927 100644 --- a/napalm_base/utils/string_parsers.py +++ b/napalm_base/utils/string_parsers.py @@ -85,7 +85,7 @@ def convert_uptime_string_seconds(uptime): # n days, HH:MM:SS where each field is required (except for days) (r"((?P\d+) day(s)?,\s+)?" r"((?P\d+)):((?P\d+)):((?P\d+))"), - # 7w6d5h4m3s where each field is uptional + # 7w6d5h4m3s where each field is optional (r"((?P\d+)w)?((?P\d+)d)?((?P\d+)h)?" r"((?P\d+)m)?((?P\d+)s)?"), ] @@ -103,7 +103,7 @@ def convert_uptime_string_seconds(uptime): if value is not None: if unit == 'years': uptime_seconds += int(value) * 31536000 - if unit == 'weeks': + elif unit == 'weeks': uptime_seconds += int(value) * 604800 elif unit == 'days': uptime_seconds += int(value) * 86400 diff --git a/test/unit/TestHelpers.py b/test/unit/TestHelpers.py index 8eacb95f..8009650a 100644 --- a/test/unit/TestHelpers.py +++ b/test/unit/TestHelpers.py @@ -302,6 +302,31 @@ def test_ip(self): '2001:db8:85a3::8a2e:370:7334' ) + def test_convert_uptime_string_seconds(self): + """ + Tests the parser function ```convert_uptime_string_seconds```: + + * check if all raw uptime strings passed return the expected uptime in seconds + """ + + # Regex 1 + self.assertEqual(convert_uptime_string_seconds('24 days, 11 hours, 25 minutes'), 2114700) + self.assertEqual(convert_uptime_string_seconds('1 hour, 5 minutes'), 3900) + self.assertEqual(convert_uptime_string_seconds('1 year, 2 weeks, 5 minutes'), 32745900) + self.assertEqual(convert_uptime_string_seconds('95 weeks, 2 days, 10 hours, 58 minutes'), 57668280) + + # Regex 2 + self.assertEqual(convert_uptime_string_seconds('114 days, 22:27:32'), 9930452) + self.assertEqual(convert_uptime_string_seconds('0 days, 22:27:32'), 80852) + self.assertEqual(convert_uptime_string_seconds('365 days, 5:01:44'), 31554104) + + # Regex 3 + self.assertEqual(convert_uptime_string_seconds('7w6d5h4m3s'), 4770243) + self.assertEqual(convert_uptime_string_seconds('95w2d10h58m'), 57668280) + self.assertEqual(convert_uptime_string_seconds('1h5m'), 3900) + + + class FakeNetworkDriver(NetworkDriver): From 92cbd8875b2acda02049d5cbeb1ee24b80c56f93 Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Sat, 8 Apr 2017 09:06:20 -0700 Subject: [PATCH 10/12] Fix missing import in test --- test/unit/TestHelpers.py | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/test/unit/TestHelpers.py b/test/unit/TestHelpers.py index 8009650a..1da94581 100644 --- a/test/unit/TestHelpers.py +++ b/test/unit/TestHelpers.py @@ -40,6 +40,7 @@ import napalm_base.helpers import napalm_base.exceptions from napalm_base.base import NetworkDriver +from napalm_base.utils.string_parsers import convert_uptime_string_seconds class TestBaseHelpers(unittest.TestCase): @@ -325,7 +326,27 @@ def test_convert_uptime_string_seconds(self): self.assertEqual(convert_uptime_string_seconds('95w2d10h58m'), 57668280) self.assertEqual(convert_uptime_string_seconds('1h5m'), 3900) - + # Additional tests from real devices +### self.assertEqual(convert_uptime_string_seconds('26 weeks, 2 days, 7 hours, 7 minutes', +### +### 'Uptime = +###./jobmethods.py: 'Uptime = 19 weeks, 2 days, 2 hours, 2 minutes', +###./jobmethods.py: 'Uptime = 15 weeks, 3 days, 5 hours, 57 minutes', +###./jobmethods.py: 'Uptime = 1 year, 8 weeks, 15 minutes', +###./jobmethods.py: 'Uptime = 8 weeks, 2 hours, 5 minutes', +###./jobmethods.py: 'Uptime = 8 weeks, 2 hours, 1 minute', +###./jobmethods.py: 'Uptime = 2 years, 40 weeks, 1 day, 22 hours, 3 minutes', +###./jobmethods.py: 'Uptime = 2 years, 40 weeks, 1 day, 19 hours, 46 minutes', +###./jobmethods.py: 'Uptime = 1 year, 39 weeks, 15 hours, 23 minutes', +###./jobmethods.py: 'Uptime = 33 weeks, 19 hours, 12 minutes', +###./jobmethods.py: 'Uptime = 33 weeks, 19 hours, 8 minutes', +###./jobmethods.py: 'Uptime = 33 weeks, 19 hours, 10 minutes', +###./jobmethods.py: 'Uptime = 51 weeks, 5 days, 13 hours, 0 minutes', +###./jobmethods.py: 'Uptime = 51 weeks, 5 days, 12 hours, 57 minutes', +###./jobmethods.py: 'Uptime = 51 weeks, 5 days, 12 hours, 55 minutes', +###./jobmethods.py: 'Uptime = 51 weeks, 5 days, 12 hours, 58 minutes' +###./jobmethods.py: if DEBUG: print "Executing DEVICEUPTIMEREPORT" + class FakeNetworkDriver(NetworkDriver): From 24b99d2c90ea1b9189b41ea89a538f20642fc85e Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Sat, 8 Apr 2017 10:41:35 -0700 Subject: [PATCH 11/12] Adding more tests; fix pylama --- test/unit/TestHelpers.py | 63 +++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 27 deletions(-) diff --git a/test/unit/TestHelpers.py b/test/unit/TestHelpers.py index 1da94581..f4e5b302 100644 --- a/test/unit/TestHelpers.py +++ b/test/unit/TestHelpers.py @@ -314,7 +314,42 @@ def test_convert_uptime_string_seconds(self): self.assertEqual(convert_uptime_string_seconds('24 days, 11 hours, 25 minutes'), 2114700) self.assertEqual(convert_uptime_string_seconds('1 hour, 5 minutes'), 3900) self.assertEqual(convert_uptime_string_seconds('1 year, 2 weeks, 5 minutes'), 32745900) - self.assertEqual(convert_uptime_string_seconds('95 weeks, 2 days, 10 hours, 58 minutes'), 57668280) + self.assertEqual( + convert_uptime_string_seconds('95 weeks, 2 days, 10 hours, 58 minutes'), 57668280) + self.assertEqual( + convert_uptime_string_seconds('26 weeks, 2 days, 7 hours, 7 minutes'), 15923220) + self.assertEqual( + convert_uptime_string_seconds('19 weeks, 2 days, 2 hours, 2 minutes'), 11671320) + self.assertEqual( + convert_uptime_string_seconds('15 weeks, 3 days, 5 hours, 57 minutes'), 9352620) + self.assertEqual( + convert_uptime_string_seconds('1 year, 8 weeks, 15 minutes'), 36375300) + self.assertEqual( + convert_uptime_string_seconds('8 weeks, 2 hours, 5 minutes'), 4845900) + self.assertEqual( + convert_uptime_string_seconds('8 weeks, 2 hours, 1 minute'), 4845660) + self.assertEqual( + convert_uptime_string_seconds('2 years, 40 weeks, 1 day, 22 hours, 3 minutes'), + 87429780) + self.assertEqual( + convert_uptime_string_seconds('2 years, 40 weeks, 1 day, 19 hours, 46 minutes'), + 87421560) + self.assertEqual( + convert_uptime_string_seconds('1 year, 39 weeks, 15 hours, 23 minutes'), 55178580) + self.assertEqual( + convert_uptime_string_seconds('33 weeks, 19 hours, 12 minutes'), 20027520) + self.assertEqual( + convert_uptime_string_seconds('33 weeks, 19 hours, 8 minutes'), 20027280) + self.assertEqual( + convert_uptime_string_seconds('33 weeks, 19 hours, 10 minutes'), 20027400) + self.assertEqual( + convert_uptime_string_seconds('51 weeks, 5 days, 13 hours, 0 minutes'), 31323600) + self.assertEqual( + convert_uptime_string_seconds('51 weeks, 5 days, 12 hours, 57 minutes'), 31323420) + self.assertEqual( + convert_uptime_string_seconds('51 weeks, 5 days, 12 hours, 55 minutes'), 31323300) + self.assertEqual( + convert_uptime_string_seconds('51 weeks, 5 days, 12 hours, 58 minutes'), 31323480) # Regex 2 self.assertEqual(convert_uptime_string_seconds('114 days, 22:27:32'), 9930452) @@ -326,43 +361,17 @@ def test_convert_uptime_string_seconds(self): self.assertEqual(convert_uptime_string_seconds('95w2d10h58m'), 57668280) self.assertEqual(convert_uptime_string_seconds('1h5m'), 3900) - # Additional tests from real devices -### self.assertEqual(convert_uptime_string_seconds('26 weeks, 2 days, 7 hours, 7 minutes', -### -### 'Uptime = -###./jobmethods.py: 'Uptime = 19 weeks, 2 days, 2 hours, 2 minutes', -###./jobmethods.py: 'Uptime = 15 weeks, 3 days, 5 hours, 57 minutes', -###./jobmethods.py: 'Uptime = 1 year, 8 weeks, 15 minutes', -###./jobmethods.py: 'Uptime = 8 weeks, 2 hours, 5 minutes', -###./jobmethods.py: 'Uptime = 8 weeks, 2 hours, 1 minute', -###./jobmethods.py: 'Uptime = 2 years, 40 weeks, 1 day, 22 hours, 3 minutes', -###./jobmethods.py: 'Uptime = 2 years, 40 weeks, 1 day, 19 hours, 46 minutes', -###./jobmethods.py: 'Uptime = 1 year, 39 weeks, 15 hours, 23 minutes', -###./jobmethods.py: 'Uptime = 33 weeks, 19 hours, 12 minutes', -###./jobmethods.py: 'Uptime = 33 weeks, 19 hours, 8 minutes', -###./jobmethods.py: 'Uptime = 33 weeks, 19 hours, 10 minutes', -###./jobmethods.py: 'Uptime = 51 weeks, 5 days, 13 hours, 0 minutes', -###./jobmethods.py: 'Uptime = 51 weeks, 5 days, 12 hours, 57 minutes', -###./jobmethods.py: 'Uptime = 51 weeks, 5 days, 12 hours, 55 minutes', -###./jobmethods.py: 'Uptime = 51 weeks, 5 days, 12 hours, 58 minutes' -###./jobmethods.py: if DEBUG: print "Executing DEVICEUPTIMEREPORT" - - class FakeNetworkDriver(NetworkDriver): def __init__(self): - """Connection details not needed.""" - pass def load_merge_candidate(self, config=None): - """ This method is called at the end of the helper ```load_template```. To check whether the test arrives at the very end of the helper function, will return True instead of raising NotImplementedError exception. """ - return True From 5842639a7177871e7ebc4b6f01bc78e9f11edbbd Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Tue, 2 May 2017 16:37:22 -0700 Subject: [PATCH 12/12] napalm-base release 0.23.3 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index a27d316d..a89aa435 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ setup( name="napalm-base", - version='0.23.2', + version='0.23.3', packages=find_packages(), author="David Barroso", author_email="dbarrosop@dravetech.com",