Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace dateutil.tz with ZoneInfo and tzlocal for better cross-platform compatibility. #40

Merged
merged 10 commits into from
Apr 22, 2024
4 changes: 3 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ description = "Logging/encoding/decoding using CLP's IR stream format"
readme = "README.md"
requires-python = ">=3.7"
dependencies = [
"backports.zoneinfo >= 0.2.1; python_version < '3.9'",
"clp-ffi-py >= 0.0.11",
"python-dateutil >= 2.7.0",
"typing-extensions >= 3.7.4",
"tzlocal == 5.1; python_version < '3.8'",
"tzlocal >= 5.2; python_version >= '3.8'",
"zstandard >= 0.18.0",
]
classifiers = [
Expand Down
12 changes: 5 additions & 7 deletions src/clp_logging/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import sys
import time
from abc import ABCMeta, abstractmethod
from datetime import tzinfo
from math import floor
from pathlib import Path
from queue import Empty, Queue
Expand All @@ -13,7 +12,7 @@
from types import FrameType
from typing import Callable, ClassVar, Dict, IO, Optional, Tuple, Union

import dateutil.tz
import tzlocal
from clp_ffi_py.ir import FourByteEncoder
from zstandard import FLUSH_FRAME, ZstdCompressionWriter, ZstdCompressor

Expand Down Expand Up @@ -59,12 +58,11 @@ def _init_timeinfo(fmt: Optional[str], tz: Optional[str]) -> Tuple[str, str]:
if not fmt:
fmt = "yyyy-MM-d H:m:s.A"
if not tz:
tzf: Optional[tzinfo] = dateutil.tz.gettz()
if tzf:
tzp: Path = Path.resolve(Path(tzf._filename)) # type: ignore
tz = "/".join([tzp.parent.name, tzp.name])
else:
try:
tz = tzlocal.get_localzone_name()
except Exception:
tz = "UTC"

return fmt, tz


Expand Down
16 changes: 11 additions & 5 deletions src/clp_logging/readers.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
from abc import ABCMeta, abstractmethod
from datetime import datetime, tzinfo
from datetime import datetime
from pathlib import Path
from sys import stderr
from types import TracebackType
from typing import IO, Iterator, List, Match, Optional, Tuple, Type, Union

import dateutil.tz
from clp_ffi_py.ir import FourByteEncoder
from zstandard import ZstdDecompressionReader, ZstdDecompressor

Expand All @@ -31,6 +30,13 @@
VAR_COMPACT_ENCODING,
)

try:
from zoneinfo import ZoneInfo # type: ignore[import-not-found, unused-ignore]
except ImportError:
from backports.zoneinfo import ( # type: ignore[import-not-found, no-redef, unused-ignore]
ZoneInfo,
)


class Log:
"""
Expand Down Expand Up @@ -61,7 +67,7 @@ def __init__(self) -> None:
def __str__(self) -> str:
return self.formatted_msg

def _decode(self, timestamp_format: Optional[str], timezone: Optional[tzinfo]) -> int:
def _decode(self, timestamp_format: Optional[str], timezone: Optional[ZoneInfo]) -> int:
"""
Populate the `variables`, `msg`, and `formatted_msg` fields by decoding
the encoded `encoded_logtype and `encoded_variables`.
Expand Down Expand Up @@ -148,7 +154,7 @@ def __init__(self, timestamp_format: Optional[str], chunk_size: int) -> None:
self.metadata: Optional[Metadata] = None
self.last_timestamp_ms: int
self.timestamp_format: Optional[str] = timestamp_format
self.timezone: Optional[tzinfo]
self.timezone: Optional[ZoneInfo]
self.pos: int

def read_preamble(self) -> int:
Expand Down Expand Up @@ -186,7 +192,7 @@ def read_preamble(self) -> int:
# We do not use the timestamp pattern from the preamble as it may
# be from other languages and therefore incompatible.
# self.timestamp_format = self.metadata[METADATA_TIMESTAMP_PATTERN_KEY]
self.timezone = dateutil.tz.gettz(self.metadata[METADATA_TZ_ID_KEY])
self.timezone = ZoneInfo(self.metadata[METADATA_TZ_ID_KEY])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The class ZoneInfo is an implementation of tzinfo abstracted class, shall we narrow down the type of self.timezone to ZoneInfo instead?
This means we should also update the type annotation in Log._decode

return self.pos

@abstractmethod
Expand Down
Loading