Skip to content

Commit 4a89c1b

Browse files
authored
Update croniter to 6.0.0 (#13548)
Make class `croniter` generic over `ret_type` and tighten return types for some methods.
1 parent c7b8fe9 commit 4a89c1b

File tree

3 files changed

+170
-47
lines changed

3 files changed

+170
-47
lines changed

stubs/croniter/METADATA.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
version = "5.0.1"
1+
version = "6.0.0"
22
upstream_repository = "https://github.com/pallets-eco/croniter"

stubs/croniter/croniter/__init__.pyi

+11
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,22 @@
1+
from . import croniter as croniter_m
12
from .croniter import (
3+
DAY_FIELD as DAY_FIELD,
4+
HOUR_FIELD as HOUR_FIELD,
5+
MINUTE_FIELD as MINUTE_FIELD,
6+
MONTH_FIELD as MONTH_FIELD,
27
OVERFLOW32B_MODE as OVERFLOW32B_MODE,
8+
SECOND_FIELD as SECOND_FIELD,
9+
UTC_DT as UTC_DT,
10+
YEAR_FIELD as YEAR_FIELD,
311
CroniterBadCronError as CroniterBadCronError,
412
CroniterBadDateError as CroniterBadDateError,
513
CroniterBadTypeRangeError as CroniterBadTypeRangeError,
14+
CroniterError as CroniterError,
615
CroniterNotAlphaError as CroniterNotAlphaError,
716
CroniterUnsupportedSyntaxError as CroniterUnsupportedSyntaxError,
817
croniter as croniter,
918
croniter_range as croniter_range,
1019
datetime_to_timestamp as datetime_to_timestamp,
1120
)
21+
22+
cron_m = croniter_m

stubs/croniter/croniter/croniter.pyi

+158-46
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,46 @@
11
import datetime
22
from _typeshed import Unused
33
from collections import OrderedDict
4-
from collections.abc import Iterator
4+
from collections.abc import Generator
55
from re import Match, Pattern
6-
from typing import Any, Final, Literal, overload
6+
from typing import Any, Final, Generic, Literal, Protocol, TypeVar, overload
77
from typing_extensions import Never, Self, TypeAlias
88

9-
_RetType: TypeAlias = type[float | datetime.datetime]
9+
_R_co = TypeVar("_R_co", float, datetime.datetime, default=float, covariant=True)
10+
_R2_co = TypeVar("_R2_co", float, datetime.datetime, covariant=True)
1011
_Expressions: TypeAlias = list[str] # fixed-length list of 5 or 6 strings
1112

13+
class _AllIter(Protocol[_R_co]):
14+
@overload
15+
def __call__(
16+
self, ret_type: type[_R2_co], start_time: float | datetime.datetime | None = None, update_current: bool | None = None
17+
) -> Generator[_R2_co]: ...
18+
@overload
19+
def __call__(
20+
self, ret_type: None = None, start_time: float | datetime.datetime | None = None, update_current: bool | None = None
21+
) -> Generator[_R_co]: ...
22+
1223
def is_32bit() -> bool: ...
1324

1425
OVERFLOW32B_MODE: Final[bool]
1526

27+
UTC_DT: Final[datetime.timezone]
1628
EPOCH: Final[datetime.datetime]
1729
M_ALPHAS: Final[dict[str, int]]
1830
DOW_ALPHAS: Final[dict[str, int]]
19-
ALPHAS: Final[dict[str, int]]
31+
32+
MINUTE_FIELD: Final = 0
33+
HOUR_FIELD: Final = 1
34+
DAY_FIELD: Final = 2
35+
MONTH_FIELD: Final = 3
36+
DOW_FIELD: Final = 4
37+
SECOND_FIELD: Final = 5
38+
YEAR_FIELD: Final = 6
39+
40+
UNIX_FIELDS: Final[tuple[int, int, int, int, int]]
41+
SECOND_FIELDS: Final[tuple[int, int, int, int, int, int]]
42+
YEAR_FIELDS: Final[tuple[int, int, int, int, int, int, int]]
43+
2044
step_search_re: Final[Pattern[str]]
2145
only_int_re: Final[Pattern[str]]
2246

@@ -26,26 +50,18 @@ star_or_int_re: Final[Pattern[str]]
2650
special_dow_re: Final[Pattern[str]]
2751
re_star: Final[Pattern[str]]
2852
hash_expression_re: Final[Pattern[str]]
29-
MINUTE_FIELD: Final = 0
30-
HOUR_FIELD: Final = 1
31-
DAY_FIELD: Final = 2
32-
MONTH_FIELD: Final = 3
33-
DOW_FIELD: Final = 4
34-
SECOND_FIELD: Final = 5
53+
54+
CRON_FIELDS: Final[dict[str | int, tuple[int, ...]]]
3555
UNIX_CRON_LEN: Final = 5
36-
YEAR_FIELD: Final = 6
3756
SECOND_CRON_LEN: Final = 6
3857
YEAR_CRON_LEN: Final = 7
39-
SECOND_FIELDS: Final[tuple[int, int, int, int, int, int]]
40-
UNIX_FIELDS: Final[tuple[int, int, int, int, int]]
41-
YEAR_FIELDS: Final[tuple[int, int, int, int, int, int, int]]
42-
CRON_FIELDS: Final[dict[str | int, tuple[int, ...]]]
4358
VALID_LEN_EXPRESSION: Final[set[int]]
59+
TIMESTAMP_TO_DT_CACHE: Final[dict[tuple[float, str], datetime.datetime]]
4460
EXPRESSIONS: dict[tuple[str, bytes], _Expressions]
45-
46-
UTC_DT: Final[datetime.timezone]
61+
MARKER: object
4762

4863
def timedelta_to_seconds(td: datetime.timedelta) -> float: ...
64+
def datetime_to_timestamp(d: datetime.datetime) -> float: ...
4965

5066
class CroniterError(ValueError): ...
5167
class CroniterBadTypeRangeError(TypeError): ...
@@ -54,9 +70,7 @@ class CroniterUnsupportedSyntaxError(CroniterBadCronError): ...
5470
class CroniterBadDateError(CroniterError): ...
5571
class CroniterNotAlphaError(CroniterError): ...
5672

57-
def datetime_to_timestamp(d: datetime.datetime) -> float: ...
58-
59-
class croniter(Iterator[Any]):
73+
class croniter(Generic[_R_co]):
6074
MONTHS_IN_YEAR: Final = 12
6175
RANGES: Final[
6276
tuple[
@@ -102,8 +116,8 @@ class croniter(Iterator[Any]):
102116
]
103117
]
104118
LEN_MEANS_ALL: Final[tuple[int, int, int, int, int, int, int]]
105-
bad_length: Final[str]
106119

120+
second_at_beginning: bool
107121
tzinfo: datetime.tzinfo | None
108122

109123
# Initialized to None, but immediately set to a float.
@@ -113,13 +127,56 @@ class croniter(Iterator[Any]):
113127

114128
expanded: list[list[str]]
115129
nth_weekday_of_month: dict[str, set[int]]
130+
fields: tuple[int, ...]
116131
expressions: _Expressions
117132

133+
@overload
134+
def __new__(
135+
cls,
136+
expr_format: str,
137+
start_time: float | datetime.datetime | None = None,
138+
ret_type: type[float] = ...,
139+
day_or: bool = True,
140+
max_years_between_matches: int | None = None,
141+
is_prev: bool = False,
142+
hash_id: str | bytes | None = None,
143+
implement_cron_bug: bool = False,
144+
second_at_beginning: bool | None = None,
145+
expand_from_start_time: bool = False,
146+
) -> croniter[float]: ...
147+
@overload
148+
def __new__(
149+
cls,
150+
expr_format: str,
151+
start_time: float | datetime.datetime | None,
152+
ret_type: type[datetime.datetime],
153+
day_or: bool = True,
154+
max_years_between_matches: int | None = None,
155+
is_prev: bool = False,
156+
hash_id: str | bytes | None = None,
157+
implement_cron_bug: bool = False,
158+
second_at_beginning: bool | None = None,
159+
expand_from_start_time: bool = False,
160+
) -> croniter[datetime.datetime]: ...
161+
@overload
162+
def __new__(
163+
cls,
164+
expr_format: str,
165+
*,
166+
ret_type: type[datetime.datetime],
167+
day_or: bool = True,
168+
max_years_between_matches: int | None = None,
169+
is_prev: bool = False,
170+
hash_id: str | bytes | None = None,
171+
implement_cron_bug: bool = False,
172+
second_at_beginning: bool | None = None,
173+
expand_from_start_time: bool = False,
174+
) -> croniter[datetime.datetime]: ...
118175
def __init__(
119176
self,
120177
expr_format: str,
121178
start_time: float | datetime.datetime | None = None,
122-
ret_type: _RetType | None = ...,
179+
ret_type: type[_R_co] = ...,
123180
day_or: bool = True,
124181
max_years_between_matches: int | None = None,
125182
is_prev: bool = False,
@@ -128,44 +185,74 @@ class croniter(Iterator[Any]):
128185
second_at_beginning: bool | None = None,
129186
expand_from_start_time: bool = False,
130187
) -> None: ...
131-
# Most return value depend on ret_type, which can be passed in both as a method argument and as
132-
# a constructor argument.
188+
@overload
189+
def get_next(
190+
self, ret_type: type[_R2_co], start_time: float | datetime.datetime | None = None, update_current: bool = True
191+
) -> _R_co: ...
192+
@overload
133193
def get_next(
134-
self, ret_type: _RetType | None = None, start_time: float | datetime.datetime | None = None, update_current: bool = True
135-
) -> Any: ...
194+
self, ret_type: None = None, start_time: float | datetime.datetime | None = None, update_current: bool = True
195+
) -> _R_co: ...
196+
@overload
197+
def get_prev(
198+
self, ret_type: type[_R2_co], start_time: float | datetime.datetime | None = None, update_current: bool = True
199+
) -> _R2_co: ...
200+
@overload
136201
def get_prev(
137-
self, ret_type: _RetType | None = None, start_time: float | datetime.datetime | None = None, update_current: bool = True
138-
) -> Any: ...
139-
def get_current(self, ret_type: _RetType | None = None) -> Any: ...
202+
self, ret_type: None = None, start_time: float | datetime.datetime | None = None, update_current: bool = True
203+
) -> _R_co: ...
204+
@overload
205+
def get_current(self, ret_type: type[_R2_co]) -> _R2_co: ...
206+
@overload
207+
def get_current(self, ret_type: None = None) -> _R_co: ...
140208
def set_current(self, start_time: float | datetime.datetime | None, force: bool = True) -> float: ...
209+
@staticmethod
210+
def datetime_to_timestamp(d: datetime.datetime) -> float: ...
211+
def timestamp_to_datetime(self, timestamp: float, tzinfo: datetime.tzinfo | None = ...) -> datetime.datetime: ...
212+
@staticmethod
213+
def timedelta_to_seconds(td: datetime.timedelta) -> float: ...
214+
@overload
215+
def all_next(
216+
self, ret_type: type[_R2_co], start_time: float | datetime.datetime | None = None, update_current: bool | None = None
217+
) -> Generator[_R2_co]: ...
218+
@overload
219+
def all_next(
220+
self, ret_type: None = None, start_time: float | datetime.datetime | None = None, update_current: bool | None = None
221+
) -> Generator[_R_co]: ...
222+
@overload
223+
def all_prev(
224+
self, ret_type: type[_R2_co], start_time: float | datetime.datetime | None = None, update_current: bool | None = None
225+
) -> Generator[_R2_co]: ...
226+
@overload
227+
def all_prev(
228+
self, ret_type: None = None, start_time: float | datetime.datetime | None = None, update_current: bool | None = None
229+
) -> Generator[_R_co]: ...
230+
def iter(self, *args: Unused, **kwargs: Unused) -> _AllIter[_R_co]: ...
141231
def __iter__(self) -> Self: ...
232+
@overload
142233
def next(
143234
self,
144-
ret_type: _RetType | None = None,
235+
ret_type: type[_R2_co],
145236
start_time: float | datetime.datetime | None = None,
146237
is_prev: bool | None = None,
147238
update_current: bool | None = None,
148-
) -> Any: ...
149-
__next__ = next
150-
def all_next(
151-
self,
152-
ret_type: _RetType | None = None,
153-
start_time: float | datetime.datetime | None = None,
154-
update_current: bool | None = None,
155-
) -> Iterator[Any]: ...
156-
def all_prev(
239+
) -> _R2_co: ...
240+
@overload
241+
def next(
157242
self,
158-
ret_type: _RetType | None = None,
243+
ret_type: None = None,
159244
start_time: float | datetime.datetime | None = None,
245+
is_prev: bool | None = None,
160246
update_current: bool | None = None,
161-
) -> Iterator[Any]: ...
162-
def iter(self, ret_type: _RetType | None = ...) -> Iterator[Any]: ...
163-
def is_leap(self, year: int) -> bool: ...
247+
) -> _R_co: ...
248+
__next__ = next
249+
@staticmethod
250+
def is_leap(year: int) -> bool: ...
164251
@classmethod
165252
def value_alias(
166253
cls,
167254
val: int,
168-
field: Literal[0, 1, 2, 3, 4, 5, 6],
255+
field_index: Literal[0, 1, 2, 3, 4, 5, 6],
169256
len_expressions: int | list[Any] | dict[Any, Any] | tuple[Any, ...] | set[Any] = 5,
170257
) -> int: ...
171258
@classmethod
@@ -198,17 +285,42 @@ class croniter(Iterator[Any]):
198285
second_at_beginning: bool = False,
199286
) -> bool: ...
200287

