Overview
tif1 is built with type safety as a first-class citizen. Every public API, function, method, and data structure includes comprehensive type hints that enable static type checkers (mypy, pyright, pytype) to catch errors before runtime. This design philosophy provides multiple benefits:
- Compile-time error detection: Catch type mismatches, invalid parameters, and API misuse before running code
- Enhanced IDE support: Get accurate autocomplete, inline documentation, parameter hints, and refactoring tools
- Self-documenting code: Type hints serve as inline documentation that never goes out of sync
- Safer refactoring: Change code with confidence knowing type checkers will catch breaking changes
- Better developer experience: Spend less time debugging runtime errors and more time building features
tif1, organized into the following sections:
What You’ll Learn
- Literal Type Aliases - Constrained string values for session types, tire compounds, backends, and track status
- TypedDict Schemas - Structured definitions for DataFrame row data (laps, telemetry, weather, race control)
- DataFrame Type Hints - Proper typing for pandas and polars DataFrames
- Object Type Hints - Type annotations for Session, Driver, Lap, and other core objects
- Protocol Types - Duck-typed interfaces for DataFrame-like objects
- Generic Type Patterns - Advanced patterns for async functions, unions, and generic code
- Type Checking Tools - How to use mypy, pyright, and IDE integrations
- Best Practices - Proven patterns for writing type-safe tif1 code
Quick Import Reference
All types are importable fromtif1.types:
Type System Philosophy
tif1 follows these type system principles:
- Explicit over implicit: All public APIs have explicit type annotations
- Strict by default: Types are as specific as possible (Literal types over str)
- Optional transparency: Optional fields use
NotRequiredorOptionalto make None handling explicit - Backend agnostic: Union types support both pandas and polars without code changes
- Runtime validation: Types are validated at runtime where appropriate (pydantic models)
- Zero runtime cost: Type hints have no performance impact in production
Literal Type Aliases
Literal types are one of Python’s most powerful type system features. They restrict values to a specific, finite set of allowed strings, providing compile-time validation and excellent autocomplete support in IDEs. Unlike plainstr types, Literal types give you:
- Exhaustive checking: Type checkers can verify all possible values are handled
- Autocomplete: IDEs show exactly which values are valid
- Refactoring safety: Renaming a literal value updates all usages
- Documentation: The type itself documents valid values
BackendType
The BackendType literal specifies which DataFrame library backend to use for data operations. tif1 is designed to be backend-agnostic, supporting both pandas and polars with identical APIs.
Backend Comparison
| Feature | pandas | polars |
|---|---|---|
| Performance | Good for small-medium datasets | Excellent for large datasets |
| Memory Usage | Higher memory footprint | Optimized memory usage |
| Evaluation | Eager (immediate) | Lazy (optimized query plans) |
| Ecosystem | Massive ecosystem, 15+ years | Growing ecosystem, modern |
| Learning Curve | Gentle, widely documented | Steeper, but more consistent API |
| Parallelization | Limited (GIL-bound) | Built-in parallel execution |
| Type Safety | Improving with pandas 2.0+ | Strong typing from the start |
| Best For | Exploratory analysis, small data | Production pipelines, big data |
When to Choose Each Backend
Choose pandas when:- Working with datasets under 1GB
- Using existing pandas-based code or libraries
- Need maximum ecosystem compatibility (scikit-learn, matplotlib, etc.)
- Prefer familiar, widely-documented APIs
- Doing interactive exploratory analysis in Jupyter
- Working with datasets over 1GB
- Need maximum performance and memory efficiency
- Building production data pipelines
- Want lazy evaluation and query optimization
- Need better multi-core utilization
- Prefer strongly-typed, consistent APIs
Basic Usage
Global Configuration
Set the backend globally to avoid passinglib to every function:
Function Parameter Typing
UseBackendType in function signatures to enforce valid backends:
Runtime Backend Detection
Check which backend is being used at runtime:Backend-Specific Optimizations
Write code that adapts to the backend:Type-Safe Backend Switching
Create a utility to safely switch backends:SessionType
The SessionType literal defines all valid Formula 1 session types across different weekend formats. Formula 1 has evolved its weekend structure over the years, introducing sprint races and varying qualifying formats. This type ensures you only reference sessions that actually exist in the F1 calendar.
F1 Weekend Format Evolution
Formula 1 weekend formats have changed significantly, especially with the introduction of sprint races: Standard Race Weekend (Traditional Format) Used for most Grand Prix weekends:| Day | Session | Purpose |
|---|---|---|
| Friday | Practice 1 (FP1) | Initial setup, tire testing, track familiarization |
| Friday | Practice 2 (FP2) | Race simulation, long runs, setup refinement |
| Saturday | Practice 3 (FP3) | Final setup changes, qualifying preparation |
| Saturday | Qualifying | Determines race starting grid (Q1, Q2, Q3 format) |
| Sunday | Race | Main event, championship points awarded |
| Day | Session | Purpose |
|---|---|---|
| Friday | Practice 1 (FP1) | Only practice session, limited setup time |
| Friday | Qualifying | Determines Sprint starting grid |
| Saturday | Sprint | Short race (~100km), determines Race starting grid |
| Sunday | Race | Main event, full championship points |
| Day | Session | Purpose |
|---|---|---|
| Friday | Practice 1 (FP1) | Only practice session |
| Friday | Sprint Qualifying/Shootout | Determines Sprint starting grid |
| Saturday | Sprint | Short race, determines Race starting grid |
| Saturday | Qualifying | Determines Race starting grid (overrides Sprint result) |
| Sunday | Race | Main event, full championship points |
Session Type Details
Practice Sessions"Practice 1": First practice session, typically Friday morning"Practice 2": Second practice session, typically Friday afternoon"Practice 3": Third practice session, typically Saturday morning (standard weekends only)
"Qualifying": Main qualifying session determining race grid"Sprint Qualifying": Qualifying for sprint race (2023 format, some races)"Sprint Shootout": Alternative name for sprint qualifying (2023 format, some races)
"Sprint": Short-format race (~100km, ~30 minutes)"Race": Main Grand Prix race (full distance, ~305km except Monaco)
Basic Usage
Loading All Weekend Sessions
Iterate through all sessions for a complete weekend analysis:Dynamic Session Detection
Handle different weekend formats automatically:Weekend Format Detection
Determine which format a weekend uses:Session Validation
Validate session names before using them:Session Comparison and Analysis
Compare sessions across a weekend:CompoundType
The CompoundType literal defines all possible tire compound names used in Formula 1. Pirelli, the official tire supplier, provides different compounds for different track conditions and strategies.
Tire Compound Breakdown
Dry Weather Compounds (Slick Tires) Pirelli brings three dry compounds to each race, designated as Soft, Medium, and Hard. The actual compounds vary by track:-
"SOFT": Fastest but least durable, used for qualifying and short stints- Highest grip level
- Fastest lap times
- Shortest lifespan (typically 15-25 laps depending on track)
- Preferred for qualifying and sprint races
- Red sidewall marking
-
"MEDIUM": Balanced performance and durability- Middle ground between speed and longevity
- Common race start tire
- Moderate degradation (typically 25-35 laps)
- Yellow sidewall marking
-
"HARD": Slowest but most durable, used for long stints- Lowest grip but longest lifespan
- Used for one-stop strategies
- Highest durability (typically 35-50+ laps)
- White sidewall marking
-
"INTERMEDIATE": For damp or drying track conditions- Used when track is wet but not soaked
- Can disperse moderate water
- Green sidewall marking
- Often used as track transitions from wet to dry
-
"WET": For heavy rain and standing water- Maximum water displacement (85 liters per second at 300 km/h)
- Deep grooves for aquaplaning prevention
- Blue sidewall marking
- Mandatory in very wet conditions
"UNKNOWN": Compound data not available or not recorded"TEST_UNKNOWN": Used during testing sessions where compound is not specified
Basic Usage
Tire Strategy Analysis
Analyze tire strategies across a race:Compound Performance Comparison
Compare lap times across different compounds:Tire Degradation Analysis
Track tire degradation over a stint:Compound Usage Statistics
Get overall compound usage statistics:TrackStatusType
The TrackStatusType literal defines track status codes that indicate race control conditions during a session. These codes are critical for understanding when laps are valid for comparison and when incidents occurred.
Track Status Breakdown
Green Flag Conditions"1": Normal racing conditions- Full racing speed allowed
- Overtaking permitted
- Lap times are representative
- Used for performance analysis
"2": Local yellow flag- Danger on or near track
- Drivers must slow down
- No overtaking in affected sector
- Lap times affected, not representative
"4": Safety Car deployed- Physical pace car on track
- All cars bunch up behind safety car
- Significantly slower lap times
- Used for major incidents or debris
- Pit stops often strategic during SC
-
"6": VSC active- No physical car, drivers follow delta time
- Must maintain specific lap time
- No overtaking
- Less bunching than full SC
- Used for minor incidents
-
"7": VSC ending- Transition period
- Drivers prepare to resume racing
- Brief status before green flag
"5": Session stopped- All cars must return to pits
- Track conditions unsafe
- Used for major accidents, heavy rain, or track damage
- Session may resume later
Basic Usage
Filtering Representative Laps
Get only laps that are representative of true pace:Track Status Timeline
Analyze when track status changed during a session:Safety Car Impact Analysis
Analyze the impact of safety cars on race pace:TypedDict Schemas
TypedDict is a Python feature that provides type hints for dictionary structures. Unlike regular dictionaries, TypedDict allows you to specify:- Exact keys that must or may exist
- Type of value for each key
- Which fields are required vs optional
tif1 uses TypedDict extensively to define the structure of DataFrame row data. This provides:
- Type safety: IDEs and type checkers know what fields exist
- Autocomplete: Get field suggestions when accessing row data
- Documentation: The type itself documents the data structure
- Validation: Catch typos and missing fields at development time
NotRequired for optional fields, making it explicit which fields may be None or missing.
LapDataDict
The LapDataDict TypedDict defines the complete structure of lap timing data in DataFrames. This is the most comprehensive data structure in tif1, containing timing, speed, tire, weather, and metadata for each lap.
Field Categories Explained
Core Identity Fields These four fields are always present and form the unique identity of each lap:datetime.timedelta objects for precision and easy arithmetic:
Complete Lap Analysis Example
Comprehensive example using all field categories:TelemetryDataDict
Structure of high-frequency telemetry data. All fields except Time are optional.
WeatherDataDict
Structure of weather data returned by session.weather.
RaceControlDataDict
Structure of race control messages.
DriverInfoDict
Structure of driver information.
DataFrame type hints
For better IDE support, use type hints with DataFrames:Pandas DataFrames
Polars DataFrames
Union types for lib-agnostic code
Object type hints
Core Objects
Model Objects
Generic type hints
Async Functions
Dictionary Returns
Complete type-annotated example
Type Checking
Using mypy
Using pyright
IDE Support
Modern IDEs like VS Code, PyCharm, and others provide:- Autocomplete based on type hints
- Inline type checking
- Parameter hints
- Return type hints
Best Practices
- Always use type hints in function signatures: Helps catch errors early.
- Use Union types for lib-agnostic code: Supports both pandas and polars.
- Import types from tif1.types: Centralized type definitions.
- Use TypedDict for JSON data: Better than plain dicts.
- Enable strict type checking: Use mypy or pyright in CI/CD.
- Document complex types: Add docstrings explaining type parameters.
- Use Optional for nullable values: Makes None handling explicit.
Hovering over ‘session’ shows: session: Session
laps = session.lapsHovering over ‘laps’ shows: laps: DataFrame
driver = session.get_driver(“VER”)Hovering over ‘driver’ shows: driver: Driver
2. Use Union Types for Backend-Agnostic Code
Support both pandas and polars without code duplication:3. Import Types from tif1.types
Centralized type definitions ensure consistency:4. Use TypedDict for Structured Data
Better than plain dicts for type safety:5. Enable Strict Type Checking
Use mypy or pyright in your development workflow:6. Document Complex Types
Add docstrings explaining type parameters:7. Use Optional for Nullable Values
Make None handling explicit:8. Leverage Type Guards
Use type guards for runtime type checking:9. Use Literal Types for Constants
Restrict values to specific constants:10. Combine Types for Complex Scenarios
Use type combinations for advanced patterns:Summary
This comprehensive guide covered all type definitions intif1:
Key Takeaways
- Literal Types provide compile-time validation for constrained values (BackendType, SessionType, CompoundType, TrackStatusType)
- TypedDict Schemas define structured DataFrame row data with explicit required/optional fields (LapDataDict, TelemetryDataDict, WeatherDataDict, RaceControlDataDict, DriverInfoDict)
- DataFrame Types support both pandas and polars through Union types, enabling backend-agnostic code
- Object Types provide type hints for core tif1 objects (Session, Driver, Lap, Telemetry)
- Type Checking Tools (mypy, pyright) catch errors before runtime and integrate with modern IDEs
- Best Practices include always using type hints, leveraging Union types, importing from tif1.types, and enabling strict type checking
Benefits of Type Safety in tif1
- Catch Errors Early: Type checkers find bugs before code runs
- Better IDE Support: Autocomplete, inline docs, refactoring tools
- Self-Documenting: Types serve as always-current documentation
- Safer Refactoring: Change code confidently with type validation
- Improved Collaboration: Types communicate intent to other developers
- Zero Runtime Cost: Type hints have no performance impact
Next Steps
- Enable Type Checking: Add mypy or pyright to your project
- Add Type Hints: Annotate your tif1 code with proper types
- Use IDE Features: Leverage autocomplete and inline documentation
- Write Type-Safe Code: Follow the best practices outlined above
- Contribute: Help improve tif1’s type definitions