Open torfsen opened 1 year ago
Using babel version v2.11.0 with Python 3.9 does not give the error, so this becomes an issue in the latest versions.
I just encountered this with Babel 2.12.1
running with Python 3.9 inside an Ubuntu 22.04 (Jammy) container. The problem is definitely the double slash in the /etc/localtime
link. I don't know why the Ubuntu installer creates an irregular link like that, but it is indeed valid.
It looks like the problem is in localtime/_unix.py. The os.readlink()
function is used to get the target of /etc/localtime
. This does not normalize the path, so the time zone ID is being parsed incorrectly as /UTC
instead of UTC
.
def _get_localzone(_root: str = '/') -> datetime.tzinfo:
"""Tries to find the local timezone configuration.
This method prefers finding the timezone name and passing that to
zoneinfo or pytz, over passing in the localtime file, as in the later
case the zoneinfo name is unknown.
The parameter _root makes the function look for files like /etc/localtime
beneath the _root directory. This is primarily used by the tests.
In normal usage you call the function without parameters.
"""
# <snip>
# This is actually a pretty reliable way to test for the local time
# zone on operating systems like OS X. On OS X especially this is the
# only one that actually works.
try:
link_dst = os.readlink('/etc/localtime')
except OSError:
pass
# <snip>
I think the solution to this is to replace os.readlink()
with pathlib.Path().resolve()
, which will normalize the path and remove the double slashes. I created a fork, but coming up with a test for this is tricky.
Confirmed this is also a problem with Python 3.10 on Ubuntu.
I submitted https://github.com/python-babel/babel/pull/1006 for this back in June. The PR could not be automatically merged because some unrelated broken tests were failing. It looks like it was manually merged by a maintainer, but I'm not sure what the current status is.
The broken unit tests have been fixed upstream. I rebased my fixes onto master
and submitted https://github.com/python-babel/babel/pull/1035. This should pass all automated checks, which will hopefully streamline the merge process and speed up the resolution of this issue.
For anybody that needs a temporary workaround, I was able to fix this in an Ubuntu Docker image by recreating the /etc/localtime
link to remove the double slashes:
rm -f /etc/localtime
ln -s /usr/share/zoneinfo/Etc/UTC /etc/localtime
I'm having this issue with Ubuntu 22.04, python 3.10 and babel 2.13.
Traceback (most recent call last):
File "/usr/local/bin/sphinx-build", line 5, in <module>
from sphinx.cmd.build import main
File "/usr/local/lib/python3.10/dist-packages/sphinx/cmd/build.py", line 25, in <module>
from sphinx.application import Sphinx
File "/usr/local/lib/python3.10/dist-packages/sphinx/application.py", line 32, in <module>
from sphinx.config import Config
File "/usr/local/lib/python3.10/dist-packages/sphinx/config.py", line 22, in <module>
from sphinx.util.i18n import format_date
File "/usr/local/lib/python3.10/dist-packages/sphinx/util/i18n.py", line 17, in <module>
import babel.dates
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 49, in _get_localzone
tzinfo = _get_tzinfo(zone_name)
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
The strange thing is that my /etc/localtime does not have any slash... but it is quite strange anyway:
$ cat /etc/localtime
TZif2UTCTZif2UTC
UTC0
Don't know how to fix it.
[EDIT] Sorry! Now I noticed that the double slash is on the filepath itself...
$ ls -la /etc/localtime
/etc/localtime -> /usr/share/zoneinfo//UTC
So this solution indeed fixed my error:
$ rm -f /etc/localtime
$ ln -s /usr/share/zoneinfo/UTC /etc/localtime
Overview Description
Importing
babel.localtime
crashes on Python 3.9 if/etc/localtime
contains double-slashes.Steps to Reproduce
Note the double-slash,
//UTC
.Actual Results
Crash.
Expected Results
No crash.
Reproducibility
Crashes for me on Python 3.9 with
babel
2.12.1
. Works on Python 3.8.The problem is that
babel.localtime._unix._get_localzone
has naive path handling.Additional Information
I'm not sure whether
babel
is to blame here, but since this is working on Python 3.8 it would be nice to makebabel
more robust here. As far as I can tell, double slashes are valid in POSIX and should be treated as single slashes.