From b96059987cb83cb54d718289e44aaf3f33bdd1a6 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Wed, 18 Sep 2019 10:30:57 -0700 Subject: [PATCH 1/2] BUG/CLN: DatetimeTZDtype.construct_from_string Exception --- pandas/core/dtypes/dtypes.py | 19 +++++++++++-------- pandas/tests/dtypes/test_dtypes.py | 11 ++++++++++- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/pandas/core/dtypes/dtypes.py b/pandas/core/dtypes/dtypes.py index aa7e6801ba431..fcdb89dd8a334 100644 --- a/pandas/core/dtypes/dtypes.py +++ b/pandas/core/dtypes/dtypes.py @@ -685,7 +685,7 @@ def __init__(self, unit="ns", tz=None): tz = timezones.tz_standardize(tz) elif tz is not None: raise pytz.UnknownTimeZoneError(tz) - elif tz is None: + if tz is None: raise TypeError("A 'tz' is required.") self._unit = unit @@ -737,14 +737,17 @@ def construct_from_string(cls, string): """ if isinstance(string, str): msg = "Could not construct DatetimeTZDtype from '{}'" - try: - match = cls._match.match(string) - if match: - d = match.groupdict() + match = cls._match.match(string) + if match: + d = match.groupdict() + try: return cls(unit=d["unit"], tz=d["tz"]) - except Exception: - # TODO(py3): Change this pass to `raise TypeError(msg) from e` - pass + except (KeyError, TypeError, ValueError) as err: + # KeyError if maybe_get_tz tries and fails to get a + # pytz timezone (actually pytz.UnknownTimeZoneError). + # TypeError if we pass a nonsense tz; + # ValueError if we pass a unit other than "ns" + raise TypeError(msg.format(string)) from err raise TypeError(msg.format(string)) raise TypeError("Could not construct DatetimeTZDtype") diff --git a/pandas/tests/dtypes/test_dtypes.py b/pandas/tests/dtypes/test_dtypes.py index 3288c9c584565..67a16d65246ec 100644 --- a/pandas/tests/dtypes/test_dtypes.py +++ b/pandas/tests/dtypes/test_dtypes.py @@ -248,9 +248,18 @@ def test_construct_from_string_raises(self): with pytest.raises(TypeError, match="notatz"): DatetimeTZDtype.construct_from_string("datetime64[ns, notatz]") - with pytest.raises(TypeError, match="^Could not construct DatetimeTZDtype$"): + msg = "^Could not construct DatetimeTZDtype$" + with pytest.raises(TypeError, match=msg): DatetimeTZDtype.construct_from_string(["datetime64[ns, notatz]"]) + with pytest.raises(TypeError, match=msg): + # non-nano unit + DatetimeTZDtype.construct_from_string(["datetime64[ps, UTC]"]) + + with pytest.raises(TypeError, match=msg): + # dateutil str that returns None from gettz + DatetimeTZDtype.construct_from_string(["datetime64[ns, dateutil/invalid]"]) + def test_is_dtype(self): assert not DatetimeTZDtype.is_dtype(None) assert DatetimeTZDtype.is_dtype(self.dtype) From 509665e233eeaed3ca307f964742f5a8827de9f1 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Wed, 18 Sep 2019 10:33:22 -0700 Subject: [PATCH 2/2] update test --- pandas/tests/dtypes/test_dtypes.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pandas/tests/dtypes/test_dtypes.py b/pandas/tests/dtypes/test_dtypes.py index 67a16d65246ec..6013e58bc6929 100644 --- a/pandas/tests/dtypes/test_dtypes.py +++ b/pandas/tests/dtypes/test_dtypes.py @@ -248,17 +248,18 @@ def test_construct_from_string_raises(self): with pytest.raises(TypeError, match="notatz"): DatetimeTZDtype.construct_from_string("datetime64[ns, notatz]") - msg = "^Could not construct DatetimeTZDtype$" + msg = "^Could not construct DatetimeTZDtype" with pytest.raises(TypeError, match=msg): + # list instead of string DatetimeTZDtype.construct_from_string(["datetime64[ns, notatz]"]) with pytest.raises(TypeError, match=msg): # non-nano unit - DatetimeTZDtype.construct_from_string(["datetime64[ps, UTC]"]) + DatetimeTZDtype.construct_from_string("datetime64[ps, UTC]") with pytest.raises(TypeError, match=msg): # dateutil str that returns None from gettz - DatetimeTZDtype.construct_from_string(["datetime64[ns, dateutil/invalid]"]) + DatetimeTZDtype.construct_from_string("datetime64[ns, dateutil/invalid]") def test_is_dtype(self): assert not DatetimeTZDtype.is_dtype(None)