From 66c66bdf4ca60ddfc92dbf9fc1616edc7a968241 Mon Sep 17 00:00:00 2001 From: sebres Date: Tue, 2 Dec 2014 00:56:20 +0100 Subject: [PATCH] code review and few new test cases --- fail2ban/server/actions.py | 1 + fail2ban/server/mytime.py | 42 ++++++++++++++++++---------------- fail2ban/tests/misctestcase.py | 18 +++++++++++++++ fail2ban/tests/utils.py | 3 ++- 4 files changed, 43 insertions(+), 21 deletions(-) diff --git a/fail2ban/server/actions.py b/fail2ban/server/actions.py index b4612f8c..c00dc7fc 100644 --- a/fail2ban/server/actions.py +++ b/fail2ban/server/actions.py @@ -167,6 +167,7 @@ class Actions(JailThread, Mapping): # @param value the time def setBanTime(self, value): + value = MyTime.str2seconds(value) self.__banManager.setBanTime(value) logSys.info("Set banTime = %s" % value) diff --git a/fail2ban/server/mytime.py b/fail2ban/server/mytime.py index 47509f19..329e2465 100644 --- a/fail2ban/server/mytime.py +++ b/fail2ban/server/mytime.py @@ -98,32 +98,34 @@ class MyTime: else: return time.localtime(MyTime.myTime) - ## - # Wraps string expression like "1h 2m 3s" into number contains seconds (3723). - # The string expression will be evaluated as mathematical expression, spaces between each groups - # will be wrapped to "+" operand (only if any operand does not specified between). - # Because of case insensitivity and overwriting with minutes ("m" or "mm"), the short replacement for month - # are "mo" or "mon" (like %b by date formating). - # Ex: 1hour+30min = 5400 - # 0d 1h 30m = 5400 - # 1year-6mo = 15778800 - # 6 months = 15778800 - # warn: month is not 30 days, it is a year in seconds / 12, the leap years will be respected also: - # >>>> float(Test.str2seconds("1month")) / 60 / 60 / 24 - # 30.4375 - # >>>> float(Test.str2seconds("1year")) / 60 / 60 / 24 - # 365.25 - # - # @returns number (calculated seconds from expression "val") - @staticmethod def str2seconds(val): + """Wraps string expression like "1h 2m 3s" into number contains seconds (3723). + The string expression will be evaluated as mathematical expression, spaces between each groups + will be wrapped to "+" operand (only if any operand does not specified between). + Because of case insensitivity and overwriting with minutes ("m" or "mm"), the short replacement for month + are "mo" or "mon". + Ex: 1hour+30min = 5400 + 0d 1h 30m = 5400 + 1year-6mo = 15778800 + 6 months = 15778800 + warn: month is not 30 days, it is a year in seconds / 12, the leap years will be respected also: + >>>> float(str2seconds("1month")) / 60 / 60 / 24 + 30.4375 + >>>> float(str2seconds("1year")) / 60 / 60 / 24 + 365.25 + + @returns number (calculated seconds from expression "val") + """ + if isinstance(val, (int, long, float, complex)): + return val # replace together standing abbreviations, example '1d12h' -> '1d 12h': val = re.sub(r"(?i)(?<=[a-z])(\d)", r" \1", val) # replace abbreviation with expression: for rexp, rpl in ( - (r"days?|da|dd?", 24*60*60), (r"week?|wee?|ww?", 7*24*60*60), (r"months?|mon?", (365*3+366)*24*60*60/4/12), (r"years?|yea?|yy?", (365*3+366)*24*60*60/4), - (r"seconds?|sec?|ss?", 1), (r"minutes?|min?|mm?", 60), (r"hours?|ho|hh?", 60*60), + (r"days?|da|dd?", 24*60*60), (r"weeks?|wee?|ww?", 7*24*60*60), (r"months?|mon?", (365*3+366)*24*60*60/4/12), + (r"years?|yea?|yy?", (365*3+366)*24*60*60/4), + (r"seconds?|sec?|ss?", 1), (r"minutes?|min?|mm?", 60), (r"hours?|hou?|hh?", 60*60), ): val = re.sub(r"(?i)(?<=[\d\s])(%s)\b" % rexp, "*"+str(rpl), val) val = re.sub(r"(\d)\s+(\d)", r"\1+\2", val); diff --git a/fail2ban/tests/misctestcase.py b/fail2ban/tests/misctestcase.py index e28ce422..a2310ec5 100644 --- a/fail2ban/tests/misctestcase.py +++ b/fail2ban/tests/misctestcase.py @@ -35,6 +35,7 @@ from StringIO import StringIO from ..helpers import formatExceptionInfo, mbasename, TraceBack, FormatterWithTraceBack, getLogger from ..helpers import splitcommaspace from ..server.datetemplate import DatePatternRegex +from ..server.mytime import MyTime class HelpersTest(unittest.TestCase): @@ -229,3 +230,20 @@ class CustomDateFormatsTest(unittest.TestCase): self.assertEqual( date, datetime.datetime(2007, 1, 25, 16, 0)) + +class MyTimeTest(unittest.TestCase): + + def testStr2Seconds(self): + # several formats / write styles: + str2sec = MyTime.str2seconds + self.assertEqual(str2sec('1y6mo30w15d12h35m25s'), 66821725) + self.assertEqual(str2sec('2yy 3mo 4ww 10dd 5hh 30mm 20ss'), 74307620) + self.assertEqual(str2sec('2 years 3 months 4 weeks 10 days 5 hours 30 minutes 20 seconds'), 74307620) + self.assertEqual(str2sec('1 year + 1 month - 1 week + 1 day'), 33669000) + self.assertEqual(str2sec('2 * 0.5 yea + 1*1 mon - 3*1/3 wee + 2/2 day - (2*12 hou 3*20 min 80 sec) '), 33578920.0) + self.assertEqual(str2sec('2*.5y+1*1mo-3*1/3w+2/2d-(2*12h3*20m80s) '), 33578920.0) + self.assertEqual(str2sec('1ye -2mo -3we -4da -5ho -6mi -7se'), 24119633) + # month and year in days : + self.assertEqual(float(str2sec("1 month")) / 60 / 60 / 24, 30.4375) + self.assertEqual(float(str2sec("1 year")) / 60 / 60 / 24, 365.25) + diff --git a/fail2ban/tests/utils.py b/fail2ban/tests/utils.py index 35fa59fd..62596292 100644 --- a/fail2ban/tests/utils.py +++ b/fail2ban/tests/utils.py @@ -132,6 +132,7 @@ def gatherTests(regexps=None, no_network=False): tests.addTest(unittest.makeSuite(misctestcase.SetupTest)) tests.addTest(unittest.makeSuite(misctestcase.TestsUtilsTest)) tests.addTest(unittest.makeSuite(misctestcase.CustomDateFormatsTest)) + tests.addTest(unittest.makeSuite(misctestcase.MyTimeTest)) # Database tests.addTest(unittest.makeSuite(databasetestcase.DatabaseTest)) @@ -296,4 +297,4 @@ else: kernel32.CloseHandle(process) return True else: - return False \ No newline at end of file + return False