CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-time-machine

Travel through time in your tests.

Overview
Eval results
Files

escape-hatch.mddocs/

Escape Hatch

The escape hatch provides access to real time functions during time travel, enabling tests to access actual system time when needed. This is essential for performance measurements, external API calls, or any operations requiring real timestamps.

Capabilities

Escape Hatch Object

The global escape_hatch object provides access to real time functions and travel status checking.

class _EscapeHatch:
    def is_travelling(self) -> bool:
        """
        Check if time travel is currently active.
        
        Returns:
        True if time travel is active, False otherwise
        """
    
    time: _EscapeHatchTime
    datetime: _EscapeHatchDatetime
escape_hatch: _EscapeHatch

Usage examples:

import time_machine
from datetime import datetime

# Check travel status
print(time_machine.escape_hatch.is_travelling())  # False

with time_machine.travel("2023-01-01"):
    print(time_machine.escape_hatch.is_travelling())  # True
    
    # Access real time during travel
    real_time = time_machine.escape_hatch.time.time()
    fake_time = time.time()
    
    print(f"Real time: {real_time}")
    print(f"Fake time: {fake_time}")

print(time_machine.escape_hatch.is_travelling())  # False

Real Time Functions

Access to real time module functions that bypass time travel patching.

class _EscapeHatchTime:
    def clock_gettime(self, clk_id: int) -> float:
        """
        Get real clock time for specified clock ID.
        
        Parameters:
        - clk_id: Clock identifier (e.g., time.CLOCK_REALTIME)
        
        Returns:
        Real clock time as float seconds
        """
    
    def clock_gettime_ns(self, clk_id: int) -> int:
        """
        Get real clock time in nanoseconds for specified clock ID.
        
        Parameters:
        - clk_id: Clock identifier
        
        Returns:
        Real clock time as int nanoseconds
        """
    
    def gmtime(self, secs: float | None = None) -> struct_time:
        """
        Get real GMT time struct.
        
        Parameters:
        - secs: Optional timestamp, uses real current time if None
        
        Returns:
        Real GMT time as struct_time
        """
    
    def localtime(self, secs: float | None = None) -> struct_time:
        """
        Get real local time struct.
        
        Parameters:
        - secs: Optional timestamp, uses real current time if None
        
        Returns:
        Real local time as struct_time
        """
    
    def monotonic(self) -> float:
        """
        Get real monotonic time (unaffected by system clock adjustments).
        
        Returns:
        Real monotonic time as float seconds
        """
    
    def monotonic_ns(self) -> int:
        """
        Get real monotonic time in nanoseconds.
        
        Returns:
        Real monotonic time as int nanoseconds
        """
    
    def strftime(self, format: str, t: tuple | struct_time | None = None) -> str:
        """
        Format real time using strftime.
        
        Parameters:
        - format: Format string
        - t: Optional time tuple, uses real current time if None
        
        Returns:
        Formatted time string
        """
    
    def time(self) -> float:
        """
        Get real current time as Unix timestamp.
        
        Returns:
        Real current time as float seconds since Unix epoch
        """
    
    def time_ns(self) -> int:
        """
        Get real current time as nanosecond timestamp.
        
        Returns:
        Real current time as int nanoseconds since Unix epoch
        """

Usage examples:

import time
import time_machine

with time_machine.travel("2023-01-01"):
    # Fake time (2023)
    fake_time = time.time()
    
    # Real time (actual current time)
    real_time = time_machine.escape_hatch.time.time()
    
    print(f"Travel time: {fake_time}")  # ~1672531200 (2023-01-01)
    print(f"Real time: {real_time}")    # Actual current timestamp
    
    # Performance measurement using real monotonic time
    start = time_machine.escape_hatch.time.monotonic()
    # ... some operation ...
    elapsed = time_machine.escape_hatch.time.monotonic() - start
    print(f"Real elapsed time: {elapsed}")

Real DateTime Functions

Access to real datetime module functions that bypass time travel patching.

class _EscapeHatchDatetime:
    datetime: _EscapeHatchDatetimeDatetime

class _EscapeHatchDatetimeDatetime:
    def now(self, tz: dt.tzinfo | None = None) -> dt.datetime:
        """
        Get real current datetime.
        
        Parameters:
        - tz: Optional timezone info
        
        Returns:
        Real current datetime object
        """
    
    def utcnow(self) -> dt.datetime:
        """
        Get real current UTC datetime (naive).
        
        Returns:
        Real current UTC datetime without timezone info
        """

Usage examples:

import time_machine
from datetime import datetime, timezone

with time_machine.travel("2023-01-01"):
    # Fake datetime (2023)
    fake_now = datetime.now()
    
    # Real datetime (actual current time)
    real_now = time_machine.escape_hatch.datetime.datetime.now()
    
    print(f"Travel time: {fake_now}")  # 2023-01-01 00:00:00
    print(f"Real time: {real_now}")    # Actual current datetime
    
    # Real UTC time
    real_utc = time_machine.escape_hatch.datetime.datetime.utcnow()
    print(f"Real UTC: {real_utc}")
    
    # Real time with timezone
    real_tz = time_machine.escape_hatch.datetime.datetime.now(timezone.utc)
    print(f"Real UTC+TZ: {real_tz}")

Common Use Cases

Performance Measurement

import time_machine

def test_performance():
    with time_machine.travel("2023-01-01"):
        # Use real monotonic time for accurate performance measurement
        start = time_machine.escape_hatch.time.monotonic()
        
        # Operation being timed
        slow_operation()
        
        elapsed = time_machine.escape_hatch.time.monotonic() - start
        assert elapsed < 1.0  # Should complete within 1 second

External API Testing

import time_machine
import requests

def test_api_with_real_timestamps():
    with time_machine.travel("2023-01-01"):
        # API expects real timestamps in headers
        real_timestamp = time_machine.escape_hatch.time.time()
        
        response = requests.post("https://api.example.com/data", 
                               headers={"X-Timestamp": str(real_timestamp)},
                               json={"created_at": time.time()})  # Uses fake time
        
        assert response.status_code == 200

Logging with Real Timestamps

import time_machine
import logging

def test_with_real_log_timestamps():
    # Custom formatter using real time
    class RealTimeFormatter(logging.Formatter):
        def formatTime(self, record, datefmt=None):
            real_time = time_machine.escape_hatch.time.time()
            return super().formatTime(
                type('Record', (), {'created': real_time})(), datefmt
            )
    
    with time_machine.travel("2023-01-01"):
        logger = logging.getLogger("test")
        handler = logging.StreamHandler()
        handler.setFormatter(RealTimeFormatter())
        logger.addHandler(handler)
        
        logger.info("This log has real timestamp despite time travel")

Conditional Logic Based on Travel Status

import time_machine

def get_current_time():
    """Get current time, using real time in production, fake time in tests."""
    if time_machine.escape_hatch.is_travelling():
        # In tests - use travel time
        return datetime.now()
    else:
        # In production - use real time
        return time_machine.escape_hatch.datetime.datetime.now()

def test_conditional_time():
    # Outside travel - uses real time
    real_time = get_current_time()
    
    with time_machine.travel("2023-01-01"):
        # Inside travel - uses fake time
        fake_time = get_current_time()
        assert fake_time.year == 2023

Type Definitions

from time import struct_time
from datetime import datetime as dt

_TimeTuple = tuple[int, int, int, int, int, int, int, int, int]

Install with Tessl CLI

npx tessl i tessl/pypi-time-machine

docs

cli-migration.md

core-time-travel.md

escape-hatch.md

index.md

pytest-integration.md

tile.json