From b3d432514714482702104dd7b32d517a70f720ab Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Thu, 9 Nov 2017 18:45:01 -0800 Subject: [PATCH 1/4] add validation functions, with fixed messages --- pandas/_libs/tslibs/offsets.pyx | 17 +++++++++++++++++ pandas/tseries/offsets.py | 33 ++++++++++----------------------- 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/pandas/_libs/tslibs/offsets.pyx b/pandas/_libs/tslibs/offsets.pyx index 87be9fa910101..5ca96f791b048 100644 --- a/pandas/_libs/tslibs/offsets.pyx +++ b/pandas/_libs/tslibs/offsets.pyx @@ -219,6 +219,23 @@ def _validate_business_time(t_input): raise ValueError("time data must be string or datetime.time") +def _validate_n(n): + if n == 0 or not isinstance(n, int): + raise ValueError('N cannot be 0') + + +def _validate_month(month): + if not isinstance(month, int) or not 1 <= month <= 12: + raise ValueError('Month must go from 1 to 12') + + +def _validate_weekday(weekday, allow_none=False): + if allow_none and weekday is None: + pass + elif not isinstance(weekday, int) or not 0 <= weekday <= 6: + raise ValueError('weekday must be 0<=weekday<=6, got ' + '{day}'.format(day=weekday)) + # --------------------------------------------------------------------- # Constructor Helpers diff --git a/pandas/tseries/offsets.py b/pandas/tseries/offsets.py index 5843aaa23be57..8a5e1b0a4a04b 100644 --- a/pandas/tseries/offsets.py +++ b/pandas/tseries/offsets.py @@ -18,7 +18,8 @@ from pandas._libs.tslibs.offsets import ( ApplyTypeError, as_datetime, _is_normalized, - _get_firstbday, _get_calendar, _to_dt64, _validate_business_time, + _get_firstbday, _get_calendar, _to_dt64, + _validate_business_time, _validate_n, _validate_month, _validate_weekday, _int_to_weekday, _weekday_to_int, _determine_offset, apply_index_wraps, @@ -1398,10 +1399,7 @@ def __init__(self, n=1, normalize=False, weekday=None): self.normalize = normalize self.weekday = weekday - if self.weekday is not None: - if self.weekday < 0 or self.weekday > 6: - raise ValueError('Day must be 0<=day<=6, got {day}' - .format(day=self.weekday)) + _validate_weekday(weekday, allow_none=True) self.kwds = {'weekday': weekday} @@ -1490,12 +1488,8 @@ def __init__(self, n=1, normalize=False, week=None, weekday=None): self.weekday = weekday self.week = week - if self.n == 0: - raise ValueError('N cannot be 0') - - if self.weekday < 0 or self.weekday > 6: - raise ValueError('Day must be 0<=day<=6, got {day}' - .format(day=self.weekday)) + _validate_n(n) + _validate_weekday(weekday) if self.week < 0 or self.week > 3: raise ValueError('Week must be 0<=week<=3, got {week}' .format(week=self.week)) @@ -1586,12 +1580,8 @@ def __init__(self, n=1, normalize=False, weekday=None): self.normalize = normalize self.weekday = weekday - if self.n == 0: - raise ValueError('N cannot be 0') - - if self.weekday < 0 or self.weekday > 6: - raise ValueError('Day must be 0<=day<=6, got {day}' - .format(day=self.weekday)) + _validate_n(n) + _validate_weekday(weekday) self.kwds = {'weekday': weekday} @@ -1848,8 +1838,7 @@ def __init__(self, n=1, normalize=False, month=None): month = month if month is not None else self._default_month self.month = month - if self.month < 1 or self.month > 12: - raise ValueError('Month must go from 1 to 12') + _validate_month(month) DateOffset.__init__(self, n=n, normalize=normalize, month=month) @@ -2102,8 +2091,7 @@ def __init__(self, n=1, normalize=False, weekday=0, startingMonth=1, self.kwds = {'weekday': weekday, 'startingMonth': startingMonth, 'variation': variation} - if self.n == 0: - raise ValueError('N cannot be 0') + _validate_n(n) if self.variation not in ["nearest", "last"]: raise ValueError('{variation} is not a valid variation' @@ -2354,8 +2342,7 @@ def __init__(self, n=1, normalize=False, weekday=0, startingMonth=1, 'qtr_with_extra_week': qtr_with_extra_week, 'variation': variation} - if self.n == 0: - raise ValueError('N cannot be 0') + _validate_n(n) @cache_readonly def _offset(self): From ada3854098cf08fd894241810061b3058023da29 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Thu, 9 Nov 2017 19:11:32 -0800 Subject: [PATCH 2/4] update regexes in tests --- pandas/_libs/tslibs/offsets.pyx | 12 ++++++------ pandas/tests/tseries/test_offsets.py | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/pandas/_libs/tslibs/offsets.pyx b/pandas/_libs/tslibs/offsets.pyx index 5ca96f791b048..040cb6b562fd0 100644 --- a/pandas/_libs/tslibs/offsets.pyx +++ b/pandas/_libs/tslibs/offsets.pyx @@ -212,8 +212,8 @@ def _validate_business_time(t_input): raise ValueError("time data must match '%H:%M' format") elif isinstance(t_input, dt_time): if t_input.second != 0 or t_input.microsecond != 0: - raise ValueError( - "time data must be specified only with hour and minute") + raise ValueError("time data must be specified only with " + "hour and minute") return t_input else: raise ValueError("time data must be string or datetime.time") @@ -221,20 +221,20 @@ def _validate_business_time(t_input): def _validate_n(n): if n == 0 or not isinstance(n, int): - raise ValueError('N cannot be 0') + raise ValueError("N cannot be 0") def _validate_month(month): if not isinstance(month, int) or not 1 <= month <= 12: - raise ValueError('Month must go from 1 to 12') + raise ValueError("Month must go from 1 to 12") def _validate_weekday(weekday, allow_none=False): if allow_none and weekday is None: pass elif not isinstance(weekday, int) or not 0 <= weekday <= 6: - raise ValueError('weekday must be 0<=weekday<=6, got ' - '{day}'.format(day=weekday)) + raise ValueError("weekday must be 0<=weekday<=6, got " + "{day}".format(day=weekday)) # --------------------------------------------------------------------- # Constructor Helpers diff --git a/pandas/tests/tseries/test_offsets.py b/pandas/tests/tseries/test_offsets.py index 4fd3bba01602f..2173e07913775 100644 --- a/pandas/tests/tseries/test_offsets.py +++ b/pandas/tests/tseries/test_offsets.py @@ -2192,7 +2192,7 @@ def test_repr(self): def test_corner(self): pytest.raises(ValueError, Week, weekday=7) tm.assert_raises_regex( - ValueError, "Day must be", Week, weekday=-1) + ValueError, "weekday must be", Week, weekday=-1) def test_isAnchored(self): assert Week(weekday=0).isAnchored() @@ -2263,9 +2263,9 @@ def test_constructor(self): n=1, week=4, weekday=0) tm.assert_raises_regex(ValueError, "^Week", WeekOfMonth, n=1, week=-1, weekday=0) - tm.assert_raises_regex(ValueError, "^Day", WeekOfMonth, + tm.assert_raises_regex(ValueError, "^weekday", WeekOfMonth, n=1, week=0, weekday=-1) - tm.assert_raises_regex(ValueError, "^Day", WeekOfMonth, + tm.assert_raises_regex(ValueError, "^weekday", WeekOfMonth, n=1, week=0, weekday=7) def test_repr(self): @@ -2347,10 +2347,10 @@ def test_constructor(self): tm.assert_raises_regex(ValueError, "^N cannot be 0", LastWeekOfMonth, n=0, weekday=1) - tm.assert_raises_regex(ValueError, "^Day", LastWeekOfMonth, n=1, + tm.assert_raises_regex(ValueError, "^weekday", LastWeekOfMonth, n=1, weekday=-1) tm.assert_raises_regex( - ValueError, "^Day", LastWeekOfMonth, n=1, weekday=7) + ValueError, "^weekday", LastWeekOfMonth, n=1, weekday=7) def test_offset(self): # Saturday From 9ef49b4d21c122d3b6712d50cadbae61b2e97c16 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Thu, 9 Nov 2017 21:53:46 -0800 Subject: [PATCH 3/4] whitespace fixup --- pandas/_libs/tslibs/offsets.pyx | 1 + 1 file changed, 1 insertion(+) diff --git a/pandas/_libs/tslibs/offsets.pyx b/pandas/_libs/tslibs/offsets.pyx index 040cb6b562fd0..5cde55cb36079 100644 --- a/pandas/_libs/tslibs/offsets.pyx +++ b/pandas/_libs/tslibs/offsets.pyx @@ -236,6 +236,7 @@ def _validate_weekday(weekday, allow_none=False): raise ValueError("weekday must be 0<=weekday<=6, got " "{day}".format(day=weekday)) + # --------------------------------------------------------------------- # Constructor Helpers From 94bb28613525b9efc7b35d6acba15592a2cca72e Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Fri, 10 Nov 2017 08:30:39 -0800 Subject: [PATCH 4/4] Add docstrings to validation funcs --- pandas/_libs/tslibs/offsets.pyx | 35 +++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/pandas/_libs/tslibs/offsets.pyx b/pandas/_libs/tslibs/offsets.pyx index 5cde55cb36079..b4892796aa982 100644 --- a/pandas/_libs/tslibs/offsets.pyx +++ b/pandas/_libs/tslibs/offsets.pyx @@ -220,16 +220,51 @@ def _validate_business_time(t_input): def _validate_n(n): + """ + Require that `n` be a nonzero integer. + + Parameters + ---------- + n : int + + Raises + ------ + ValueError + """ if n == 0 or not isinstance(n, int): raise ValueError("N cannot be 0") def _validate_month(month): + """ + Require that `month` be an integer between 1 and 12 inclusive. + + Parameters + ---------- + month : int + + Raises + ------ + ValueError + """ if not isinstance(month, int) or not 1 <= month <= 12: raise ValueError("Month must go from 1 to 12") def _validate_weekday(weekday, allow_none=False): + """ + Require that `weekday` be an integer between 0 and 6, inclusive, or that + None be explicitly allowed. + + Parameters + ---------- + weekday : int (or None) + allow_none : bool, default False + + Raises + ------ + ValueError + """ if allow_none and weekday is None: pass elif not isinstance(weekday, int) or not 0 <= weekday <= 6: