Skip to content

Commit

Permalink
[#1635] Move string_to_timedelta() out of helpers
Browse files Browse the repository at this point in the history
This is not intended to be a template helper function so doesn't belong
in ckan/lib/helpers.py. Just put it in email_notifications, since that's
the only module that uses it.
  • Loading branch information
Sean Hammond committed Dec 11, 2012
1 parent 02cda1c commit 5e4669d
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 75 deletions.
60 changes: 58 additions & 2 deletions ckan/lib/email_notifications.py
Expand Up @@ -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<days>\d+) days'
patterns.append(days_only_pattern)
hms_only_pattern = '(?P<hours>\d?\d):(?P<minutes>\d\d):(?P<seconds>\d\d)'
patterns.append(hms_only_pattern)
ms_only_pattern = '.(?P<milliseconds>\d\d\d)(?P<microseconds>\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):
Expand Down Expand Up @@ -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)
Expand Down
56 changes: 0 additions & 56 deletions ckan/lib/helpers.py
Expand Up @@ -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<days>\d+) days'
patterns.append(days_only_pattern)
hms_only_pattern = '(?P<hours>\d?\d):(?P<minutes>\d\d):(?P<seconds>\d\d)'
patterns.append(hms_only_pattern)
ms_only_pattern = '.(?P<milliseconds>\d\d\d)(?P<microseconds>\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
Expand Down
29 changes: 29 additions & 0 deletions 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))
17 changes: 0 additions & 17 deletions ckan/tests/lib/test_helpers.py
Expand Up @@ -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)

0 comments on commit 5e4669d

Please sign in to comment.