From 94c73ec95223d3dbd4c47a905bf67c04fba285ac Mon Sep 17 00:00:00 2001 From: David Bew Date: Mon, 16 Jun 2014 17:10:40 +0100 Subject: [PATCH] Fix cache key collision and add test for cache key distinctness. --- pandas/tseries/tests/test_timezones.py | 15 +++++++++++++++ pandas/tslib.pyx | 7 ++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/pandas/tseries/tests/test_timezones.py b/pandas/tseries/tests/test_timezones.py index e6da490e1f722..b1d8bdd9f81ce 100644 --- a/pandas/tseries/tests/test_timezones.py +++ b/pandas/tseries/tests/test_timezones.py @@ -805,6 +805,21 @@ def test_utc_with_system_utc(self): self.assertEqual(ts, ts.tz_convert(dateutil.tz.tzutc())) +class TestTimeZoneCacheKey(tm.TestCase): + def test_cache_keys_are_distinct_for_pytz_vs_dateutil(self): + tzs = pytz.common_timezones + for tz_name in tzs: + if tz_name == 'UTC': + # skip utc as it's a special case in dateutil + continue + tz_p = tslib.maybe_get_tz(tz_name) + tz_d = tslib.maybe_get_tz('dateutil/' + tz_name) + if tz_d is None: + # skip timezones that dateutil doesn't know about. + continue + self.assertNotEqual(tslib._p_tz_cache_key(tz_p), tslib._p_tz_cache_key(tz_d)) + + class TestTimeZones(tm.TestCase): _multiprocess_can_split_ = True diff --git a/pandas/tslib.pyx b/pandas/tslib.pyx index c36d34b2199d8..2e0e8af3f5119 100644 --- a/pandas/tslib.pyx +++ b/pandas/tslib.pyx @@ -1962,6 +1962,11 @@ cdef inline bint _treat_tz_as_dateutil(object tz): return hasattr(tz, '_trans_list') and hasattr(tz, '_trans_idx') +def _p_tz_cache_key(tz): + ''' Python interface for cache function to facilitate testing.''' + return _tz_cache_key(tz) + + cdef inline object _tz_cache_key(object tz): """ Return the key in the cache for the timezone info object or None if unknown. @@ -1982,7 +1987,7 @@ cdef inline object _tz_cache_key(object tz): raise ValueError('Bad tz filename. Dateutil on python 3 on windows has a bug which causes tzfile._filename to be the same for all ' 'timezone files. Please construct dateutil timezones implicitly by passing a string like "dateutil/Europe/London" ' 'when you construct your pandas objects instead of passing a timezone object. See https://github.com/pydata/pandas/pull/7362') - return tz._filename + return 'dateutil' + tz._filename else: return None