Context

The EvaluationContext provides attributes for targeting rules and percentage rollouts during flag evaluation. It follows the OpenFeature specification patterns.

Overview

The context is an immutable dataclass that carries information about the current evaluation request. This includes:

  • Targeting key: Primary identifier for consistent hashing in percentage rollouts

  • User attributes: User ID, organization, tenant for user-level targeting

  • Environment info: Environment name, app version for deployment-based rules

  • Custom attributes: Flexible key-value pairs for any targeting logic

  • Request metadata: IP address, user agent, country for request-level targeting

Key Features:

  • Immutable by design (frozen dataclass)

  • Flexible attribute access via get() method

  • Merge support for combining contexts

  • Builder-style methods for creating variations

Quick Example

from litestar_flags import EvaluationContext

# Create a context for a specific user
context = EvaluationContext(
    targeting_key="user-123",
    user_id="user-123",
    organization_id="org-456",
    environment="production",
    attributes={
        "plan": "premium",
        "beta_tester": True,
        "signup_date": "2024-01-15",
    },
)

# Access attributes
plan = context.get("plan")  # "premium"
beta = context.get("beta_tester")  # True

API Reference

Evaluation context for feature flag evaluation.

class litestar_flags.context.EvaluationContext[source]

Bases: object

Immutable context for flag evaluation.

Follows OpenFeature specification patterns. The context provides attributes that can be used for targeting rules and percentage rollouts.

targeting_key

Primary identifier for consistent hashing in percentage rollouts.

user_id

User identifier for user-level targeting.

organization_id

Organization identifier for org-level targeting.

tenant_id

Tenant identifier for multi-tenant applications.

environment

Environment name (e.g., “production”, “staging”).

app_version

Application version for version-based rollouts.

attributes

Custom attributes for flexible targeting rules.

ip_address

Client IP address (can be auto-populated by middleware).

user_agent

Client user agent string.

country

Country code (e.g., “US”, “GB”).

timestamp

Evaluation timestamp for time-based rules.

Example

>>> context = EvaluationContext(
...     targeting_key="user-123",
...     user_id="user-123",
...     attributes={"plan": "premium", "beta_tester": True},
... )
>>> context.get("plan")
'premium'
Parameters:
targeting_key: str | None
user_id: str | None
organization_id: str | None
tenant_id: str | None
environment: str | None
app_version: str | None
attributes: dict[str, Any]
ip_address: str | None
user_agent: str | None
country: str | None
timestamp: datetime
get(key, default=None)[source]

Get attribute by key, checking standard attributes first.

Parameters:
  • key (str) – The attribute key to look up.

  • default (Any) – Default value if attribute is not found.

Return type:

Any

Returns:

The attribute value or the default.

merge(other)[source]

Merge with another context (other takes precedence).

Creates a new context with values from both contexts, where the other context’s values override this context’s values.

Parameters:

other (EvaluationContext) – The context to merge with (takes precedence).

Return type:

EvaluationContext

Returns:

A new merged EvaluationContext.

with_targeting_key(targeting_key)[source]

Create a new context with an updated targeting key.

Parameters:

targeting_key (str) – The new targeting key.

Return type:

EvaluationContext

Returns:

A new EvaluationContext with the updated targeting key.

with_attributes(**kwargs)[source]

Create a new context with additional attributes.

Parameters:

**kwargs (Any) – Additional attributes to add.

Return type:

EvaluationContext

Returns:

A new EvaluationContext with the additional attributes.

__init__(targeting_key=None, user_id=None, organization_id=None, tenant_id=None, environment=None, app_version=None, attributes=<factory>, ip_address=None, user_agent=None, country=None, timestamp=<factory>)
Parameters:
Return type:

None

Creating Contexts

Basic Context

# Minimal context with just a targeting key
context = EvaluationContext(targeting_key="user-123")

# User context with common attributes
context = EvaluationContext(
    targeting_key="user-123",
    user_id="user-123",
    organization_id="org-456",
    environment="production",
)

With Custom Attributes

context = EvaluationContext(
    targeting_key="user-123",
    attributes={
        "plan": "enterprise",
        "feature_tier": 3,
        "enabled_addons": ["analytics", "export"],
        "created_at": "2024-01-01",
    },
)

Request Context

For request-level targeting (often populated by middleware):

context = EvaluationContext(
    targeting_key="user-123",
    ip_address="192.168.1.1",
    user_agent="Mozilla/5.0...",
    country="US",
)

Accessing Attributes

The get() method provides unified access to both standard and custom attributes:

context = EvaluationContext(
    user_id="user-123",
    attributes={"plan": "premium"},
)

# Access standard attributes
user_id = context.get("user_id")  # "user-123"

# Access custom attributes
plan = context.get("plan")  # "premium"

# Default values for missing attributes
tier = context.get("tier", default="free")  # "free"

Modifying Contexts

Since contexts are immutable, modification methods return new instances:

With New Targeting Key

base_context = EvaluationContext(
    user_id="user-123",
    environment="production",
)

# Create a new context with different targeting key
session_context = base_context.with_targeting_key("session-abc")

With Additional Attributes

base_context = EvaluationContext(
    targeting_key="user-123",
    attributes={"plan": "free"},
)

# Add new attributes (original attributes are preserved)
upgraded_context = base_context.with_attributes(
    plan="premium",
    upgraded_at="2024-06-01",
)

Merging Contexts

Merge two contexts, with the second context taking precedence:

default_context = EvaluationContext(
    environment="production",
    attributes={"version": "1.0"},
)

request_context = EvaluationContext(
    targeting_key="user-123",
    user_id="user-123",
    attributes={"source": "api"},
)

# Merge: request_context values override default_context
merged = default_context.merge(request_context)
# Result has: environment="production", targeting_key="user-123",
#             user_id="user-123", attributes={"version": "1.0", "source": "api"}

Integration with Middleware

When using the FeatureFlagsMiddleware, context can be automatically extracted from requests:

from litestar_flags import (
    FeatureFlagsConfig,
    FeatureFlagsPlugin,
    EvaluationContext,
)

def extract_context(request) -> EvaluationContext:
    """Custom context extractor."""
    return EvaluationContext(
        targeting_key=str(request.user.id) if request.user else None,
        user_id=str(request.user.id) if request.user else None,
        ip_address=request.client.host if request.client else None,
        user_agent=request.headers.get("user-agent"),
    )

config = FeatureFlagsConfig(
    backend="memory",
    enable_middleware=True,
    context_extractor=extract_context,
)