diff --git a/ckan/lib/email_notifications.py b/ckan/lib/email_notifications.py index 144d9a8a4fd..d4033bde974 100644 --- a/ckan/lib/email_notifications.py +++ b/ckan/lib/email_notifications.py @@ -5,13 +5,69 @@ ''' import datetime +import re import pylons import ckan.model as model import ckan.logic as logic import ckan.lib.base as base -import ckan.lib.helpers as helpers + + +def string_to_timedelta(s): + '''Parse a string s and return a standard datetime.timedelta object. + + Handles days, hours, minutes, seconds, and microseconds. + + Accepts strings in these formats: + + 2 days + 14 days + 4:35:00 (hours, minutes and seconds) + 4:35:12.087465 (hours, minutes, seconds and microseconds) + 7 days, 3:23:34 + 7 days, 3:23:34.087465 + .087465 (microseconds only) + + :raises ckan.logic.ParameterError: if the given string does not match any + of the recognised formats + + ''' + patterns = [] + days_only_pattern = '(?P\d+) days' + patterns.append(days_only_pattern) + hms_only_pattern = '(?P\d?\d):(?P\d\d):(?P\d\d)' + patterns.append(hms_only_pattern) + ms_only_pattern = '.(?P\d\d\d)(?P\d\d\d)' + patterns.append(ms_only_pattern) + hms_and_ms_pattern = hms_only_pattern + ms_only_pattern + patterns.append(hms_and_ms_pattern) + days_and_hms_pattern = '{0}, {1}'.format(days_only_pattern, + hms_only_pattern) + patterns.append(days_and_hms_pattern) + days_and_hms_and_ms_pattern = days_and_hms_pattern + ms_only_pattern + patterns.append(days_and_hms_and_ms_pattern) + + for pattern in patterns: + match = re.match('^{0}$'.format(pattern), s) + if match: + break + + if not match: + import ckan.logic + raise ckan.logic.ParameterError('Not a valid time: {0}'.format(s)) + + gd = match.groupdict() + days = int(gd.get('days', '0')) + hours = int(gd.get('hours', '0')) + minutes = int(gd.get('minutes', '0')) + seconds = int(gd.get('seconds', '0')) + milliseconds = int(gd.get('milliseconds', '0')) + microseconds = int(gd.get('microseconds', '0')) + delta = datetime.timedelta(days=days, hours=hours, minutes=minutes, + seconds=seconds, milliseconds=milliseconds, + microseconds=microseconds) + return delta def _notifications_for_activities(activities, user_dict): @@ -128,7 +184,7 @@ def get_and_send_notifications_for_user(user): # notifications from longer ago than this time will not be sent. email_notifications_since = pylons.config.get( 'ckan.email_notifications_since', '2 days') - email_notifications_since = helpers.string_to_timedelta( + email_notifications_since = string_to_timedelta( email_notifications_since) email_notifications_since = (datetime.datetime.now() - email_notifications_since) diff --git a/ckan/lib/helpers.py b/ckan/lib/helpers.py index 1cdcffb1545..af0bb8199e9 100644 --- a/ckan/lib/helpers.py +++ b/ckan/lib/helpers.py @@ -1315,62 +1315,6 @@ def resource_preview(resource, pkg_id): ) -def string_to_timedelta(s): - '''Parse a string s and return a standard datetime.timedelta object. - - Handles days, hours, minutes, seconds, and microseconds. - - Accepts strings in these formats: - - 2 days - 14 days - 4:35:00 (hours, minutes and seconds) - 4:35:12.087465 (hours, minutes, seconds and microseconds) - 7 days, 3:23:34 - 7 days, 3:23:34.087465 - .087465 (microseconds only) - - :raises ckan.logic.ParameterError: if the given string does not match any - of the recognised formats - - ''' - patterns = [] - days_only_pattern = '(?P\d+) days' - patterns.append(days_only_pattern) - hms_only_pattern = '(?P\d?\d):(?P\d\d):(?P\d\d)' - patterns.append(hms_only_pattern) - ms_only_pattern = '.(?P\d\d\d)(?P\d\d\d)' - patterns.append(ms_only_pattern) - hms_and_ms_pattern = hms_only_pattern + ms_only_pattern - patterns.append(hms_and_ms_pattern) - days_and_hms_pattern = '{0}, {1}'.format(days_only_pattern, - hms_only_pattern) - patterns.append(days_and_hms_pattern) - days_and_hms_and_ms_pattern = days_and_hms_pattern + ms_only_pattern - patterns.append(days_and_hms_and_ms_pattern) - - for pattern in patterns: - match = re.match('^{0}$'.format(pattern), s) - if match: - break - - if not match: - import ckan.logic - raise ckan.logic.ParameterError('Not a valid time: {0}'.format(s)) - - gd = match.groupdict() - days = int(gd.get('days', '0')) - hours = int(gd.get('hours', '0')) - minutes = int(gd.get('minutes', '0')) - seconds = int(gd.get('seconds', '0')) - milliseconds = int(gd.get('milliseconds', '0')) - microseconds = int(gd.get('microseconds', '0')) - delta = datetime.timedelta(days=days, hours=hours, minutes=minutes, - seconds=seconds, milliseconds=milliseconds, - microseconds=microseconds) - return delta - - # these are the functions that will end up in `h` template helpers __allowed_functions__ = [ # functions defined in ckan.lib.helpers diff --git a/ckan/tests/lib/test_email_notifications.py b/ckan/tests/lib/test_email_notifications.py new file mode 100644 index 00000000000..7f927798885 --- /dev/null +++ b/ckan/tests/lib/test_email_notifications.py @@ -0,0 +1,29 @@ +'''Tests for the ckan.lib.email_notifications module. + +Note that email_notifications is used by an action function, so most of the +tests for the module are done by testing the action function in +ckan.test.functional.api. This test module contains some additional unit tests. + +''' +import datetime + +import ckan.lib.email_notifications as email_notifications + + +def test_string_to_time_delta(): + assert email_notifications.string_to_timedelta('2 days') == ( + datetime.timedelta(days=2)) + assert email_notifications.string_to_timedelta('14 days') == ( + datetime.timedelta(days=14)) + assert email_notifications.string_to_timedelta('4:35:00') == ( + datetime.timedelta(hours=4, minutes=35, seconds=00)) + assert email_notifications.string_to_timedelta('4:35:12.087465') == ( + datetime.timedelta(hours=4, minutes=35, seconds=12, + milliseconds=87, microseconds=465)) + assert email_notifications.string_to_timedelta('7 days, 3:23:34') == ( + datetime.timedelta(days=7, hours=3, minutes=23, seconds=34)) + assert email_notifications.string_to_timedelta( + '7 days, 3:23:34.087465') == datetime.timedelta(days=7, hours=3, + minutes=23, seconds=34, milliseconds=87, microseconds=465) + assert email_notifications.string_to_timedelta('.123456') == ( + datetime.timedelta(milliseconds=123, microseconds=456)) diff --git a/ckan/tests/lib/test_helpers.py b/ckan/tests/lib/test_helpers.py index 85355cde8b9..68859977c62 100644 --- a/ckan/tests/lib/test_helpers.py +++ b/ckan/tests/lib/test_helpers.py @@ -177,20 +177,3 @@ def test_get_pkg_dict_extra(self): assert_equal(h.get_pkg_dict_extra(pkg_dict, 'extra_not_found'), None) assert_equal(h.get_pkg_dict_extra(pkg_dict, 'extra_not_found','default_value'), 'default_value') - - def test_string_to_time_delta(self): - assert h.string_to_timedelta('2 days') == datetime.timedelta(days=2) - assert h.string_to_timedelta('14 days') == datetime.timedelta( - days=14) - assert h.string_to_timedelta('4:35:00') == datetime.timedelta( - hours=4, minutes=35, seconds=00) - assert h.string_to_timedelta('4:35:12.087465') == datetime.timedelta( - hours=4, minutes=35, seconds=12, milliseconds=87, - microseconds=465) - assert h.string_to_timedelta('7 days, 3:23:34') == datetime.timedelta( - days=7, hours=3, minutes=23, seconds=34) - assert h.string_to_timedelta('7 days, 3:23:34.087465') == ( - datetime.timedelta(days=7, hours=3, minutes=23, seconds=34, - milliseconds=87, microseconds=465)) - assert h.string_to_timedelta('.123456') == datetime.timedelta( - milliseconds=123, microseconds=456)