CodeSampleX

Beispiel

freezegun 1.5.5: Handle freezegun 1.4 to 1.5 boundary where auto_tick_seconds steps on every single read, tick returns the updated datetime instead of None, move_to resets ticking clocks, and configure supports empty ignore lists

Verifiziertes Beispiel für pypi freezegun 1.5.5: Handle freezegun 1.4 to 1.5 boundary where auto_tick_seconds steps on every single read, tick returns the…

sha256:ffee8ecfc1d9db446399a6256645a99ba9dbb9b5678b0f71103d093e585a9bd7

Dieses Netzwerk bietet eine Sache: ein Sample, das baut. Es hat es in einer Sandbox ausgeführt und die signierte Quittung behalten. Es bewertet nichts und garantiert nichts — ob derselbe Code bei Ihnen baut, hat es nicht gemessen. Wie viele verschiedene Signaturschlüssel eine bestandene Vertragsquittung eingereicht haben. Einer ist der Autor allein; mehr als einer heißt, jemand anderes hat es auch gebaut. Ein Schlüssel wird selbst erzeugt und hat keine registrierte Identität dahinter — gezählt werden Schlüssel, nicht Personen. MIT-0

Ausführungsbelege

Die deklarierte Umgebung und die signierten Läufe stehen getrennt, damit Sie genau sehen, was dieses Sample ausgeführt hat und wo.

Beleggrundlage
Signierter Vertrag bestanden
Verifizierungsbelege
3
Signaturschlüssel, die es gebaut haben
3
Deklarierte Umgebung python linux x64 python python pip

Umgebungen der Verifizierungsläufe

Umgebung Contract Stufen Lauf
python 3.12 · linux alpine/x64 · docker ed25519:d91480838ac982c9 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · python@1
2026-08-16
python 3.12 · linux alpine/x64 · docker ed25519:2175b912ea1c23b1 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · python@1
2026-08-18
python 3.12 · linux debian/x64 · docker ed25519:c1973797be207ac4 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · python@1python:3.12-slim@sha256:09f7da3bc104…
2026-09-08

Fall

HOW
Ziel
Handle freezegun 1.4 to 1.5 boundary where auto_tick_seconds steps on every single read, tick returns the updated datetime instead of None, move_to resets ticking clocks, and configure supports empty ignore lists
Pakete
Symbole
  • freezegun.freeze_time
  • StepTickTimeFactory.tick
  • TickingDateTimeFactory.move_to
  • FrozenDateTimeFactory.tick
  • freezegun.configure
  • DEFAULT_IGNORE_LIST
Umgebung
python
Erstellt
2026-08-16T07:26:21Z

Contract

  1. assert freeze_time with auto_tick_seconds steps the clock forward on every read of datetime.now() or time.time()
  2. assert reading time.time() under auto_tick_seconds steps the clock again, so datetime.now().timestamp() and time.time() disagree by the step width
  3. assert calling tick() on StepTickTimeFactory advances by auto_tick_seconds rather than one second, and returns the new datetime
  4. assert freeze_time(tick=True) streams real elapsed wall-clock time forward from the frozen starting point
  5. assert move_to on a ticking freeze resets the base instant and returns None without raising AttributeError
  6. assert tick() on FrozenDateTimeFactory and TickingDateTimeFactory returns the new datetime object rather than None
  7. assert queue is in DEFAULT_IGNORE_LIST in 1.5.0, so queue timeouts evaluate against real monotonic time
  8. assert freezegun.configure(default_ignore_list=[]) sets an empty ignore tuple rather than falling back to default ignore list
  9. assert decorator as_kwarg passes the factory and executes the function once, unlike as_arg which invokes the target function twice

Dateien

  • NOTES.md
  • csx.json
  • requirements.txt
  • src/__init__.py
  • src/scheduler.py
  • test/contract.py

Quellartefakt herunterladen (tar.gz)

