Skip to content

Commit 4446903

Browse files
committed
Use pathlib.Path to read unix tz
1 parent 91d0c1e commit 4446903

File tree

1 file changed

+35
-63
lines changed

1 file changed

+35
-63
lines changed

src/pendulum/tz/local_timezone.py

+35-63
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import warnings
88

99
from contextlib import contextmanager
10+
from pathlib import Path
1011
from typing import TYPE_CHECKING
1112
from typing import cast
1213

@@ -165,86 +166,57 @@ def _get_unix_timezone(_root: str = "/") -> Timezone:
165166

166167
# Now look for distribution specific configuration files
167168
# that contain the timezone name.
168-
tzpath = os.path.join(_root, "etc/timezone")
169-
if os.path.isfile(tzpath):
170-
with open(tzpath, "rb") as tzfile:
171-
tzfile_data = tzfile.read()
172-
173-
# Issue #3 was that /etc/timezone was a zoneinfo file.
174-
# That's a misconfiguration, but we need to handle it gracefully:
175-
if tzfile_data[:5] != b"TZif2":
176-
etctz = tzfile_data.strip().decode()
177-
# Get rid of host definitions and comments:
178-
if " " in etctz:
179-
etctz, dummy = etctz.split(" ", 1)
180-
if "#" in etctz:
181-
etctz, dummy = etctz.split("#", 1)
182-
183-
return Timezone(etctz.replace(" ", "_"))
169+
tzpath = Path(_root) / "etc" / "timezone"
170+
if tzpath.is_file():
171+
tzfile_data = tzpath.read_bytes()
172+
# Issue #3 was that /etc/timezone was a zoneinfo file.
173+
# That's a misconfiguration, but we need to handle it gracefully:
174+
if not tzfile_data.startswith(b"TZif2"):
175+
etctz = tzfile_data.strip().decode()
176+
# Get rid of host definitions and comments:
177+
etctz, _, _ = etctz.partition(" ")
178+
etctz, _, _ = etctz.partition("#")
179+
return Timezone(etctz.replace(" ", "_"))
184180

185181
# CentOS has a ZONE setting in /etc/sysconfig/clock,
186182
# OpenSUSE has a TIMEZONE setting in /etc/sysconfig/clock and
187183
# Gentoo has a TIMEZONE setting in /etc/conf.d/clock
188184
# We look through these files for a timezone:
189-
zone_re = re.compile(r'\s*ZONE\s*=\s*"')
190-
timezone_re = re.compile(r'\s*TIMEZONE\s*=\s*"')
191-
end_re = re.compile('"')
185+
zone_re = re.compile(r'\s*(TIME)?ZONE\s*=\s*"([^"]+)?"')
192186

193187
for filename in ("etc/sysconfig/clock", "etc/conf.d/clock"):
194-
tzpath = os.path.join(_root, filename)
195-
if not os.path.isfile(tzpath):
196-
continue
197-
198-
with open(tzpath) as tzfile:
199-
data = tzfile.readlines()
200-
201-
for line in data:
202-
# Look for the ZONE= setting.
203-
match = zone_re.match(line)
204-
if match is None:
205-
# No ZONE= setting. Look for the TIMEZONE= setting.
206-
match = timezone_re.match(line)
207-
208-
if match is not None:
209-
# Some setting existed
210-
line = line[match.end() :]
211-
etctz = line[
212-
: cast(
213-
"re.Match[str]",
214-
end_re.search(line),
215-
).start()
216-
]
217-
218-
parts = list(reversed(etctz.replace(" ", "_").split(os.path.sep)))
219-
tzpath_parts: list[str] = []
220-
while parts:
221-
tzpath_parts.insert(0, parts.pop(0))
222-
223-
with contextlib.suppress(InvalidTimezone):
224-
return Timezone(os.path.join(*tzpath_parts))
188+
tzpath = Path(_root) / filename
189+
if tzpath.is_file():
190+
data = tzpath.read_text().splitlines()
191+
for line in data:
192+
# Look for the ZONE= or TIMEZONE= setting.
193+
match = zone_re.match(line)
194+
if match:
195+
etctz = match.group(2)
196+
parts = list(reversed(etctz.replace(" ", "_").split(os.path.sep)))
197+
tzpath_parts: list[str] = []
198+
while parts:
199+
tzpath_parts.insert(0, parts.pop(0))
200+
with contextlib.suppress(InvalidTimezone):
201+
return Timezone(os.path.sep.join(tzpath_parts))
225202

226203
# systemd distributions use symlinks that include the zone name,
227204
# see manpage of localtime(5) and timedatectl(1)
228-
tzpath = os.path.join(_root, "etc", "localtime")
229-
if os.path.isfile(tzpath) and os.path.islink(tzpath):
230-
parts = list(
231-
reversed(os.path.realpath(tzpath).replace(" ", "_").split(os.path.sep))
232-
)
205+
tzpath = Path(_root) / "etc" / "localtime"
206+
if tzpath.is_file() and tzpath.is_symlink():
207+
parts = [p.replace(" ", "_") for p in reversed(tzpath.resolve().parts)]
233208
tzpath_parts: list[str] = [] # type: ignore[no-redef]
234209
while parts:
235210
tzpath_parts.insert(0, parts.pop(0))
236211
with contextlib.suppress(InvalidTimezone):
237-
return Timezone(os.path.join(*tzpath_parts))
212+
return Timezone(os.path.sep.join(tzpath_parts))
238213

239214
# No explicit setting existed. Use localtime
240215
for filename in ("etc/localtime", "usr/local/etc/localtime"):
241-
tzpath = os.path.join(_root, filename)
242-
243-
if not os.path.isfile(tzpath):
244-
continue
245-
246-
with open(tzpath, "rb") as f:
247-
return Timezone.from_file(f)
216+
tzpath = Path(_root) / filename
217+
if tzpath.is_file():
218+
with tzpath.open("rb") as f:
219+
return Timezone.from_file(f)
248220

249221
warnings.warn(
250222
"Unable not find any timezone configuration, defaulting to UTC.", stacklevel=1

0 commit comments

Comments
 (0)