Skip to content

Commit

Permalink
Merge pull request #636 from aiven/aiven-anton/fix/add-stubs-for-isodate
Browse files Browse the repository at this point in the history
chore: Add partial stubs for the isodate library
  • Loading branch information
tvainika authored Jun 2, 2023
2 parents 82ab84a + 5c53eaa commit 7e024f1
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 9 deletions.
14 changes: 10 additions & 4 deletions karapace/backup/poll_timeout.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@
from datetime import timedelta
from functools import cached_property
from isodate import duration_isoformat, parse_duration
from typing import Final

__all__ = ["PollTimeout"]
__all__ = ("PollTimeout",)


class PollTimeout:
Expand All @@ -19,9 +20,14 @@ class PollTimeout:
"""

def __init__(self, value: str | timedelta) -> None:
self.__value = value if isinstance(value, timedelta) else parse_duration(value)
if self.__value // timedelta(seconds=1) < 1:
raise ValueError(f"Poll timeout MUST be at least one second, got: {self}")
duration = value if isinstance(value, timedelta) else parse_duration(value)
# parse_duration() returns Duration objects for values that cannot be
# represented by a datetime.timedelta.
if not isinstance(duration, timedelta):
raise ValueError(f"Poll timeout must be less than one year, got: {duration}")
if isinstance(duration, timedelta) and duration < timedelta(seconds=1):
raise ValueError(f"Poll timeout must be at least one second, got: {duration}")
self.__value: Final = duration

@classmethod
def default(cls) -> PollTimeout:
Expand Down
4 changes: 1 addition & 3 deletions mypy.ini
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
[mypy]
mypy_path = $MYPY_CONFIG_FILE_DIR/stubs
python_version = 3.8
packages = karapace
show_error_codes = True
Expand Down Expand Up @@ -115,8 +116,5 @@ ignore_errors = True
[mypy-kafka.*]
ignore_missing_imports = True

[mypy-isodate.*]
ignore_missing_imports = True

[mypy-networkx.*]
ignore_missing_imports = True
3 changes: 3 additions & 0 deletions stubs/isodate/__init__.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from isodate.isoduration import duration_isoformat, parse_duration

__all__ = ("duration_isoformat", "parse_duration")
21 changes: 21 additions & 0 deletions stubs/isodate/duration.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from decimal import Decimal

import datetime

class Duration:
months: Decimal
years: Decimal
tdelta: datetime.timedelta

def __init__(
self,
days: int = ...,
seconds: int = ...,
microseconds: int = ...,
milliseconds: int = ...,
minutes: int = ...,
hours: int = ...,
weeks: int = ...,
months: int = ...,
years: int = ...,
) -> None: ...
18 changes: 18 additions & 0 deletions stubs/isodate/isoduration.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from .duration import Duration
from typing import Literal, overload

import datetime

@overload
def parse_duration(
datestring: str,
) -> datetime.timedelta | Duration: ...
@overload
def parse_duration(
datestring: str,
as_timedelta_if_possible: Literal[False],
) -> Duration: ...
def duration_isoformat(
tduration: Duration | datetime.timedelta,
format: str = ...,
) -> str: ...
Empty file added stubs/isodate/py.typed
Empty file.
13 changes: 11 additions & 2 deletions tests/unit/backup/test_poll_timeout.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,18 @@
class TestPollTimeout:
@pytest.mark.parametrize("it", ("PT0.999S", timedelta(milliseconds=999)))
def test_min_validation(self, it: Union[str, timedelta]) -> None:
with pytest.raises(ValueError) as e:
with pytest.raises(
ValueError,
match=r"^Poll timeout must be at least one second, got: 0:00:00.999000$",
):
PollTimeout(it)
assert str(e.value) == "Poll timeout MUST be at least one second, got: PT0.999S"

def test_max_validation(self) -> None:
with pytest.raises(
ValueError,
match=r"^Poll timeout must be less than one year, got: 1 years, 0:00:00$",
):
PollTimeout("P1Y")

# Changing the default is not a breaking change, but the documentation needs to be adjusted!
def test_default(self) -> None:
Expand Down

0 comments on commit 7e024f1

Please sign in to comment.