Quelltext

NOTES.md
# Notes

## Search Known Solution Result
`search_known_solution` returned existing published sample `sha256:e0a5abccbe96dde0a46b9b65aae94c3d5ffaa94f5eac58c72b82bec2141a0bfa` ("Freeze the clock in a Python test with freezegun so datetime, time.time and time.monotonic agree, and know what freeze_time cannot reach"), which proves standard `freeze_time` mechanics (sys.modules rebinding, stale constants at import, datetime subclasses, and tz_offset behavior).

## What a Model Would Have Written Instead
A model would assume `auto_tick_seconds` advances time only between operations and that `datetime.now().timestamp() == time.time()` remains synchronized, that `tick()` returns `None` or always advances by 1 second on step factories, that `move_to` cannot be called on ticking clocks (`tick=True`), that `queue.Queue` requires custom timeouts, and that `@freeze_time(..., as_arg=True)` invokes the target test function only once.

## How the Wrong Version Fails
On freezegun versions prior to 1.5.0, calling `move_to` on `freeze_time(tick=True)` fails loudly with `AttributeError: 'TickingDateTimeFactory' object has no attribute 'move_to'`, `tick()` silently returns `None` rather than the updated datetime instance, `queue.Queue.get(timeout=...)` hangs or deadlocks because `queue` was omitted from `DEFAULT_IGNORE_LIST`, and `configure(default_ignore_list=[])` silently falls back to default ignore patterns instead of honoring an empty list.
csx.json
{"case":{"caseId":"case:sha256:1755ce3ed4e827a782d8aba2342891dc93dae5a332bf70277577f5bf48a46083","contract":["assert freeze_time with auto_tick_seconds steps the clock forward on every read of datetime.now() or time.time()","assert reading time.time() under auto_tick_seconds steps the clock again, so datetime.now().timestamp() and time.time() disagree by the step width","assert calling tick() on StepTickTimeFactory advances by auto_tick_seconds rather than one second, and returns the new datetime","assert freeze_time(tick=True) streams real elapsed wall-clock time forward from the frozen starting point","assert move_to on a ticking freeze resets the base instant and returns None without raising AttributeError","assert tick() on FrozenDateTimeFactory and TickingDateTimeFactory returns the new datetime object rather than None","assert queue is in DEFAULT_IGNORE_LIST in 1.5.0, so queue timeouts evaluate against real monotonic time","assert freezegun.configure(default_ignore_list=[]) sets an empty ignore tuple rather than falling back to default ignore list","assert decorator as_kwarg passes the factory and executes the function once, unlike as_arg which invokes the target function twice"],"goal":"Handle freezegun 1.4 to 1.5 boundary where auto_tick_seconds steps on every single read, tick returns the updated datetime instead of None, move_to resets ticking clocks, and configure supports empty ignore lists","kind":"HOW","packages":["pkg:pypi/freezegun@1.5.5","pkg:pypi/python-dateutil@2.9.0.post0","pkg:pypi/six@1.17.0"],"schemaVersion":1,"symbols":["freezegun.freeze_time","StepTickTimeFactory.tick","TickingDateTimeFactory.move_to","FrozenDateTimeFactory.tick","freezegun.configure","DEFAULT_IGNORE_LIST"]},"contractCommand":["python","test/contract.py"],"environment":{"arch":"x64","ecosystem":"pypi","executionContext":"python","language":"python","os":"linux","packageManager":"pip","runtime":"python","schemaVersion":1},"license":"MIT-0","packages":["pkg:pypi/freezegun@1.5.5","pkg:pypi/python-dateutil@2.9.0.post0","pkg:pypi/six@1.17.0"],"schemaVersion":1,"symbols":["freezegun.freeze_time","StepTickTimeFactory.tick","TickingDateTimeFactory.move_to","FrozenDateTimeFactory.tick","freezegun.configure","DEFAULT_IGNORE_LIST"],"verifierAdapter":"python@1"}
requirements.txt
freezegun==1.5.5
python-dateutil==2.9.0.post0
six==1.17.0
src/__init__.py
"""Package root for freezegun boundary tests."""
src/scheduler.py
"""Scheduler and sampling module demonstrating clock interactions under freezegun."""

