Temporal Code
Time-Native Programming for Python
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
@evolvingdecorator — 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 daysCanaryStrategy— Small % traffic with auto-promote/rollbackABTestStrategy— Even split with comparison reportingScheduledStrategy— 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
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)
| File | Size | Uploaded | |
|---|---|---|---|
| temporal_code-0.1.0.tar.gz | 16.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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
|