rudy-ab-test
A lightweight, rule-based feature-flag and A/B test engine for Python.
Define variables with fallback defaults, attach prioritized rules driven by arbitrary context dicts, and evaluate them at runtime — no external services required.
Installation
pip install rudy-ab-test
Quick start
from rudy_ab_test import RuleEngine, Variable, Rule, Condition
engine = RuleEngine()
rule = Rule(
name="premium_model_for_prod",
conditions=[Condition(field="environment", operator="eq", value="prod")],
result="gpt-4",
priority=1,
)
engine.register(Variable(name="model_name", default="gpt-3.5-turbo", rules=[rule]))
result = engine.evaluate("model_name", {"environment": "prod"})
# → "gpt-4"
Core concepts
Condition
A single predicate evaluated against the context dict.
| Field | Type | Description |
|---|---|---|
field |
str |
Key looked up in the context dict |
operator |
str |
Comparison operator (see table below) |
value |
Any |
Right-hand side of the comparison |
Supported operators
| Operator | Meaning |
|---|---|
eq |
context[field] == value |
neq |
context[field] != value |
in |
context[field] in value |
not_in |
context[field] not in value |
gt |
context[field] > value |
gte |
context[field] >= value |
lt |
context[field] < value |
lte |
context[field] <= value |
starts_with |
str(context[field]).startswith(...) |
ends_with |
str(context[field]).endswith(...) |
Rule
A rule fires when all its conditions match. The first matching rule (by descending priority) determines the variable's value.
| Field | Type | Description |
|---|---|---|
name |
str |
Unique identifier (for debugging/logging) |
conditions |
list[Condition] |
All must match (AND logic) |
result |
Any |
Value returned when this rule fires |
priority |
int |
Higher value → evaluated first (default 0) |
Variable
A named configuration point with a default value and an ordered list of rules.
| Field | Type | Description |
|---|---|---|
name |
str |
Variable identifier |
default |
Any |
Returned when no rule matches |
rules |
list[Rule] |
Evaluated in descending priority order |
RuleEngine
Central registry. Stores variables and evaluates them against a context dict.
Usage
Evaluating a single variable
value = engine.evaluate("retriever_provider", context)
Evaluating multiple variables at once
Pass a list of names to get a dict back:
results = engine.evaluate(["retriever_provider", "model_name", "environment"], context)
# → {"retriever_provider": "aws", "model_name": "gpt-3.5-turbo", "environment": "dev"}
Multiple conditions (AND logic)
All conditions in a rule must match for the rule to fire:
rule = Rule(
name="aws_for_application",
conditions=[
Condition(field="system_type", operator="eq", value="application"),
Condition(field="token_hash", operator="starts_with", value="xpto"),
Condition(field="token_hash", operator="ends_with", value="abc123"),
],
result="aws",
priority=1,
)
Priority
Rules are sorted by descending priority on register(). When two rules could match, the one with the highest priority wins:
rule_high = Rule(name="r1", conditions=[...], result="aws", priority=2)
rule_low = Rule(name="r2", conditions=[...], result="bridge", priority=1)
# rule_high is evaluated first
Serialization — export and reload
Variables can be serialized to plain dicts (e.g. to store in a database or config file) and reloaded:
payload = engine.export_variables() # list[dict]
# ... save to DB / JSON file ...
new_engine = RuleEngine()
new_engine.load_variables(payload)
Complete example
from rudy_ab_test import RuleEngine, Variable, Rule, Condition
engine = RuleEngine()
# --- retriever_provider ---
engine.register(Variable(
name="retriever_provider",
default="bridge",
rules=[
Rule(
name="aws_for_privileged_users",
conditions=[
Condition(field="system_type", operator="eq", value="user"),
Condition(field="function", operator="in", value=["SPECIALIST_1", "SUPERINTENDENT"]),
],
result="aws",
priority=2,
),
Rule(
name="aws_for_verified_apps",
conditions=[
Condition(field="system_type", operator="eq", value="application"),
Condition(field="token_hash", operator="starts_with", value="xpto"),
Condition(field="token_hash", operator="ends_with", value="abc123"),
],
result="aws",
priority=1,
),
],
))
# --- model_name ---
engine.register(Variable(
name="model_name",
default="gpt-3.5-turbo",
rules=[
Rule(name="prod_model", conditions=[Condition(field="environment", operator="eq", value="prod")], result="gpt-4", priority=1),
Rule(name="dev_model", conditions=[Condition(field="environment", operator="eq", value="dev")], result="gpt-3.5-turbo", priority=2),
],
))
# Evaluate a privileged user
user_ctx = {"system_type": "user", "function": "SPECIALIST_1", "environment": "dev"}
print(engine.evaluate(["retriever_provider", "model_name"], user_ctx))
# → {"retriever_provider": "aws", "model_name": "gpt-3.5-turbo"}
# Evaluate a standard user
anon_ctx = {"system_type": "user", "function": "JUNIOR_ANALIST", "environment": "dev"}
print(engine.evaluate(["retriever_provider", "model_name"], anon_ctx))
# → {"retriever_provider": "bridge", "model_name": "gpt-3.5-turbo"}
Requirements
- Python ≥ 3.10
License
MIT
Metadata
Release files for rudy-ab-test 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 | Provenance | |
|---|---|---|---|---|
| rudy_ab_test-0.1.0.tar.gz | 6.0 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| rudy_ab_test-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 11.2 kB
Release files / rudy_ab_test-0.1.0.tar.gz
| Download URL | rudy_ab_test-0.1.0.tar.gz |
|---|---|
| Size | 6.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d1a3854fa18dd2a88ed05b4ea2f2c3e0d7a9ab6010f65346805a7e9894555451
|
|
BLAKE2b-256 checksum How to use checksums |
c87ea943257f188bd50ace0baf7ac6fa80edcaa5f309a040945e5f9b2e98279d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.6
|
Release files / rudy_ab_test-0.1.0-py3-none-any.whl
| Download URL | rudy_ab_test-0.1.0-py3-none-any.whl |
|---|---|
| Size | 5.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e649c5b99aabc4dbe5f7c2294427f0c67b07e5fa845b1ee2b5c02f6318bcf32e
|
|
BLAKE2b-256 checksum How to use checksums |
6b4832d3351c913f2e707a9fdc323478970259ce7752d504eabd5abecdb93d34
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.6
|
Security for rudy-ab-test 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.