Skip to main content
Beyond the core timing and telemetry API, tif1 provides several utility functions to manage its internal state, performance, and reliability layers.

Logging

setup_logging

Configure the logging level for tif1.
def setup_logging(level: int = logging.WARNING) -> None
Parameters:
  • level: Standard logging level from the logging module
Available Levels:
  • logging.DEBUG: Detailed diagnostic information
  • logging.INFO: General informational messages
  • logging.WARNING: Warning messages (default)
  • logging.ERROR: Error messages only
  • logging.CRITICAL: Critical errors only
Example:
import tif1
import logging

# Enable debug logging
tif1.setup_logging(logging.DEBUG)

# Now all tif1 operations will log debug info
session = tif1.get_session(2021, "Belgian Grand Prix", "Race")
Debug Output Example:
DEBUG:tif1.core:Loading session: 2021/Belgian_Grand_Prix/Race
DEBUG:tif1.cache:Cache hit for drivers.json
DEBUG:tif1.http:Fetching https://cdn.jsdelivr.net/...
DEBUG:tif1.core:Loaded 20 drivers

Configuration

get_config

Returns the global configuration singleton instance.
def get_config() -> Config
The Config object allows you to programmatically get and set settings that are normally loaded from .tif1rc or environment variables. Returns:
  • Config singleton instance
Example:
config = tif1.get_config()

# Get current settings
print(f"Lib: {config.get('lib')}")
print(f"Cache enabled: {config.get('enable_cache')}")
print(f"Timeout: {config.get('timeout')}")

# Update settings
config.set("lib", "polars")
config.set("timeout", 60)

# Save to file
config.save()  # Saves to ~/.tif1rc

Config Methods

get(key, default=None)

Retrieve a configuration value.
lib = config.get("lib", "pandas")
timeout = config.get("timeout", 30)

set(key, value)

Update a configuration value in memory.
config.set("lib", "polars")
config.set("enable_cache", True)
config.set("ultra_cold_start", True)

save(path=None)

Save current configuration to a JSON file.
# Save to default location (~/.tif1rc)
config.save()

# Save to custom location
config.save("/path/to/custom/config.json")

Available configuration keys

KeyTypeDefaultDescription
libstr"pandas"DataFrame lib ("pandas" or "polars")
enable_cacheboolTrueEnable multi-layer caching system
cache_dirstr~/.tif1/cacheCache database location
timeoutint30Network request timeout (seconds)
max_retriesint3Maximum retry attempts for failed requests
validate_databoolTrueEnable Pydantic validation of JSON data
ultra_cold_startboolFalseEnable ultra-low latency mode
circuit_breaker_thresholdint5Failures before circuit breaker opens
circuit_breaker_timeoutint60Circuit breaker reset timeout (seconds)

Cache Management

get_cache

Returns the persistent SQLite cache singleton instance.
def get_cache() -> Cache
Returns:
  • Cache singleton instance
Example:
cache = tif1.get_cache()

# Check cache location
print(f"Cache dir: {cache.cache_dir}")

# Check if session data exists
has_data = cache.has_session_data(2025, "Monaco_Grand_Prix", "Race")
print(f"Has cached data: {has_data}")

# Clear all cache
cache.clear()

Cache Methods

clear()

Remove all entries from both memory and SQLite cache.
cache = tif1.get_cache()
cache.clear()
print("Cache cleared")

has_session_data(year, gp, session)

Check if cache contains data for a specific session.
exists = cache.has_session_data(2021, "Belgian_Grand_Prix", "Race")
if exists:
    print("Session data is cached")

close()

Close the SQLite database connection.
cache = tif1.get_cache()
# ... operations ...
cache.close()

get(key)

Get raw cached data by key.
data = cache.get("2025/Monaco_Grand_Prix/Race/drivers.json")

set(key, data)

Store data in cache.
cache.set("custom_key", {"data": "value"})

get_telemetry(year, gp, session, driver, lap)

Get cached telemetry data.
tel_data = cache.get_telemetry(2021, "Belgian_Grand_Prix", "Race", "VER", 1)

set_telemetry(year, gp, session, driver, lap, data)

Store telemetry data in cache.
cache.set_telemetry(2021, "Belgian_Grand_Prix", "Race", "VER", 1, telemetry_dict)

Data Utilities

to_timedelta

Convert various formats to pandas timedelta.
def to_timedelta(x) -> pd.Timedelta
Parameters:
  • x: String, float, int, or timedelta to convert
Example:
from tif1.utils import to_timedelta

# From string
td = to_timedelta("1:23.456")  # 1 minute 23.456 seconds
td = to_timedelta("00:01:23.456")  # Full format

# From seconds
td = to_timedelta(83.456)

# From timedelta (passthrough)
td = to_timedelta(pd.Timedelta(seconds=83.456))

to_datetime

Convert string to pandas datetime.
def to_datetime(x) -> pd.Timestamp
Example:
from tif1.utils import to_datetime

dt = to_datetime("2021-08-29 14:00:00")

recursive_dict_get

