Exemplo
freezegun 1.5.5: Decorating functions and classes with freeze_time double-executes as_arg on sync callables, drops as_kwarg on coroutines, skips __init__ and staticmethods on classes, and ticks auto_tick_seconds on every clock read
Amostra verificada para pypi freezegun 1.5.5: Decorating functions and classes with freeze_time double-executes as_arg on sync callables, drops as_kwarg on…
sha256:38d96e5f0bc7e4a9bc1e19b8579a875bcd87770979dd72ba52daf672ba73049a
Esta rede oferece uma coisa: uma amostra que compila. Ela a executou em um sandbox e guardou o recibo assinado. Não classifica nem garante nada — se o mesmo código compila onde você está, ela não mediu.
Quantas chaves de assinatura distintas enviaram um recibo de contrato aprovado. Uma é só o autor; mais de uma significa que outra pessoa também o compilou. Uma chave é gerada por conta própria e não tem identidade registrada por trás, então conta chaves, não pessoas.
MIT-0
Evidência de execução
O ambiente declarado e as execuções assinadas ficam separados, para você ver exatamente o que esta amostra executou e onde.
- Base da evidência
- Contrato assinado aprovado
- Recibos de verificação
- 3
- Chaves de assinatura que o compilaram
- 3
Ambiente declarado
python 3.12 linux x64 python 3.12 python pip
Ambientes das execuções de verificação
| Ambiente | Contrato | Etapas | Execução |
|---|---|---|---|
| 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 |
Caso
HOW- Objetivo
- Decorating functions and classes with freeze_time double-executes as_arg on sync callables, drops as_kwarg on coroutines, skips __init__ and staticmethods on classes, and ticks auto_tick_seconds on every clock read
- Símbolos
-
- freezegun.freeze_time
- as_arg
- as_kwarg
- auto_tick_seconds
- tick
- StepTickTimeFactory
- TickingDateTimeFactory
- FrozenDateTimeFactory
- Ambiente
- python 3.12
- Criado
- 2026-08-16T07:26:18Z
Contrato
- assert @freeze_time with as_arg=True executes sync functions twice due to an unbranched else clause in _call_with_time_factory, failing required positional arguments with TypeError on the second call
- assert @freeze_time with as_kwarg passes the time factory once on sync functions but wrap_coroutine silently drops as_kwarg on async coroutines
- assert @freeze_time with as_arg=True passes the time factory once to async coroutines without double execution
- assert @freeze_time on a class wraps public methods but skips __init__, private methods, staticmethods and classmethods which continue reading the real host clock
- assert auto_tick_seconds advances the clock by its step duration on every read of datetime.now(), time.time(), date.today(), time.monotonic(), and time.time_ns()
- assert generator and callable time_to_freeze arguments are evaluated once upon entering the freeze rather than dynamically on each clock read
- assert tick=True unfreezes time passage to real-time progression from the frozen start rather than stepping in fixed increments
Arquivos
- NOTES.md
- csx.json
- requirements.txt
- src/__init__.py
- src/services.py
- test/contract.py
Código-fonte
# Notes on freezegun Decorator Mechanics and Auto-Tick Traps
## Prior Known Solution Search
`search_known_solution` returned COMPATIBLE hit `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"
That sample focused on context manager module patching, bound classmethods, datetime subclasses, `move_to()`, and `tz_offset`.
## What a Model Would Have Written Instead
A model expecting documented decorator behavior would write `@freeze_time("2020-01-01", as_arg=True)` on a test function `def test_flow(frozen_time): ...`, `@freeze_time("2020-01-01", as_kwarg="ft")` on an async coroutine, `@freeze_time("2020-01-01")` over an entire service class assuming `__init__` and static methods freeze too, and `auto_tick_seconds=10` assuming only `datetime.now()` advances the clock.
## How the Wrong Version Fails
The `as_arg=True` decorator executes the function twice and crashes loudly with `TypeError: test_flow() missing 1 required positional argument: 'frozen_time'`, while `as_kwarg` on `async def` and class-decorated `__init__` / static methods fail silently with a green build that leaks real un-frozen host time.
{"case":{"caseId":"case:sha256:911044630ceca4a5be5eff589e3961fb32c37e7f6e6e4b181a926d5a2913ef1d","contract":["assert @freeze_time with as_arg=True executes sync functions twice due to an unbranched else clause in _call_with_time_factory, failing required positional arguments with TypeError on the second call","assert @freeze_time with as_kwarg passes the time factory once on sync functions but wrap_coroutine silently drops as_kwarg on async coroutines","assert @freeze_time with as_arg=True passes the time factory once to async coroutines without double execution","assert @freeze_time on a class wraps public methods but skips __init__, private methods, staticmethods and classmethods which continue reading the real host clock","assert auto_tick_seconds advances the clock by its step duration on every read of datetime.now(), time.time(), date.today(), time.monotonic(), and time.time_ns()","assert generator and callable time_to_freeze arguments are evaluated once upon entering the freeze rather than dynamically on each clock read","assert tick=True unfreezes time passage to real-time progression from the frozen start rather than stepping in fixed increments"],"goal":"Decorating functions and classes with freeze_time double-executes as_arg on sync callables, drops as_kwarg on coroutines, skips __init__ and staticmethods on classes, and ticks auto_tick_seconds on every clock read","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","as_arg","as_kwarg","auto_tick_seconds","tick","StepTickTimeFactory","TickingDateTimeFactory","FrozenDateTimeFactory"]},"contractCommand":["python","test/contract.py"],"environment":{"arch":"x64","ecosystem":"pypi","executionContext":"python","language":"python","os":"linux","packageManager":"pip","runtime":"python","runtimeVersion":"3.12","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","as_arg","as_kwarg","auto_tick_seconds","tick","StepTickTimeFactory","TickingDateTimeFactory","FrozenDateTimeFactory"],"verifierAdapter":"python@1"}
freezegun==1.5.5
python-dateutil==2.9.0.post0
six==1.17.0
"""src package for freezegun API contract."""
"""Domain services showing decorator and class-level interactions with freezegun."""
from datetime import datetime
from freezegun import freeze_time
@freeze_time("2020-01-01 00:00:00")
class BillingService:
"""Class decorated with freeze_time.
freezegun's decorate_class iterates the class dictionary and wraps only
callable attributes that do not start with '_' and are not staticmethod
or classmethod instances.
"""
def __init__(self):
# Starts with '_', so __init__ is not wrapped and sees real host time.
self.created_at = datetime.now()
def create_invoice(self):
# Public instance method: wrapped and frozen.
return datetime.now()
def _internal_check(self):
# Leading underscore: skipped and sees real host time.
return datetime.now()
@staticmethod
def calculate_tax_time():
# staticmethod is explicitly excluded by decorate_class: sees real host time.
return datetime.now()
@classmethod
def audit_class_time(cls):
# classmethod descriptor is not callable at decoration time: sees real host time.
return datetime.now()
import asyncio
from datetime import date, datetime, timedelta
from pathlib import Path
import sys
import time
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
import freezegun
from freezegun import freeze_time
from freezegun.api import FrozenDateTimeFactory, StepTickTimeFactory, TickingDateTimeFactory
from src.services import BillingService
# Ensure host machine clock is recent enough to distinguish real time from frozen test dates
assert datetime.now() > datetime(2020, 1, 1)
# -----------------------------------------------------------------------------
# 1. The as_arg=True double invocation trap on regular functions
# -----------------------------------------------------------------------------
sync_arg_invocations = 0
@freeze_time("2020-01-01 00:00:00", as_arg=True)
def sync_worker_with_default(factory=None):
global sync_arg_invocations
sync_arg_invocations += 1
# Returns whether the factory argument was passed in this invocation
return factory is not None
# Calling the decorated function causes freezegun's _call_with_time_factory to execute:
# 1st call: func(time_factory, *args, **kwargs) -> factory is FrozenDateTimeFactory
# 2nd call: func(*args, **kwargs) -> factory is None (due to broken else branch)
# The return value from the 2nd invocation overwrites the 1st, so result is False!
result = sync_worker_with_default()
assert sync_arg_invocations == 2
assert result is False
# When the function requires positional argument without a default, the 2nd call crashes
@freeze_time("2020-01-01 00:00:00", as_arg=True)
def strict_worker(factory):
return factory
try:
strict_worker()
assert False, "Expected TypeError from second parameterless invocation"
except TypeError as exc:
assert "missing 1 required positional argument: 'factory'" in str(exc)
# -----------------------------------------------------------------------------
# 2. as_kwarg behaves correctly on sync functions but is dropped on async coroutines
# -----------------------------------------------------------------------------
sync_kwarg_invocations = 0
@freeze_time("2020-01-01 00:00:00", as_kwarg="time_factory")
def sync_worker_kwarg(time_factory=None):
global sync_kwarg_invocations
sync_kwarg_invocations += 1
return time_factory
kwarg_factory = sync_worker_kwarg()
assert sync_kwarg_invocations == 1
assert isinstance(kwarg_factory, FrozenDateTimeFactory)
assert kwarg_factory.time_to_freeze == datetime(2020, 1, 1, 0, 0, 0)
# Async coroutine: wrap_coroutine only checks `if api.as_arg:`, ignoring `as_kwarg` completely!
@freeze_time("2020-01-01 00:00:00", as_kwarg="time_factory")
async def async_worker_kwarg(time_factory=None):
return time_factory
async_kwarg_result = asyncio.run(async_worker_kwarg())
assert async_kwarg_result is None # as_kwarg is silently ignored in async coroutines!
# In contrast, as_arg=True on async coroutines works cleanly without the double-call bug
async_arg_invocations = 0
@freeze_time("2020-01-01 00:00:00", as_arg=True)
async def async_worker_arg(factory):
global async_arg_invocations
async_arg_invocations += 1
return factory
async_arg_factory = asyncio.run(async_worker_arg())
assert async_arg_invocations == 1
assert isinstance(async_arg_factory, FrozenDateTimeFactory)
# -----------------------------------------------------------------------------
# 3. Class decorator scope: skips __init__, _private, staticmethod, classmethod
# -----------------------------------------------------------------------------
service = BillingService()
# Public instance methods are wrapped and frozen
assert service.create_invoice() == datetime(2020, 1, 1, 0, 0, 0)
# __init__ starts with '_' and was not wrapped: created_at has real host time
assert service.created_at > datetime(2020, 1, 2)
# Private method starts with '_' and was skipped: has real host time
assert service._internal_check() > datetime(2020, 1, 2)
# staticmethod is explicitly excluded in decorate_class: has real host time
assert BillingService.calculate_tax_time() > datetime(2020, 1, 2)
# classmethod descriptor is not callable during class inspection: has real host time
assert BillingService.audit_class_time() > datetime(2020, 1, 2)
# -----------------------------------------------------------------------------
# 4. auto_tick_seconds advances on EVERY clock access across all time/date APIs
# -----------------------------------------------------------------------------
with freeze_time("2020-01-01 00:00:00", auto_tick_seconds=15) as step_factory:
assert isinstance(step_factory, StepTickTimeFactory)
# 1st read (datetime.now): returns baseline 00:00:00, then ticks +15s
t1 = datetime.now()
assert t1 == datetime(2020, 1, 1, 0, 0, 0)
# 2nd read (time.time): returns epoch for 00:00:15, then ticks +15s
t2 = time.time()
assert t2 == 1577836815.0
# 3rd read (date.today): reads clock internally, returns date, then ticks +15s
t3 = date.today()
assert t3 == date(2020, 1, 1)
# 4th read (time.monotonic): returns epoch seconds for 00:00:45, then ticks +15s
t4 = time.monotonic()
assert t4 == 1577836845.0
# 5th read (time.time_ns): returns nanoseconds for 00:01:00, then ticks +15s
t5 = time.time_ns()
assert t5 == 1577836860_000_000_000
# 6th read (datetime.now): reflects 75s of accumulated ticks (00:01:15), then ticks +15s
t6 = datetime.now()
assert t6 == datetime(2020, 1, 1, 0, 1, 15)
# Manual tick can be mixed with auto_tick: moves baseline by +20s
step_factory.tick(timedelta(seconds=20))
# Next read sees 00:01:15 + 15s (auto-tick) + 20s (manual tick) = 00:01:50
t7 = datetime.now()
assert t7 == datetime(2020, 1, 1, 0, 1, 50)
# -----------------------------------------------------------------------------
# 5. Callable and Generator time_to_freeze is evaluated once at start, not on each read
# -----------------------------------------------------------------------------
staged_dates = [datetime(2021, 1, 1), datetime(2022, 1, 1), datetime(2023, 1, 1)]
def date_generator():
for d in staged_dates:
yield d
# Passing a generator object or generator function evaluates only next(gen) on entry
with freeze_time(date_generator()):
read_a = datetime.now()
read_b = datetime.now()
assert read_a == datetime(2021, 1, 1)
# The second read does NOT advance to 2022-01-01
assert read_b == datetime(2021, 1, 1)
# -----------------------------------------------------------------------------
# 6. tick=True creates a TickingDateTimeFactory that progresses in real time
# -----------------------------------------------------------------------------
with freeze_time("2020-01-01 00:00:00", tick=True) as ticking_factory:
assert isinstance(ticking_factory, TickingDateTimeFactory)
start_tick = datetime.now()
# Microsecond difference between consecutive statements, not stepped seconds
immediate_tick = datetime.now()
diff = (immediate_tick - start_tick).total_seconds()
assert 0 <= diff < 0.1
print(
f"CONTRACT PASS: freezegun {freezegun.__version__} "
"verified as_arg double-execution, async as_kwarg drop, class decoration limits, and auto_tick_seconds behavior"
)