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

Fix tick delta type handling #546

Merged
merged 6 commits into from
May 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 15 additions & 9 deletions freezegun/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -509,10 +509,11 @@ def __init__(self, time_to_freeze: datetime.datetime, start: datetime.datetime):
def __call__(self) -> datetime.datetime:
return self.time_to_freeze + (real_datetime.now() - self.start)

def tick(self, delta: Union[datetime.timedelta, int]=datetime.timedelta(seconds=1)) -> datetime.datetime:
if isinstance(delta, numbers.Real):
# noinspection PyTypeChecker
self.move_to(self.time_to_freeze + datetime.timedelta(seconds=delta))
def tick(self, delta: Union[datetime.timedelta, float]=datetime.timedelta(seconds=1)) -> datetime.datetime:
if isinstance(delta, numbers.Integral):
self.move_to(self.time_to_freeze + datetime.timedelta(seconds=int(delta)))
elif isinstance(delta, numbers.Real):
self.move_to(self.time_to_freeze + datetime.timedelta(seconds=float(delta)))
else:
self.move_to(self.time_to_freeze + delta) # type: ignore
return self.time_to_freeze
Expand All @@ -531,10 +532,11 @@ def __init__(self, time_to_freeze: datetime.datetime):
def __call__(self) -> datetime.datetime:
return self.time_to_freeze

def tick(self, delta: Union[datetime.timedelta, int]=datetime.timedelta(seconds=1)) -> datetime.datetime:
if isinstance(delta, numbers.Real):
# noinspection PyTypeChecker
self.time_to_freeze += datetime.timedelta(seconds=delta)
def tick(self, delta: Union[datetime.timedelta, float]=datetime.timedelta(seconds=1)) -> datetime.datetime:
if isinstance(delta, numbers.Integral):
self.move_to(self.time_to_freeze + datetime.timedelta(seconds=int(delta)))
elif isinstance(delta, numbers.Real):
self.move_to(self.time_to_freeze + datetime.timedelta(seconds=float(delta)))
else:
self.time_to_freeze += delta # type: ignore
return self.time_to_freeze
Expand All @@ -557,9 +559,13 @@ def __call__(self) -> datetime.datetime:
self.tick()
return return_time

def tick(self, delta: Union[datetime.timedelta, int, None]=None) -> datetime.datetime:
def tick(self, delta: Union[datetime.timedelta, float, None]=None) -> datetime.datetime:
if not delta:
delta = datetime.timedelta(seconds=self.step_width)
elif isinstance(delta, numbers.Integral):
delta = datetime.timedelta(seconds=int(delta))
elif isinstance(delta, numbers.Real):
delta = datetime.timedelta(seconds=float(delta))
self.time_to_freeze += delta # type: ignore
return self.time_to_freeze

Expand Down
12 changes: 12 additions & 0 deletions tests/test_datetimes.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import time
import calendar
import datetime
import fractions
import unittest
import locale
import sys
Expand Down Expand Up @@ -180,6 +181,17 @@ def test_manual_increment() -> None:
assert frozen_datetime.tick(delta=datetime.timedelta(seconds=10)) == expected
assert frozen_datetime() == expected

expected = initial_datetime + datetime.timedelta(seconds=22.5)
ticked_time = frozen_datetime.tick(
delta=fractions.Fraction(3, 2) # type: ignore
# type hints follow the recommendation of
# https://peps.python.org/pep-0484/#the-numeric-tower
# which means for instance `Fraction`s work at runtime, but not
# during static type analysis
)
assert ticked_time == expected
assert frozen_datetime() == expected


def test_move_to() -> None:
initial_datetime = datetime.datetime(year=1, month=7, day=12,
Expand Down
39 changes: 38 additions & 1 deletion tests/test_operations.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import datetime
import fractions
import pytest
from freezegun import freeze_time
from dateutil.relativedelta import relativedelta
from datetime import timedelta, tzinfo
from tests import utils
from typing import Any
from typing import Any, Union


@freeze_time("2012-01-14")
Expand Down Expand Up @@ -102,3 +104,38 @@ def test_auto_tick() -> None:
auto_incremented_time = datetime.datetime.now()
assert first_time + datetime.timedelta(seconds=15) == auto_incremented_time


@pytest.mark.parametrize(
"tick,expected_diff",
(
(datetime.timedelta(milliseconds=1500), 1.5),
(1, 1),
(1.5, 1.5),
(fractions.Fraction(3, 2), 1.5),
)
)
def test_auto_and_manual_tick(
tick: Union[
datetime.timedelta,
int,
float,
# fractions.Fraction,
# Fraction works at runtime, but not at type-checking time
# cf. https://peps.python.org/pep-0484/#the-numeric-tower
],
expected_diff: float
) -> None:
first_time = datetime.datetime(2020, 1, 14, 0, 0, 0, 1)

with freeze_time(first_time, auto_tick_seconds=2) as frozen_time:
frozen_time.tick(tick)
incremented_time = datetime.datetime.now()
expected_time = first_time + datetime.timedelta(seconds=expected_diff)
assert incremented_time == expected_time

expected_time += datetime.timedelta(seconds=2) # auto_tick_seconds

frozen_time.tick(tick)
incremented_time = datetime.datetime.now()
expected_time += datetime.timedelta(seconds=expected_diff)
assert incremented_time == expected_time
Loading