From 2ac141a5d8d875c957ad7a278011842540d12484 Mon Sep 17 00:00:00 2001 From: sdementen Date: Fri, 27 Jan 2017 07:15:05 +0100 Subject: [PATCH 1/7] fix for issue #15240 replace **kwd argument to explicit argument to raise TypeError when wrong argument name is given --- pandas/tslib.pyx | 55 ++++++++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/pandas/tslib.pyx b/pandas/tslib.pyx index 7c65ab5422309..672cc97ea1ebd 100644 --- a/pandas/tslib.pyx +++ b/pandas/tslib.pyx @@ -650,7 +650,9 @@ class Timestamp(_Timestamp): astimezone = tz_convert - def replace(self, **kwds): + def replace(self, year=None, month=None, day=None, + hour=None, minute=None, second=None, microsecond=None, nanosecond=None, + tzinfo=None) """ implements datetime.replace, handles nanoseconds @@ -675,10 +677,10 @@ class Timestamp(_Timestamp): _TSObject ts # set to naive if needed - tzinfo = self.tzinfo + _tzinfo = self.tzinfo value = self.value - if tzinfo is not None: - value = tz_convert_single(value, 'UTC', tzinfo) + if _tzinfo is not None: + value = tz_convert_single(value, 'UTC', _tzinfo) # setup components pandas_datetime_to_datetimestruct(value, PANDAS_FR_ns, &dts) @@ -692,27 +694,24 @@ class Timestamp(_Timestamp): "{v} for {k}".format(v=type(v), k=k)) return v - for k, v in kwds.items(): - if k == 'year': - dts.year = validate(k, v) - elif k == 'month': - dts.month = validate(k, v) - elif k == 'day': - dts.day = validate(k, v) - elif k == 'hour': - dts.hour = validate(k, v) - elif k == 'minute': - dts.min = validate(k, v) - elif k == 'second': - dts.sec = validate(k, v) - elif k == 'microsecond': - dts.us = validate(k, v) - elif k == 'nanosecond': - dts.ps = validate(k, v) * 1000 - elif k == 'tzinfo': - tzinfo = v - else: - raise ValueError("invalid name {} passed".format(k)) + if year is not None: + dts.year = validate('year', year) + if month is not None: + dts.month = validate('month', month) + if day is not None: + dts.day = validate('day', day) + if hour is not None: + dts.hour = validate('hour', hour) + if minute is not None: + dts.min = validate('minute', minute) + if second is not None: + dts.sec = validate('second', second) + if microsecond is not None: + dts.us = validate('microsecond', microsecond) + if nanosecond is not None: + dts.ps = validate('nanosecond', nanosecond) * 1000 + if tzinfo is not None: + _tzinfo = tzinfo # reconstruct & check bounds value = pandas_datetimestruct_to_datetime(PANDAS_FR_ns, &dts) @@ -720,10 +719,10 @@ class Timestamp(_Timestamp): _check_dts_bounds(&dts) # set tz if needed - if tzinfo is not None: - value = tz_convert_single(value, tzinfo, 'UTC') + if _tzinfo is not None: + value = tz_convert_single(value, _tzinfo, 'UTC') - result = create_timestamp_from_ts(value, dts, tzinfo, self.freq) + result = create_timestamp_from_ts(value, dts, _tzinfo, self.freq) return result From d5c7b0a28c521dd6dfad9d12bda31e7bd1004c68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20de=20Menten?= Date: Fri, 27 Jan 2017 22:07:36 +0100 Subject: [PATCH 2/7] update exception type raised when wrong argument to Timestamp.replace --- pandas/tseries/tests/test_timezones.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/tseries/tests/test_timezones.py b/pandas/tseries/tests/test_timezones.py index db8cda5c76479..88c607a863869 100644 --- a/pandas/tseries/tests/test_timezones.py +++ b/pandas/tseries/tests/test_timezones.py @@ -1198,7 +1198,7 @@ def test_replace(self): # error def f(): dt.replace(foo=5) - self.assertRaises(ValueError, f) + self.assertRaises(TypeError, f) def f(): dt.replace(hour=0.1) From 52630542dd506993c56d3b5311d8cd2958aecd3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20de=20Menten?= Date: Fri, 27 Jan 2017 22:08:00 +0100 Subject: [PATCH 3/7] fix typos + update doc --- pandas/tslib.pyx | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/pandas/tslib.pyx b/pandas/tslib.pyx index 672cc97ea1ebd..f52bd8ea5f5f2 100644 --- a/pandas/tslib.pyx +++ b/pandas/tslib.pyx @@ -652,18 +652,21 @@ class Timestamp(_Timestamp): def replace(self, year=None, month=None, day=None, hour=None, minute=None, second=None, microsecond=None, nanosecond=None, - tzinfo=None) + tzinfo=None): """ implements datetime.replace, handles nanoseconds Parameters ---------- - kwargs: key-value dict - - accepted keywords are: - year, month, day, hour, minute, second, microsecond, nanosecond, tzinfo - - values must be integer, or for tzinfo, a tz-convertible + year : int, optional + month : int, optional + day : int, optional + hour : int, optional + minute : int, optional + second : int, optional + microsecond : int, optional + nanosecond: int, optional + tzinfo : tz-convertible, optional Returns ------- @@ -673,7 +676,7 @@ class Timestamp(_Timestamp): cdef: pandas_datetimestruct dts int64_t value - object tzinfo, result, k, v + object _tzinfo, result, k, v _TSObject ts # set to naive if needed From 1a407776ed0132797fc5e639daf9c2df93954d3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20de=20Menten?= Date: Fri, 27 Jan 2017 22:16:41 +0100 Subject: [PATCH 4/7] update what's new with bug fix --- doc/source/whatsnew/v0.20.0.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/source/whatsnew/v0.20.0.txt b/doc/source/whatsnew/v0.20.0.txt index afe2758db9ab1..ffed06a173725 100644 --- a/doc/source/whatsnew/v0.20.0.txt +++ b/doc/source/whatsnew/v0.20.0.txt @@ -416,6 +416,7 @@ Performance Improvements Bug Fixes ~~~~~~~~~ +- Bug in ``Timestamp.replace`` wrong exception raised when wrong argument name given (:issue:`15240`) - Bug in ``Index`` power operations with reversed operands (:issue:`14973`) - Bug in ``TimedeltaIndex`` addition where overflow was being allowed without error (:issue:`14816`) - Bug in ``TimedeltaIndex`` raising a ``ValueError`` when boolean indexing with ``loc`` (:issue:`14946`) From 9455ee9c3b5f526930eea74c4679bfe66e4666b1 Mon Sep 17 00:00:00 2001 From: sdementen Date: Fri, 27 Jan 2017 07:15:05 +0100 Subject: [PATCH 5/7] fix for issue #15240 replace **kwd argument to explicit argument to raise TypeError when wrong argument name is given --- pandas/tslib.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/tslib.pyx b/pandas/tslib.pyx index f52bd8ea5f5f2..8a9ce2fc22934 100644 --- a/pandas/tslib.pyx +++ b/pandas/tslib.pyx @@ -650,7 +650,7 @@ class Timestamp(_Timestamp): astimezone = tz_convert - def replace(self, year=None, month=None, day=None, + def replace(self, year=None, month=None, day=None, hour=None, minute=None, second=None, microsecond=None, nanosecond=None, tzinfo=None): """ From 52b6c2c9e04fd7cc204f1b824cfc2fbad60f4a84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20de=20Menten?= Date: Fri, 27 Jan 2017 22:28:07 +0100 Subject: [PATCH 6/7] improve description of whatsnew item --- doc/source/whatsnew/v0.20.0.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v0.20.0.txt b/doc/source/whatsnew/v0.20.0.txt index ffed06a173725..7f1b94dfa3e47 100644 --- a/doc/source/whatsnew/v0.20.0.txt +++ b/doc/source/whatsnew/v0.20.0.txt @@ -416,7 +416,7 @@ Performance Improvements Bug Fixes ~~~~~~~~~ -- Bug in ``Timestamp.replace`` wrong exception raised when wrong argument name given (:issue:`15240`) +- Bug in ``Timestamp.replace`` exception ValueError raised when wrong argument name given, should be TypeError (:issue:`15240`) - Bug in ``Index`` power operations with reversed operands (:issue:`14973`) - Bug in ``TimedeltaIndex`` addition where overflow was being allowed without error (:issue:`14816`) - Bug in ``TimedeltaIndex`` raising a ``ValueError`` when boolean indexing with ``loc`` (:issue:`14946`) From e70e75a3e0690d16b3e76a6b99e4500a61532ba3 Mon Sep 17 00:00:00 2001 From: Jeff Reback Date: Sat, 28 Jan 2017 07:38:19 -0500 Subject: [PATCH 7/7] use tzinfo=object to accept None as a default parameter --- doc/source/whatsnew/v0.20.0.txt | 2 +- pandas/tseries/tests/test_timezones.py | 1 - pandas/tslib.pyx | 7 ++++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/source/whatsnew/v0.20.0.txt b/doc/source/whatsnew/v0.20.0.txt index 7f1b94dfa3e47..f87fad051fad2 100644 --- a/doc/source/whatsnew/v0.20.0.txt +++ b/doc/source/whatsnew/v0.20.0.txt @@ -416,7 +416,7 @@ Performance Improvements Bug Fixes ~~~~~~~~~ -- Bug in ``Timestamp.replace`` exception ValueError raised when wrong argument name given, should be TypeError (:issue:`15240`) +- Bug in ``Timestamp.replace`` now raises ``TypeError`` when incorrect argument names are given; previously this raised ``ValueError`` (:issue:`15240`) - Bug in ``Index`` power operations with reversed operands (:issue:`14973`) - Bug in ``TimedeltaIndex`` addition where overflow was being allowed without error (:issue:`14816`) - Bug in ``TimedeltaIndex`` raising a ``ValueError`` when boolean indexing with ``loc`` (:issue:`14946`) diff --git a/pandas/tseries/tests/test_timezones.py b/pandas/tseries/tests/test_timezones.py index 88c607a863869..64787b6e4e79a 100644 --- a/pandas/tseries/tests/test_timezones.py +++ b/pandas/tseries/tests/test_timezones.py @@ -826,7 +826,6 @@ def test_date_range_span_dst_transition(self): def test_convert_datetime_list(self): dr = date_range('2012-06-02', periods=10, tz=self.tzstr('US/Eastern'), name='foo') - dr2 = DatetimeIndex(list(dr), name='foo') self.assert_index_equal(dr, dr2) self.assertEqual(dr.tz, dr2.tz) diff --git a/pandas/tslib.pyx b/pandas/tslib.pyx index 8a9ce2fc22934..57018c3bd466f 100644 --- a/pandas/tslib.pyx +++ b/pandas/tslib.pyx @@ -652,7 +652,7 @@ class Timestamp(_Timestamp): def replace(self, year=None, month=None, day=None, hour=None, minute=None, second=None, microsecond=None, nanosecond=None, - tzinfo=None): + tzinfo=object, fold=0): """ implements datetime.replace, handles nanoseconds @@ -667,6 +667,8 @@ class Timestamp(_Timestamp): microsecond : int, optional nanosecond: int, optional tzinfo : tz-convertible, optional + fold : int, optional, default is 0 + added in 3.6, NotImplemented Returns ------- @@ -713,7 +715,7 @@ class Timestamp(_Timestamp): dts.us = validate('microsecond', microsecond) if nanosecond is not None: dts.ps = validate('nanosecond', nanosecond) * 1000 - if tzinfo is not None: + if tzinfo is not object: _tzinfo = tzinfo # reconstruct & check bounds @@ -726,7 +728,6 @@ class Timestamp(_Timestamp): value = tz_convert_single(value, _tzinfo, 'UTC') result = create_timestamp_from_ts(value, dts, _tzinfo, self.freq) - return result def isoformat(self, sep='T'):