]> git.ipfire.org Git - thirdparty/babel.git/commitdiff
Strip extra leading slashes in `/etc/localtime` (#1165)
authorAarni Koskela <akx@iki.fi>
Fri, 10 Jan 2025 06:17:02 +0000 (08:17 +0200)
committerGitHub <noreply@github.com>
Fri, 10 Jan 2025 06:17:02 +0000 (08:17 +0200)
* Strip extra leading slashes in `/etc/localtime`

Fixes #990

Co-authored-by: Tomas R. <tomas.roun8@gmail.com>
babel/localtime/_unix.py
tests/test_localtime.py

index eb81beb618b3d4a8894468b48a4f423652f3422c..782a7d246ce2ca8cf2bb70857f670e11aeeacee0 100644 (file)
@@ -45,7 +45,13 @@ def _get_localzone(_root: str = '/') -> datetime.tzinfo:
     else:
         pos = link_dst.find('/zoneinfo/')
         if pos >= 0:
-            zone_name = link_dst[pos + 10:]
+            # On occasion, the `/etc/localtime` symlink has a double slash, e.g.
+            # "/usr/share/zoneinfo//UTC", which would make `zoneinfo.ZoneInfo`
+            # complain (no absolute paths allowed), and we'd end up returning
+            # `None` (as a fix for #1092).
+            # Instead, let's just "fix" the double slash symlink by stripping
+            # leading slashes before passing the assumed zone name forward.
+            zone_name = link_dst[pos + 10:].lstrip("/")
             tzinfo = _get_tzinfo(zone_name)
             if tzinfo is not None:
                 return tzinfo
index 723ffa0b075f265df48b9c3be815b9d218e2b127..a7eaba8f76ed0e39ec38696690c59fb92d928464 100644 (file)
@@ -1,4 +1,6 @@
+import os
 import sys
+from unittest.mock import Mock
 
 import pytest
 
@@ -27,3 +29,16 @@ def test_issue_1092_with_pytz(monkeypatch):
     monkeypatch.setenv("TZ", "/UTC")  # Malformed timezone name.
     with pytest.raises(LookupError):
         get_localzone()
+
+
+@pytest.mark.skipif(
+    sys.platform == "win32",
+    reason="Issue 990 is not applicable on Windows",
+)
+def test_issue_990(monkeypatch):
+    monkeypatch.setenv("TZ", "")
+    fake_readlink = Mock(return_value="/usr/share/zoneinfo////UTC")  # Double slash, oops!
+    monkeypatch.setattr(os, "readlink", fake_readlink)
+    from babel.localtime._unix import _get_localzone
+    assert _get_localzone() is not None
+    fake_readlink.assert_called_with("/etc/localtime")