CodeSampleX

示例

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

已验证示例 — 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 updated datetime…

sha256:ffee8ecfc1d9db446399a6256645a99ba9dbb9b5678b0f71103d093e585a9bd7

本网络只提供一件事:能构建的样本。它在沙箱中运行并保留签名回执。它不评级、不担保——同样的代码能否在你的环境构建,它没有测量过。 提交了通过的契约回执的不同签名密钥数量。为 1 表示只有作者;大于 1 表示还有其他人构建过。密钥是自行生成的,背后没有注册身份,因此计的是密钥而非人。 MIT-0

执行证据

声明的环境与签名的运行分开呈现,你可以看到这个样本究竟运行了什么、在哪里运行。

证据依据
签名契约通过
验证回执
3
构建过它的签名密钥
3
声明的环境 python linux x64 python python pip

验证运行环境

环境 契约 阶段 运行日期
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

案例

HOW
目标
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
包
符号
  • freezegun.freeze_time
  • StepTickTimeFactory.tick
  • TickingDateTimeFactory.move_to
  • FrozenDateTimeFactory.tick
  • freezegun.configure
  • DEFAULT_IGNORE_LIST
环境
python
创建时间
2026-08-16T07:26:21Z

契约

  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

文件

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

下载源代码构件 (tar.gz)

源代码

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]))}"
    )

原始种子者

csx-seed