mirror of https://github.com/fail2ban/fail2ban
Merge pull request #1740 from sebres/0.10-strptime-perf
strptime.py: small code review and performance optimizationpull/1742/head
commit
1a59a5c5a7
|
@ -95,18 +95,10 @@ def reGroupDictStrptime(found_dict, msec=False):
|
||||||
Unix time stamp.
|
Unix time stamp.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
now = MyTime.now()
|
now = \
|
||||||
year = month = day = hour = minute = None
|
year = month = day = hour = minute = tzoffset = \
|
||||||
hour = minute = None
|
weekday = julian = week_of_year = None
|
||||||
second = fraction = 0
|
second = fraction = 0
|
||||||
tzoffset = None
|
|
||||||
# Default to -1 to signify that values not known; not critical to have,
|
|
||||||
# though
|
|
||||||
week_of_year = -1
|
|
||||||
week_of_year_start = -1
|
|
||||||
# weekday and julian defaulted to -1 so as to signal need to calculate
|
|
||||||
# values
|
|
||||||
weekday = julian = -1
|
|
||||||
for key, val in found_dict.iteritems():
|
for key, val in found_dict.iteritems():
|
||||||
if val is None: continue
|
if val is None: continue
|
||||||
# Directives not explicitly handled below:
|
# Directives not explicitly handled below:
|
||||||
|
@ -116,13 +108,9 @@ def reGroupDictStrptime(found_dict, msec=False):
|
||||||
# worthless without day of the week
|
# worthless without day of the week
|
||||||
if key == 'y':
|
if key == 'y':
|
||||||
year = int(val)
|
year = int(val)
|
||||||
# Open Group specification for strptime() states that a %y
|
# Fail2ban year should be always in the current century (>= 2000)
|
||||||
#value in the range of [00, 68] is in the century 2000, while
|
if year <= 2000:
|
||||||
#[69,99] is in the century 1900
|
|
||||||
if year <= 68:
|
|
||||||
year += 2000
|
year += 2000
|
||||||
else:
|
|
||||||
year += 1900
|
|
||||||
elif key == 'Y':
|
elif key == 'Y':
|
||||||
year = int(val)
|
year = int(val)
|
||||||
elif key == 'm':
|
elif key == 'm':
|
||||||
|
@ -156,7 +144,7 @@ def reGroupDictStrptime(found_dict, msec=False):
|
||||||
elif key == 'S':
|
elif key == 'S':
|
||||||
second = int(val)
|
second = int(val)
|
||||||
elif key == 'f':
|
elif key == 'f':
|
||||||
if msec:
|
if msec: # pragma: no cover - currently unused
|
||||||
s = val
|
s = val
|
||||||
# Pad to always return microseconds.
|
# Pad to always return microseconds.
|
||||||
s += "0" * (6 - len(s))
|
s += "0" * (6 - len(s))
|
||||||
|
@ -166,21 +154,14 @@ def reGroupDictStrptime(found_dict, msec=False):
|
||||||
elif key == 'a':
|
elif key == 'a':
|
||||||
weekday = locale_time.a_weekday.index(val.lower())
|
weekday = locale_time.a_weekday.index(val.lower())
|
||||||
elif key == 'w':
|
elif key == 'w':
|
||||||
weekday = int(val)
|
weekday = int(val) - 1
|
||||||
if weekday == 0:
|
if weekday < 0: weekday = 6
|
||||||
weekday = 6
|
|
||||||
else:
|
|
||||||
weekday -= 1
|
|
||||||
elif key == 'j':
|
elif key == 'j':
|
||||||
julian = int(val)
|
julian = int(val)
|
||||||
elif key in ('U', 'W'):
|
elif key in ('U', 'W'):
|
||||||
week_of_year = int(val)
|
week_of_year = int(val)
|
||||||
if key == 'U':
|
# U starts week on Sunday, W - on Monday
|
||||||
# U starts week on Sunday.
|
week_of_year_start = 6 if key == 'U' else 0
|
||||||
week_of_year_start = 6
|
|
||||||
else:
|
|
||||||
# W starts week on Monday.
|
|
||||||
week_of_year_start = 0
|
|
||||||
elif key == 'z':
|
elif key == 'z':
|
||||||
z = val
|
z = val
|
||||||
if z in ("Z", "UTC", "GMT"):
|
if z in ("Z", "UTC", "GMT"):
|
||||||
|
@ -199,31 +180,28 @@ def reGroupDictStrptime(found_dict, msec=False):
|
||||||
# Fail2Ban will assume it's this year
|
# Fail2Ban will assume it's this year
|
||||||
assume_year = False
|
assume_year = False
|
||||||
if year is None:
|
if year is None:
|
||||||
|
if not now: now = MyTime.now()
|
||||||
year = now.year
|
year = now.year
|
||||||
assume_year = True
|
assume_year = True
|
||||||
|
if month is None or day is None:
|
||||||
# If we know the week of the year and what day of that week, we can figure
|
# If we know the week of the year and what day of that week, we can figure
|
||||||
# out the Julian day of the year.
|
# out the Julian day of the year.
|
||||||
if julian == -1 and week_of_year != -1 and weekday != -1:
|
if julian is None and week_of_year is not None and weekday is not None:
|
||||||
week_starts_Mon = True if week_of_year_start == 0 else False
|
|
||||||
julian = _calc_julian_from_U_or_W(year, week_of_year, weekday,
|
julian = _calc_julian_from_U_or_W(year, week_of_year, weekday,
|
||||||
week_starts_Mon)
|
(week_of_year_start == 0))
|
||||||
# Cannot pre-calculate datetime.datetime() since can change in Julian
|
# Cannot pre-calculate datetime.datetime() since can change in Julian
|
||||||
# calculation and thus could have different value for the day of the week
|
# calculation and thus could have different value for the day of the week
|
||||||
# calculation.
|
# calculation.
|
||||||
if julian != -1 and (month is None or day is None):
|
if julian is not None:
|
||||||
datetime_result = datetime.datetime.fromordinal((julian - 1) + datetime.datetime(year, 1, 1).toordinal())
|
datetime_result = datetime.datetime.fromordinal((julian - 1) + datetime.datetime(year, 1, 1).toordinal())
|
||||||
year = datetime_result.year
|
year = datetime_result.year
|
||||||
month = datetime_result.month
|
month = datetime_result.month
|
||||||
day = datetime_result.day
|
day = datetime_result.day
|
||||||
# Add timezone info
|
|
||||||
if tzoffset is not None:
|
|
||||||
gmtoff = tzoffset * 60
|
|
||||||
else:
|
|
||||||
gmtoff = None
|
|
||||||
|
|
||||||
# Fail2Ban assume today
|
# Fail2Ban assume today
|
||||||
assume_today = False
|
assume_today = False
|
||||||
if month is None and day is None:
|
if month is None and day is None:
|
||||||
|
if not now: now = MyTime.now()
|
||||||
month = now.month
|
month = now.month
|
||||||
day = now.day
|
day = now.day
|
||||||
assume_today = True
|
assume_today = True
|
||||||
|
@ -231,22 +209,28 @@ def reGroupDictStrptime(found_dict, msec=False):
|
||||||
# Actully create date
|
# Actully create date
|
||||||
date_result = datetime.datetime(
|
date_result = datetime.datetime(
|
||||||
year, month, day, hour, minute, second, fraction)
|
year, month, day, hour, minute, second, fraction)
|
||||||
if gmtoff is not None:
|
# Add timezone info
|
||||||
date_result = date_result - datetime.timedelta(seconds=gmtoff)
|
if tzoffset is not None:
|
||||||
|
date_result -= datetime.timedelta(seconds=tzoffset * 60)
|
||||||
|
|
||||||
if date_result > now and assume_today:
|
if assume_today:
|
||||||
|
if not now: now = MyTime.now()
|
||||||
|
if date_result > now:
|
||||||
# Rollover at midnight, could mean it's yesterday...
|
# Rollover at midnight, could mean it's yesterday...
|
||||||
date_result = date_result - datetime.timedelta(days=1)
|
date_result -= datetime.timedelta(days=1)
|
||||||
if date_result > now and assume_year:
|
if assume_year:
|
||||||
|
if not now: now = MyTime.now()
|
||||||
|
if date_result > now:
|
||||||
# Could be last year?
|
# Could be last year?
|
||||||
# also reset month and day as it's not yesterday...
|
# also reset month and day as it's not yesterday...
|
||||||
date_result = date_result.replace(
|
date_result = date_result.replace(
|
||||||
year=year-1, month=month, day=day)
|
year=year-1, month=month, day=day)
|
||||||
|
|
||||||
if gmtoff is not None:
|
# make time:
|
||||||
|
if tzoffset is not None:
|
||||||
tm = calendar.timegm(date_result.utctimetuple())
|
tm = calendar.timegm(date_result.utctimetuple())
|
||||||
else:
|
else:
|
||||||
tm = time.mktime(date_result.timetuple())
|
tm = time.mktime(date_result.timetuple())
|
||||||
if msec:
|
if msec: # pragma: no cover - currently unused
|
||||||
tm += fraction/1000000.0
|
tm += fraction/1000000.0
|
||||||
return tm
|
return tm
|
||||||
|
|
|
@ -298,6 +298,16 @@ iso8601 = DatePatternRegex("%Y-%m-%d[T ]%H:%M:%S(?:\.%f)?%z")
|
||||||
|
|
||||||
class CustomDateFormatsTest(unittest.TestCase):
|
class CustomDateFormatsTest(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
"""Call before every test case."""
|
||||||
|
unittest.TestCase.setUp(self)
|
||||||
|
setUpMyTime()
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
"""Call after every test case."""
|
||||||
|
unittest.TestCase.tearDown(self)
|
||||||
|
tearDownMyTime()
|
||||||
|
|
||||||
def testIso8601(self):
|
def testIso8601(self):
|
||||||
date = datetime.datetime.utcfromtimestamp(
|
date = datetime.datetime.utcfromtimestamp(
|
||||||
iso8601.getDate("2007-01-25T12:00:00Z")[0])
|
iso8601.getDate("2007-01-25T12:00:00Z")[0])
|
||||||
|
@ -411,6 +421,37 @@ class CustomDateFormatsTest(unittest.TestCase):
|
||||||
else:
|
else:
|
||||||
self.assertEqual(date, None)
|
self.assertEqual(date, None)
|
||||||
|
|
||||||
|
def testVariousFormatSpecs(self):
|
||||||
|
for (matched, dp, line) in (
|
||||||
|
# cover %B (full-month-name) and %I (as 12 == 0):
|
||||||
|
(1106438399.0, "^%B %Exd %I:%ExM:%ExS**", 'January 23 12:59:59'),
|
||||||
|
# cover %U (week of year starts on sunday) and %A (weekday):
|
||||||
|
(985208399.0, "^%y %U %A %ExH:%ExM:%ExS**", '01 11 Wednesday 21:59:59'),
|
||||||
|
# cover %W (week of year starts on monday) and %A (weekday):
|
||||||
|
(984603599.0, "^%y %W %A %ExH:%ExM:%ExS**", '01 11 Wednesday 21:59:59'),
|
||||||
|
# cover %W (week of year starts on monday) and %w (weekday, 0 - sunday):
|
||||||
|
(984949199.0, "^%y %W %w %ExH:%ExM:%ExS**", '01 11 0 21:59:59'),
|
||||||
|
# cover %W (week of year starts on monday) and %w (weekday, 6 - saturday):
|
||||||
|
(984862799.0, "^%y %W %w %ExH:%ExM:%ExS**", '01 11 6 21:59:59'),
|
||||||
|
# cover time only, current date, in test cases now == 14 Aug 2005 12:00 -> back to yesterday (13 Aug):
|
||||||
|
(1123963199.0, "^%ExH:%ExM:%ExS**", '21:59:59'),
|
||||||
|
# cover time only, current date, in test cases now == 14 Aug 2005 12:00 -> today (14 Aug):
|
||||||
|
(1123970401.0, "^%ExH:%ExM:%ExS**", '00:00:01'),
|
||||||
|
# cover date with current year, in test cases now == Aug 2005 -> back to last year (Sep 2004):
|
||||||
|
(1094068799.0, "^%m/%d %ExH:%ExM:%ExS**", '09/01 21:59:59'),
|
||||||
|
):
|
||||||
|
logSys.debug('== test: %r', (matched, dp, line))
|
||||||
|
dd = DateDetector()
|
||||||
|
dd.appendTemplate(dp)
|
||||||
|
date = dd.getTime(line)
|
||||||
|
if matched:
|
||||||
|
self.assertTrue(date)
|
||||||
|
if isinstance(matched, basestring): # pragma: no cover
|
||||||
|
self.assertEqual(matched, date[1].group(1))
|
||||||
|
else:
|
||||||
|
self.assertEqual(matched, date[0])
|
||||||
|
else: # pragma: no cover
|
||||||
|
self.assertEqual(date, None)
|
||||||
|
|
||||||
# def testDefaultTempate(self):
|
# def testDefaultTempate(self):
|
||||||
# self.__datedetector.setDefaultRegex("^\S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2}")
|
# self.__datedetector.setDefaultRegex("^\S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2}")
|
||||||
|
|
Loading…
Reference in New Issue