From 8548e7f7c5af72c2888b9fdb524ad713556a2166 Mon Sep 17 00:00:00 2001 From: Justin Su Date: Sun, 12 Jan 2025 07:19:28 -0500 Subject: [PATCH] Improved converters and type annotations (#1014) * Add proper type annotations to converters and fix `None` case for `as_timezone()` * Swap order of `timezone` parameter type annotation for `CronTrigger.from_crontab()` * Access enum member by name without using `__members__` --- src/apscheduler/_converters.py | 21 +++++++++------------ src/apscheduler/triggers/cron/__init__.py | 2 +- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/src/apscheduler/_converters.py b/src/apscheduler/_converters.py index 1e542f2c..fd3e3c8e 100644 --- a/src/apscheduler/_converters.py +++ b/src/apscheduler/_converters.py @@ -1,7 +1,7 @@ from __future__ import annotations from collections.abc import Callable -from datetime import date, datetime, timedelta, timezone +from datetime import date, datetime, timedelta, timezone, tzinfo from typing import Any from uuid import UUID from zoneinfo import ZoneInfo @@ -9,14 +9,14 @@ from tzlocal import get_localzone -def as_int(value: Any) -> Any: +def as_int(value: int | str) -> int: if isinstance(value, str): return int(value) return value -def as_aware_datetime(value: Any) -> Any: +def as_aware_datetime(value: datetime | str) -> datetime: if isinstance(value, str): # Before Python 3.11, fromisoformat() could not handle the "Z" suffix if value.upper().endswith("Z"): @@ -30,33 +30,30 @@ def as_aware_datetime(value: Any) -> Any: return value -def as_date(value: Any) -> Any: +def as_date(value: date | str) -> date: if isinstance(value, str): return date.fromisoformat(value) return value -def as_timezone(value: Any) -> Any: +def as_timezone(value: tzinfo | str) -> tzinfo: if isinstance(value, str): - if value is None or value == "local": - return get_localzone() - - return ZoneInfo(value) + return get_localzone() if value == "local" else ZoneInfo(value) elif value is timezone.utc: return ZoneInfo("UTC") return value -def as_uuid(value: Any) -> Any: +def as_uuid(value: UUID | str) -> UUID: if isinstance(value, str): return UUID(value) return value -def as_timedelta(value: Any) -> Any: +def as_timedelta(value: timedelta | int) -> timedelta: if isinstance(value, (float, int)): return timedelta(seconds=value) @@ -66,7 +63,7 @@ def as_timedelta(value: Any) -> Any: def as_enum(enum_class: Any) -> Callable[[Any], Any]: def converter(value: Any) -> Any: if isinstance(value, str): - return enum_class.__members__[value] + return enum_class[value] return value diff --git a/src/apscheduler/triggers/cron/__init__.py b/src/apscheduler/triggers/cron/__init__.py index 6abef7b5..b0f17235 100644 --- a/src/apscheduler/triggers/cron/__init__.py +++ b/src/apscheduler/triggers/cron/__init__.py @@ -118,7 +118,7 @@ def from_crontab( *, start_time: datetime | None = None, end_time: datetime | None = None, - timezone: str | tzinfo = "local", + timezone: tzinfo | str = "local", ) -> CronTrigger: """ Create a :class:`~CronTrigger` from a standard crontab expression.