Merge pull request #801 from pganssle/invalid_tz
Stop trying to add None to the weakref cache
diff --git a/changelog.d/672.bugfix.rst b/changelog.d/672.bugfix.rst
index 8714449..149981c 100644
--- a/changelog.d/672.bugfix.rst
+++ b/changelog.d/672.bugfix.rst
@@ -1 +1 @@
-Switched the ``tzoffset``, ``tzstr`` and ``gettz`` caches over to using weak references, so that the cache expires when no other references to the original ``tzinfo`` objects exist. This cache-expiry behavior is not considered part of the public interface and may change in the future. Requested by @pganssle (gh issue #635), implemented by @cs-cordero (gh pr #672).
+Switched the ``tzoffset``, ``tzstr`` and ``gettz`` caches over to using weak references, so that the cache expires when no other references to the original ``tzinfo`` objects exist. This cache-expiry behavior is not considered part of the public interface and may change in the future. Implemented by @cs-cordero (gh pr #672, #801)
diff --git a/dateutil/test/test_tz.py b/dateutil/test/test_tz.py
index 29c4d82..84416dd 100644
--- a/dateutil/test/test_tz.py
+++ b/dateutil/test/test_tz.py
@@ -8,6 +8,7 @@
from datetime import datetime, timedelta
from datetime import time as dt_time
from datetime import tzinfo
+from six import PY2
from six import BytesIO, StringIO
import unittest
@@ -1076,6 +1077,26 @@
@pytest.mark.gettz
+@pytest.mark.parametrize('badzone', [
+ 'Fake.Region/Abcdefghijklmnop', # Violates several tz project name rules
+])
+def test_gettz_badzone(badzone):
+ # Make sure passing a bad TZ string to gettz returns None (GH #800)
+ tzi = tz.gettz(badzone)
+ assert tzi is None
+
+
+@pytest.mark.gettz
+@pytest.mark.xfail(IS_WIN and PY2,
+ reason='tzwin fails with non-unicode characters on 2.7')
+def test_gettz_badzone_unicode():
+ # Make sure a unicode string can be passed to TZ (GH #802)
+ # When fixed, combine this with test_gettz_badzone
+ tzi = tz.gettz('🐼')
+ assert tzi is None
+
+
+@pytest.mark.gettz
@pytest.mark.xfail(IS_WIN, reason='zoneinfo separately cached')
def test_gettz_cache_clear():
NYC1 = tz.gettz('America/New_York')
diff --git a/dateutil/tz/tz.py b/dateutil/tz/tz.py
index ba0d8b7..3caac67 100644
--- a/dateutil/tz/tz.py
+++ b/dateutil/tz/tz.py
@@ -1539,10 +1539,15 @@
if rv is None:
rv = self.nocache(name=name)
- if not (name is None or isinstance(rv, tzlocal_classes)):
+ if not (name is None
+ or isinstance(rv, tzlocal_classes)
+ or rv is None):
# tzlocal is slightly more complicated than the other
# time zone providers because it depends on environment
# at construction time, so don't cache that.
+ #
+ # We also cannot store weak references to None, so we
+ # will also not store that.
self.__instances[name] = rv
return rv