import queue
import time
from datetime import datetime, timedelta
from freezegun import freeze_time


def sample_window():
    """Takes two consecutive readings to measure an instant.

    Under a static freeze_time(), start == end.
    Under auto_tick_seconds=N, start and end differ by N seconds on consecutive lines.
    """
    start = datetime.now()
    end = datetime.now()
    return start, end


def epoch_pair():
    """Reads datetime.now() and time.time().

    Under standard freeze_time(), naive datetime.now().timestamp() == time.time().
    Under auto_tick_seconds=N, time.time() consumes a second tick, desyncing the two.
    """
    dt = datetime.now()
    ts = time.time()
    return dt, ts


def wait_for_event(q, timeout_sec=0.01):
    """Waits for an item on a queue with a timeout.

    In freezegun 1.5.0+, 'queue' is in DEFAULT_IGNORE_LIST, so timeouts evaluate against
    the real monotonic clock and return promptly without hanging.
    """
    try:
        return q.get(timeout=timeout_sec)
    except queue.Empty:
        return None


@freeze_time("2025-01-01 09:00:00", as_kwarg="clock_handle")
def run_job(label, clock_handle=None):
    """Demonstrates single invocation with injected factory via as_kwarg."""
    t0 = datetime.now()
    clock_handle.tick(timedelta(minutes=30))
    t1 = datetime.now()
    return {"label": label, "t0": t0, "t1": t1}
test/contract.py
import queue
import sys
import time
from datetime import datetime, timedelta
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parents[1]))

import freezegun
import freezegun.config
from freezegun import freeze_time
from freezegun.api import (
    FrozenDateTimeFactory,
    StepTickTimeFactory,
    TickingDateTimeFactory,
)
from src import scheduler


def test_auto_tick_seconds():
    # --- 1. auto_tick_seconds advances on EVERY single clock access ---
    # Naive expectation: time stays constant during a frozen block unless manually ticked.
    # Reality: Every read of datetime.now() or time.time() consumes auto_tick_seconds.
    with freeze_time("2024-01-01 12:00:00", auto_tick_seconds=5) as step_factory:
        assert isinstance(step_factory, StepTickTimeFactory)

        # scheduler.sample_window() calls datetime.now() twice on consecutive lines
        t_start, t_end = scheduler.sample_window()
        assert t_start == datetime(2024, 1, 1, 12, 0, 0)
        assert t_end == datetime(2024, 1, 1, 12, 0, 5)
        assert (t_end - t_start).total_seconds() == 5.0

        # epoch_pair() calls datetime.now() then time.time()
        # time.time() also consumes a tick, causing timestamp() and time.time() to diverge!
        dt_val, ts_val = scheduler.epoch_pair()
        assert dt_val == datetime(2024, 1, 1, 12, 0, 10)
        assert ts_val == 1704110415.0  # corresponds to 12:00:15
        assert ts_val - dt_val.timestamp() == 5.0

        # Calling tick() on StepTickTimeFactory advances by step_width (5s), not 1s default!
        # Internal state is at 12:00:20 before tick; tick moves it to 12:00:25 and returns it.
        tick_result = step_factory.tick()
        assert tick_result == datetime(2024, 1, 1, 12, 0, 25)
        assert isinstance(tick_result, datetime)


