Transparent shadow testing for legacy refactors.
Project description
bilocate 🪞
Transparent shadow testing for legacy refactors.
Refactoring critical, legacy "spaghetti" code is terrifying. Standard shadow testing requires standing up API gateways, duplicating traffic via Kafka, or importing heavy JSON-diffing engines just to run V2 alongside V1. bilocate solves this at the Python function boundary.
You write your new logic, wrap the old function, and let the runtime natively background and compare the execution.
uv add bilocate
The Difference
| Concept | Standard Shadow Testing | bilocate |
|---|---|---|
| Infrastructure | API Gateways, message duplication queues | None. Pure Python decorators. |
| Diffing Engine | Complex JSON serialization / DeepDiff |
Native __eq__ evaluation. |
| Latency Impact | Network hop duplication | Zero. Async naturally backgrounds. |
| Telemetry & Alerts | Custom SDKs (Datadog/Sentry) | Standard library warnings module. |
Usage
You need exactly one primitive: @mimic.
import bilocate
import warnings
# Your shiny, untested V2 logic
def clean_v2_logic(payload):
return new_pydantic_math(payload)
# 1. Wrap the legacy function.
# The system transparently routes the inputs to V2 in the background.
@bilocate.mimic(clean_v2_logic)
def spaghetti_v1_logic(payload):
return legacy_dict_math(payload)
# 2. Call the function normally.
# The user gets the V1 response instantly.
result = spaghetti_v1_logic({"user_id": 123})
# CHECKPOINT:
# If clean_v2_logic returns a different value, or if V2 crashes while V1 succeeds,
# bilocate emits a native RuntimeWarning. The user's execution is completely unaffected.
Core Mechanics
- Native Telemetry:
bilocaterequires absolutely zero configuration. It doesn't ask for a logger or a statsd client. When a mismatch occurs, it emits a standardRuntimeWarning. You can route this to Sentry, Datadog, or your console natively using Python's built-inlogging.captureWarnings(True). - Flawless Error Diffing:
bilocatetreats exceptions as values. If V1 returnsNonebut V2 raises aKeyError,bilocatecleanly intercepts the crash, compares the terminal states, and reports the discrepancy without blowing up the user's stack. - Native Async Backgrounding: If your functions are
async,bilocateautomatically wraps V2 in a fire-and-forgetasyncio.create_task(). V1 returns instantly, and V2 processes seamlessly in the background event loop with zero added latency. - Zero-Dependency Comparisons: No heavy JSON serializers or deep-diffing libraries.
bilocatedelegates diffing purely to Python's native__eq__contract. If you need to compare a legacydictto a V2 object, just define__eq__on your object.
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 bilocate-0.1.0.tar.gz.
File metadata
- Download URL: bilocate-0.1.0.tar.gz
- Upload date:
- Size: 2.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.3 {"installer":{"name":"uv","version":"0.11.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"CachyOS Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a798faa777f0f4d59e8cd55ca8f2741eb8b5cdf36c68ecb890c38fa2405cd6a8
|
|
| MD5 |
23d30db29c151ddc61eeb0af09e747cd
|
|
| BLAKE2b-256 |
012b8de94bc952a72a09fc9f6632ca0418b815950c348c8bc9e058686270c09b
|
File details
Details for the file bilocate-0.1.0-py3-none-any.whl.
File metadata
- Download URL: bilocate-0.1.0-py3-none-any.whl
- Upload date:
- Size: 3.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.3 {"installer":{"name":"uv","version":"0.11.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"CachyOS Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d384f935b4ec3aa77c54c2b41e08638efb01b1b85f38742a4638cce83387a1bb
|
|
| MD5 |
0c3d0418eb9abe6125f84de8cc0bdba0
|
|
| BLAKE2b-256 |
fdb86c7bfa1a37d6c61a9ad51691d374443234efcb04dc60bea2db52784acbad
|