Safely navigate nested dictionaries.
def recursive_dict_get(d, *keys, default_none=False)
Parameters:
  • d: Dictionary to navigate
  • *keys: Keys to traverse
  • default_none: Return None instead of on missing keys
Example:
from tif1.utils import recursive_dict_get

data = {
    "session": {
        "info": {
            "name": "Monaco Grand Prix"
        }
    }
}

name = recursive_dict_get(data, "session", "info", "name")
# Returns: "Monaco Grand Prix"

missing = recursive_dict_get(data, "session", "missing", "key", default_none=True)
# Returns: None

delta_time

Calculate delta time between two laps (compatibility function).
def delta_time(reference_lap, compare_lap)
Parameters:
  • reference_lap: Reference Lap object
  • compare_lap: Lap object to compare
Returns:
  • Tuple of (delta_series, ref_telemetry, comp_telemetry)

Reliability & Networking

get_circuit_breaker

Returns the global circuit breaker instance used for network requests.
def get_circuit_breaker() -> CircuitBreaker
The circuit breaker prevents cascading failures by temporarily stopping requests after repeated failures. States:
  • closed: Normal operation, requests allowed
  • open: Too many failures, requests blocked
  • half_open: Testing if service recovered
Example:
from tif1.retry import get_circuit_breaker

cb = get_circuit_breaker()
print(f"State: {cb.state}")
print(f"Failures: {cb.failure_count}")

reset_circuit_breaker

Reset the circuit breaker to closed state.
def reset_circuit_breaker() -> None
Example:
from tif1.retry import reset_circuit_breaker

# Reset after network issues are resolved
reset_circuit_breaker()

get_cdn_manager

Returns the CDN manager responsible for fallback and source health.
def get_cdn_manager() -> CDNManager
Example:
from tif1.cdn import get_cdn_manager

cdn = get_cdn_manager()
print(f"Primary CDN: {cdn.primary_url}")

Lap Cache Management

clear_lap_cache

Clear the in-memory LRU cache for lap DataFrames.
def clear_lap_cache() -> None
Example:
from tif1.core import clear_lap_cache

# Clear lap cache to free memory
clear_lap_cache()

Complete Examples

Configure and save settings

import tif1

# Get config
config = tif1.get_config()

# Update settings
config.set("lib", "polars")
config.set("timeout", 60)
config.set("max_retries", 5)
config.set("ultra_cold_start", True)

# Save to file
config.save()

print("Configuration saved to ~/.tif1rc")

Debug session loading

import tif1
import logging

# Enable debug logging
tif1.setup_logging(logging.DEBUG)

# Load session with debug output
session = tif1.get_session(2021, "Belgian Grand Prix", "Race")
laps = session.laps

# Disable debug logging
tif1.setup_logging(logging.WARNING)

Cache management workflow

import tif1

# Get cache instance
cache = tif1.get_cache()

# Check cache status
print(f"Cache location: {cache.cache_dir}")

# Check if specific session is cached
has_spa = cache.has_session_data(2021, "Belgian_Grand_Prix", "Race")
print(f"Belgian GP cached: {has_spa}")

# Clear cache if needed
if input("Clear cache? (y/n): ").lower() == 'y':
    cache.clear()
    print("Cache cleared")

Handle network issues

import tif1
from tif1.retry import get_circuit_breaker, reset_circuit_breaker

try:
    session = tif1.get_session(2021, "Belgian Grand Prix", "Race")
    laps = session.laps
except tif1.NetworkError as e:
    print(f"Network error: {e.message}")

    # Check circuit breaker state
    cb = get_circuit_breaker()
    print(f"Circuit breaker state: {cb.state}")

    if cb.state == "open":
        print("Circuit breaker is open. Waiting before retry...")
        import time
        time.sleep(60)

        # Reset and retry
        reset_circuit_breaker()
        session = tif1.get_session(2021, "Belgian Grand Prix", "Race")

Custom configuration file

import tif1
from pathlib import Path

# Load custom config
config = tif1.get_config()

# Set custom cache directory
custom_cache = Path.home() / "my_f1_cache"
config.set("cache_dir", str(custom_cache))

# Set performance options
config.set("lib", "polars")
config.set("ultra_cold_start", True)
config.set("validate_data", False)  # Skip validation for speed

# Save to custom location
config.save(Path.home() / ".my_tif1_config")

Best Practices

  1. Enable debug logging during development: Helps understand data flow and identify issues.
  2. Use polars lib for large datasets: Better memory efficiency and performance.
  3. Clear cache periodically: Prevents disk space issues.
  4. Increase timeout for slow connections: Default 30s may not be enough on slow networks.
  5. Disable validation in production: Saves ~10-15% processing time if data quality is trusted.
  6. Use ultra-cold start for single lap queries: Significantly faster when you only need one lap’s telemetry.
  7. Save configuration after tuning: Persist your optimized settings.
  8. Monitor circuit breaker state: Helps diagnose network issues.
  9. Close cache on exit: Ensures data is flushed to disk.
import atexit
import tif1

cache = tif1.get_cache()
atexit.register(cache.close)
Last modified on March 5, 2026