288+
@overload
201289
def croniter_range(
202290
start: float | datetime.datetime,
203291
stop: float | datetime.datetime,
204292
expr_format: str,
205-
ret_type: _RetType | None = None,
293+
ret_type: type[_R2_co],
294+
day_or: bool = True,
295+
exclude_ends: bool = False,
296+
_croniter: type[croniter] | None = None,
297+
second_at_beginning: bool = False,
298+
expand_from_start_time: bool = False,
299+
) -> Generator[_R2_co, None, None]: ...
300+
@overload
301+
def croniter_range(
302+
start: float,
303+
stop: float | datetime.datetime,
304+
expr_format: str,
305+
ret_type: None = None,
306+
day_or: bool = True,
307+
exclude_ends: bool = False,
308+
_croniter: type[croniter] | None = None,
309+
second_at_beginning: bool = False,
310+
expand_from_start_time: bool = False,
311+
) -> Generator[float, None, None]: ...
312+
@overload
313+
def croniter_range(
314+
start: datetime.datetime,
315+
stop: float | datetime.datetime,
316+
expr_format: str,
317+
ret_type: None = None,
206318
day_or: bool = True,
207319
exclude_ends: bool = False,
208320
_croniter: type[croniter] | None = None,
209321
second_at_beginning: bool = False,
210322
expand_from_start_time: bool = False,
211-
) -> Iterator[Any]: ...
323+
) -> Generator[datetime.datetime, None, None]: ...
212324

213325
class HashExpander:
214326
cron: croniter

0 commit comments

Comments
 (0)