Skip to content

Commit ad0fabe

Browse files
authored
Avoid crashing on importing babel.localtime when TZ envvar is malformed (#1100)
When `pytz` is _not_ installed, importing `babel.localtime` could fail (repeatedly) when the `TZ` environment variable is malformed enough to be caught by `_validate_tzfile_path`, which might throw a certain `ValueError`. (When `pytz` is installed, it would raise an `UnknownTimeZoneError` we already catch and ignore for the same sort of input.) Fixes #1092
1 parent 2f87363 commit ad0fabe

File tree

2 files changed

+43
-0
lines changed

2 files changed

+43
-0
lines changed

babel/localtime/_helpers.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@
22
import pytz
33
except ModuleNotFoundError:
44
pytz = None
5+
6+
try:
57
import zoneinfo
8+
except ModuleNotFoundError:
9+
zoneinfo = None
610

711

812
def _get_tzinfo(tzenv: str):
@@ -19,6 +23,16 @@ def _get_tzinfo(tzenv: str):
1923
else:
2024
try:
2125
return zoneinfo.ZoneInfo(tzenv)
26+
except ValueError as ve:
27+
# This is somewhat hacky, but since _validate_tzfile_path() doesn't
28+
# raise a specific error type, we'll need to check the message to be
29+
# one we know to be from that function.
30+
# If so, we pretend it meant that the TZ didn't exist, for the benefit
31+
# of `babel.localtime` catching the `LookupError` raised by
32+
# `_get_tzinfo_or_raise()`.
33+
# See https://github.com/python-babel/babel/issues/1092
34+
if str(ve).startswith("ZoneInfo keys "):
35+
return None
2236
except zoneinfo.ZoneInfoNotFoundError:
2337
pass
2438

tests/test_localtime.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import sys
2+
3+
import pytest
4+
5+
from babel.localtime import _helpers, get_localzone
6+
7+
8+
@pytest.mark.skipif(
9+
sys.platform == "win32",
10+
reason="Issue 1092 is not applicable on Windows",
11+
)
12+
def test_issue_1092_without_pytz(monkeypatch):
13+
pytest.importorskip("zoneinfo", reason="zoneinfo is not available")
14+
monkeypatch.setenv("TZ", "/UTC") # Malformed timezone name.
15+
# In case pytz _is_ also installed, we want to pretend it's not, so patch it out...
16+
monkeypatch.setattr(_helpers, "pytz", None)
17+
with pytest.raises(LookupError):
18+
get_localzone()
19+
20+
21+
@pytest.mark.skipif(
22+
sys.platform == "win32",
23+
reason="Issue 1092 is not applicable on Windows",
24+
)
25+
def test_issue_1092_with_pytz(monkeypatch):
26+
pytest.importorskip("pytz", reason="pytz is not installed")
27+
monkeypatch.setenv("TZ", "/UTC") # Malformed timezone name.
28+
with pytest.raises(LookupError):
29+
get_localzone()

0 commit comments

Comments
 (0)