Skip to main content

Temporal Code

Time-Native Programming for Python

PyPI version Python License: MIT


Temporal Code introduces a programming paradigm where function behavior evolves over time. Instead of deploying new code and flipping a switch, you define multiple variants of a function and let a strategy decide which one runs — gradually shifting traffic, running canary tests, A/B comparisons, or switching at a scheduled time.

Zero external dependencies. Pure Python 3.10+.

Features

  • @evolving decorator — Make any function time-aware with a single line
  • Variant registration — Add new implementations via @func.variant("v2")
  • 4 built-in rollout strategies:
    • GradualStrategy — Linear traffic shift over N days
    • CanaryStrategy — Small % traffic with auto-promote/rollback
    • ABTestStrategy — Even split with comparison reporting
    • ScheduledStrategy — Hard switch at a specific timestamp
  • Automatic fallback — If the new variant throws, falls back to v1
  • Performance tracking — Latency, success rate, call count per variant
  • EvolutionTracker — Persistent JSON Lines log of all evolution events
  • CLI tool (tc) — Inspect evolution history from the terminal

Installation

pip install temporal-code

Quick Start

from temporal_code import evolving

@evolving(start="2026-06-01", duration_days=14)
def rank_results(items):
    """v1: Simple sort."""
    return sorted(items)

@rank_results.variant("v2")
def rank_results_v2(items):
    """v2: ML-powered ranking (gradually takes over in 14 days)."""
    return ml_sort(items)

# Just call it — the strategy picks the variant automatically
results = rank_results(["banana", "apple", "cherry"])

During the 14-day window starting June 1st, traffic gradually shifts from v1 to v2. If v2 raises an exception, v1 handles the request as a fallback.

Strategies

GradualStrategy

Linearly shifts traffic from the old variant to the new one over a configurable duration.

from temporal_code import evolving, GradualStrategy

@evolving(strategy=GradualStrategy(start="2026-06-01", duration_days=7))
def my_func(x):
    return old_logic(x)

@my_func.variant("v2")
def my_func_v2(x):
    return new_logic(x)
Day v1 traffic v2 traffic
0 100% 0%
3 ~57% ~43%
7 0% 100%

CanaryStrategy

Routes a small fixed percentage of traffic to the new variant. Automatically promotes after N successful calls, or rolls back if the success rate drops below a threshold.

from temporal_code import evolving, CanaryStrategy

strategy = CanaryStrategy(
    canary_weight=0.1,         # 10% traffic to new variant
    promote_after=100,         # Decide after 100 calls
    rollback_threshold=0.95,   # Roll back if success < 95%
)

@evolving(strategy=strategy)
def process_payment(amount):
    return legacy_processor(amount)

@process_payment.variant("v2")
def process_payment_v2(amount):
    return new_processor(amount)

# After 100 calls to v2:
# - If success_rate >= 95%: auto-promote v2 to 100%
# - If success_rate < 95%: auto-rollback to v1

ABTestStrategy

Splits traffic evenly (or with custom weights) and collects comparison metrics. Does not auto-promote — you decide based on the report.

from temporal_code import evolving, ABTestStrategy

ab = ABTestStrategy(split=[0.5, 0.5])

@evolving(strategy=ab, name="greeting")
def greet(user):
    return f"Dear {user}, welcome."

@greet.variant("casual")
def greet_casual(user):
    return f"Hey {user}!"

# Run for a while, then check results:
report = ab.report(greet.variants)
# {'variants': [...], 'recommendation': "Recommend 'casual': 100.0% success, 0ms avg"}

ScheduledStrategy

Hard switch at a specific point in time. Before the timestamp, v1 runs; after it, v2 runs.

from temporal_code import scheduled

@scheduled(switch_at="2026-07-01")
def get_pricing(product):
    return {"model": "flat", "price": 99}

@get_pricing.variant("v2")
def get_pricing_v2(product):
    return {"model": "tiered", "base": 49, "premium": 149}

For multi-phase schedules, use the @temporal decorator:

from temporal_code import temporal

@temporal(schedule=[
    ("2026-06-01", "v1"),
    ("2026-07-01", "v2"),
    ("2026-09-01", "v3"),
])
def pricing(item):
    return item.base_price  # v1

EvolutionTracker

Track all evolution events (calls, promotions, rollbacks) to a persistent JSON Lines file:

from pathlib import Path
from temporal_code import EvolutionTracker
from temporal_code.decorators import set_tracker

# Enable persistent tracking
tracker = EvolutionTracker(Path("./evolution_logs"))
set_tracker(tracker)

# All @evolving functions now log to ./evolution_logs/evolution.jsonl
# Query history:
history = tracker.get_history(func_name="rank_results", event_type="call", limit=50)
summary = tracker.summary("rank_results")

Each log entry is a JSON object:

{"event": "call", "function": "rank_results", "variant": "v2", "success": true, "latency_ms": 1.23, "timestamp": "2026-06-05T10:30:00+00:00"}

API Reference

Symbol Type Description
@evolving Decorator Make a function evolve over time
@temporal Decorator Multi-phase scheduled switching
@scheduled Decorator Simple two-phase switch at a timestamp
Variant Class A versioned implementation of a function
VariantResult Dataclass Result of a single variant execution
EvolutionTracker Class Persistent evolution event logger
GradualStrategy Class Linear traffic shift over N days
CanaryStrategy Class Canary deployment with auto-promote/rollback
ABTestStrategy Class A/B split test with reporting
ScheduledStrategy Class Time-based variant switching

License

MIT

Release files for temporal-code 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for temporal-code 0.1.0
File Size Uploaded
temporal_code-0.1.0.tar.gz 16.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for temporal-code 0.1.0
File Interpreter ABI Platform
temporal_code-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 31.0 kB

Release files / temporal_code-0.1.0.tar.gz

Download URL temporal_code-0.1.0.tar.gz
Size 16.8 kB
Tags Source
SHA-256 checksum
How to use checksums
a698e90763681c8b3effcbfe8c5f6d3ad27dc853f79d236edb5414b76fc5cdf4
BLAKE2b-256 checksum
How to use checksums
bd6649125e814d1b3270145d6105c73b7788d5568b1f162ddd955f2e8df1c5b3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.3

Release files / temporal_code-0.1.0-py3-none-any.whl

Download URL temporal_code-0.1.0-py3-none-any.whl
Size 14.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
66374f3251764f6c881caaac874e90b99ed000d49c6da0e849cbdf7d4a30253e
BLAKE2b-256 checksum
How to use checksums
66e56bbfa6645f6f77088442663075a1e7f34ad85450948f88fe8c91619f0baf
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.3

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page