Temporal Code - Time-native programming where function behavior evolves over time
Project description
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
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file temporal_code-0.1.0.tar.gz.
File metadata
- Download URL: temporal_code-0.1.0.tar.gz
- Upload date:
- Size: 16.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a698e90763681c8b3effcbfe8c5f6d3ad27dc853f79d236edb5414b76fc5cdf4
|
|
| MD5 |
1f7a24a5398a2339ef914854f42655d1
|
|
| BLAKE2b-256 |
bd6649125e814d1b3270145d6105c73b7788d5568b1f162ddd955f2e8df1c5b3
|
File details
Details for the file temporal_code-0.1.0-py3-none-any.whl.
File metadata
- Download URL: temporal_code-0.1.0-py3-none-any.whl
- Upload date:
- Size: 14.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
66374f3251764f6c881caaac874e90b99ed000d49c6da0e849cbdf7d4a30253e
|
|
| MD5 |
505b40116a6d5f04d8e9b72e11c98f1c
|
|
| BLAKE2b-256 |
66e56bbfa6645f6f77088442663075a1e7f34ad85450948f88fe8c91619f0baf
|