def test_ticking_clock_and_move_to():
    # --- 2. tick=True streams real elapsed wall time & 1.5.0 move_to ---
    # Naive expectation: freeze_time always pins time to a static instant.
    # Reality: tick=True allows time to flow forward at 1x speed from the freeze origin.
    with freeze_time("2024-01-01 00:00:00", tick=True) as ticking_factory:
        assert isinstance(ticking_factory, TickingDateTimeFactory)

        t0 = datetime.now()
        time.sleep(0.03)
        t1 = datetime.now()
        assert t1 > t0

        # In freezegun 1.5.0, move_to was added to TickingDateTimeFactory.
        # Prior to 1.5.0, calling move_to on a ticking freeze raised AttributeError.
        move_result = ticking_factory.move_to("2025-06-01 00:00:00")
        assert move_result is None
        assert datetime.now().year == 2025

        # tick() returns the updated datetime object
        tick_result = ticking_factory.tick(timedelta(hours=2))
        assert tick_result.year == 2025 and tick_result.hour == 2
        assert isinstance(tick_result, datetime)


def test_tick_return_values():
    # --- 3. tick() returns updated datetime in 1.5.0+ rather than None ---
    # Naive expectation: tick() returns None like move_to() (as in freezegun <1.5.0).
    # Reality: In 1.5.0+, all tick() methods return the updated datetime.
    with freeze_time("2024-01-01 00:00:00") as static_factory:
        assert isinstance(static_factory, FrozenDateTimeFactory)

        res_tick = static_factory.tick(timedelta(seconds=45))
        assert res_tick == datetime(2024, 1, 1, 0, 0, 45)
        assert isinstance(res_tick, datetime)

        # move_to continues to return None
        res_move = static_factory.move_to("2024-01-02 00:00:00")
        assert res_move is None
        assert datetime.now() == datetime(2024, 1, 2, 0, 0, 0)


def test_queue_ignore_and_configure():
    # --- 4. queue in DEFAULT_IGNORE_LIST & configure(default_ignore_list=[]) ---
    # In 1.5.0, 'queue' was added to DEFAULT_IGNORE_LIST to prevent Queue.get(timeout)
    # from blocking or failing on frozen monotonic time.
    assert "queue" in freezegun.config.DEFAULT_IGNORE_LIST

    q = queue.Queue()
    with freeze_time("2024-01-01 00:00:00"):
        # Queue get uses real monotonic time via call-stack inspection and returns promptly
        item = scheduler.wait_for_event(q, timeout_sec=0.01)
        assert item is None

    # In 1.5.0, configure(default_ignore_list=[]) allows passing an empty list.
    # In <1.5.0, passing [] evaluated as falsy and fell back to DEFAULT_IGNORE_LIST.
    freezegun.configure(default_ignore_list=[])
    with freeze_time("2024-01-01 00:00:00"):
        assert freezegun.api.ignore_lists[-1] == ()
    freezegun.configure(default_ignore_list=None)


def test_decorator_kwarg_vs_arg():
    # --- 5. Decorator as_kwarg passes factory once; as_arg has double-invocation bug ---
    res = scheduler.run_job("backup")
    assert res["label"] == "backup"
    assert res["t0"] == datetime(2025, 1, 1, 9, 0, 0)
    assert res["t1"] == datetime(2025, 1, 1, 9, 30, 0)

    # Prove as_arg double execution: _call_with_time_factory invokes func twice
    call_records = []

    @freeze_time("2024-01-01 00:00:00", as_arg=True)
    def arg_target(*args):
        call_records.append(args)

    arg_target()
    assert len(call_records) == 2
    assert isinstance(call_records[0][0], FrozenDateTimeFactory)
    assert call_records[1] == ()


if __name__ == "__main__":
    test_auto_tick_seconds()
    test_ticking_clock_and_move_to()
    test_tick_return_values()
    test_queue_ignore_and_configure()
    test_decorator_kwarg_vs_arg()
    print(
        f"CONTRACT PASS: freezegun {freezegun.__version__} boundary behaviors verified on Python {'.'.join(map(str, sys.version_info[:2]))}"
    )

Ursprungs-Seeder

csx-seed