-
Notifications
You must be signed in to change notification settings - Fork 461
Description
Overview Description
When calling routines like babel.number.get_decimal_symbol, an internal import of babel.localtime fails under certain circumstances with a ValueError, that may easily slip awareness.
Steps to Reproduce
- Have a Unix system
- set TZ=/UTC
- in Python 3.9+ without
pytz, runbabel.numbers.parse_decimal("5.2")
Actual Results
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python3.10/dist-packages/babel/numbers.py", line 1103, in parse_decimal
group_symbol = get_group_symbol(locale, numbering_system=numbering_system)
File "/usr/local/lib/python3.10/dist-packages/babel/numbers.py", line 452, in get_group_symbol
return _get_number_symbols(locale, numbering_system=numbering_system).get('group', ',')
File "/usr/local/lib/python3.10/dist-packages/babel/numbers.py", line 335, in _get_number_symbols
return parsed_locale.number_symbols[numbering_system]
File "/usr/local/lib/python3.10/dist-packages/babel/core.py", line 640, in number_symbols
return self._data['number_symbols']
File "/usr/local/lib/python3.10/dist-packages/babel/core.py", line 439, in _data
self.__data = localedata.LocaleDataDict(localedata.load(str(self)))
File "/usr/local/lib/python3.10/dist-packages/babel/localedata.py", line 137, in load
data = load(parent).copy()
File "/usr/local/lib/python3.10/dist-packages/babel/localedata.py", line 137, in load
data = load(parent).copy()
File "/usr/local/lib/python3.10/dist-packages/babel/localedata.py", line 137, in load
data = load(parent).copy()
File "/usr/local/lib/python3.10/dist-packages/babel/localedata.py", line 143, in load
data = pickle.load(fileobj)
File "/usr/local/lib/python3.10/dist-packages/babel/dates.py", line 34, in <module>
from babel import localtime
File "/usr/local/lib/python3.10/dist-packages/babel/localtime/__init__.py", line 41, in <module>
LOCALTZ = get_localzone()
File "/usr/local/lib/python3.10/dist-packages/babel/localtime/__init__.py", line 37, in get_localzone
return _get_localzone()
File "/usr/local/lib/python3.10/dist-packages/babel/localtime/_unix.py", line 36, in _get_localzone
return _tz_from_env(tzenv)
File "/usr/local/lib/python3.10/dist-packages/babel/localtime/_unix.py", line 21, in _tz_from_env
return _get_tzinfo_or_raise(tzenv)
File "/usr/local/lib/python3.10/dist-packages/babel/localtime/_helpers.py", line 29, in _get_tzinfo_or_raise
tzinfo = _get_tzinfo(tzenv)
File "/usr/local/lib/python3.10/dist-packages/babel/localtime/_helpers.py", line 21, in _get_tzinfo
return zoneinfo.ZoneInfo(tzenv)
File "/usr/lib/python3.10/zoneinfo/_tzpath.py", line 67, in find_tzfile
_validate_tzfile_path(key)
File "/usr/lib/python3.10/zoneinfo/_tzpath.py", line 81, in _validate_tzfile_path
raise ValueError(
ValueError: ZoneInfo keys may not be absolute paths, got: /UTC
Expected Results
Decimal('5.2')
Reproducibility
Works repeatedly with many calls, as long as they rely on localtime.
Additional Information
AFAICT the babel.localtime submodule is loaded lazily in the course of processing calls like babel.number.parse_decimal or babel.number.get_decimal_symbol. On systems where pytz is not present, zoneinfo is loaded in babel.localtime._unix.py via babel.localtime.__init__.py, where also get_localzone is called. On systems with TZ set (and it not being a local file), this triggers a call to zoneinfo.ZoneInfo with the value of TZ. This may be an invalid value, which raises an uncaught ValueError. This error is raised again on repeated calls, as the import fails.
While the workaround is pretty easy (install pytz), the problem here is awareness:
- I don't think many people check the full env list for potential pitfalls. It may even be out of the user's control - especially on cloud services.
- I can't think of a test that catches this accidentally.
- Many of these calls are specifically wrapped to catch
ValueErrorunder the assumption that this means that the parsing failed due to the input value.
So this is a potential case of "fails only in production silently".