dataknobs-common Complete API Reference¶
Complete auto-generated API documentation from source code docstrings.
💡 Also see: - Curated Guide - Hand-crafted tutorials and examples - Package Overview - Introduction and getting started - Source Code - View on GitHub
dataknobs_common ¶
Common utilities and base classes for dataknobs packages.
This package provides shared functionality used across all dataknobs packages:
- Exceptions: Unified exception hierarchy with context support
- Expressions: Safe expression evaluation engine with restricted builtins
- Registry: Generic registry pattern for managing named items
- Serialization: Protocols and utilities for to_dict/from_dict patterns
- Retry: Configurable retry execution with backoff strategies
- Transitions: Stateless transition validation for status graphs
- Events: Event bus abstraction for pub/sub messaging
- Testing: Test utilities, markers, and configuration factories
Example
from dataknobs_common import DataknobsError, Registry, serialize
# Use common exceptions
raise DataknobsError("Something went wrong", context={"details": "here"})
# Create a registry
registry = Registry[MyType]("my_registry")
registry.register("key", my_item)
# Serialize objects
data = serialize(my_object)
# Use event bus
from dataknobs_common.events import create_event_bus, Event, EventType
bus = create_event_bus({"backend": "memory"})
Modules:
| Name | Description |
|---|---|
events |
Event bus abstraction for distributed event handling. |
exceptions |
Common exception hierarchy for all dataknobs packages. |
expressions |
Safe expression evaluation engine. |
ratelimit |
Rate limiting abstraction supporting multiple backends. |
registry |
Generic registry pattern for managing named items. |
retry |
Retry utilities for resilient operation execution. |
serialization |
Serialization protocols and utilities for dataknobs packages. |
testing |
Test utilities for dataknobs packages. |
transitions |
Stateless transition validation for declarative status graphs. |
Classes:
| Name | Description |
|---|---|
ExpressionResult |
Result of a safe expression evaluation. |
Event |
An event message for the event bus. |
EventBus |
Abstract event bus protocol supporting multiple backends. |
EventType |
Standard event types for registry and resource changes. |
InMemoryEventBus |
Simple in-memory pub/sub event bus. |
Subscription |
Handle for managing an event subscription. |
ConcurrencyError |
Raised when concurrent operation conflicts occur. |
ConfigurationError |
Raised when configuration is invalid or missing. |
DataknobsError |
Base exception for all dataknobs packages. |
NotFoundError |
Raised when a requested item is not found. |
OperationError |
Raised when an operation fails. |
RateLimitError |
Raised when a rate limit is exceeded. |
ResourceError |
Raised when resource operations fail. |
SerializationError |
Raised when serialization or deserialization fails. |
TimeoutError |
Raised when an operation times out. |
ValidationError |
Raised when validation fails. |
InMemoryRateLimiter |
Sliding-window rate limiter backed by in-memory data structures. |
RateLimit |
A single rate limit rule. |
RateLimiter |
Abstract rate limiter protocol supporting multiple backends. |
RateLimiterConfig |
Configuration for a rate limiter. |
RateLimitStatus |
Current status of a rate limiter bucket. |
BackoffStrategy |
Backoff strategies for retries. |
RetryConfig |
Configuration for retry behavior. |
RetryExecutor |
Executes a callable with retry logic and configurable backoff. |
InvalidTransitionError |
Raised when a status transition is not allowed. |
TransitionValidator |
Stateless validator for declarative transition graphs. |
AsyncRegistry |
Async-safe registry for managing named items. |
CachedRegistry |
Registry with time-based caching support. |
PluginRegistry |
Registry for plugins with factory support and defaults. |
Registry |
Base registry for managing named items with optional metrics. |
Serializable |
Protocol for objects that can be serialized to/from dict. |
Functions:
| Name | Description |
|---|---|
safe_eval |
Evaluate a Python expression string safely. |
safe_eval_value |
Convenience wrapper returning just the value. |
create_event_bus |
Create an event bus from configuration. |
create_rate_limiter |
Create a rate limiter from configuration. |
deserialize |
Deserialize dictionary into an object. |
deserialize_list |
Deserialize a list of dictionaries into objects. |
is_deserializable |
Check if a class is deserializable. |
is_serializable |
Check if an object is serializable. |
serialize |
Serialize an object to dictionary. |
serialize_list |
Serialize a list of objects to list of dictionaries. |
create_test_json_files |
Create test JSON files. |
create_test_markdown_files |
Create test markdown files for ingestion. |
get_test_bot_config |
Get a test bot configuration. |
get_test_rag_config |
Get a test RAG/knowledge base configuration. |
is_chromadb_available |
Check if ChromaDB is available. |
is_faiss_available |
Check if FAISS is available. |
is_ollama_available |
Check if Ollama service is available. |
is_ollama_model_available |
Check if a specific Ollama model is available. |
is_package_available |
Check if a Python package is available. |
is_redis_available |
Check if Redis service is available. |
Attributes:
| Name | Type | Description |
|---|---|---|
SAFE_BUILTINS |
dict[str, Any]
|
Builtins allowlist shared by all expression contexts. |
YAML_ALIASES |
dict[str, Any]
|
Common aliases for YAML/JSON boolean and null literals. |
Attributes¶
SAFE_BUILTINS
module-attribute
¶
SAFE_BUILTINS: dict[str, Any] = {
"str": str,
"int": int,
"float": float,
"bool": bool,
"list": list,
"dict": dict,
"tuple": tuple,
"set": set,
"len": len,
"min": min,
"max": max,
"abs": abs,
"round": round,
"sorted": sorted,
"isinstance": isinstance,
"enumerate": enumerate,
"range": range,
"zip": zip,
"True": True,
"False": False,
"None": None,
}
Builtins allowlist shared by all expression contexts.
Explicitly excludes: exec, eval, __import__, open,
getattr, setattr, delattr, globals, locals,
compile, breakpoint, __builtins__ passthrough.
YAML_ALIASES
module-attribute
¶
Common aliases for YAML/JSON boolean and null literals.
Included in expression scope so that config-authored expressions
can use true/false/null (YAML style) alongside Python's
True/False/None.
Note: scope variables with the same name override these aliases (scope is applied after YAML_ALIASES).
Classes¶
ExpressionResult
dataclass
¶
Result of a safe expression evaluation.
Attributes:
| Name | Type | Description |
|---|---|---|
value |
Any
|
The evaluated result (native Python type). |
success |
bool
|
Whether evaluation succeeded. |
error |
str | None
|
Exception message if evaluation failed. |
Event
dataclass
¶
Event(
type: EventType,
topic: str,
payload: dict[str, Any] = dict(),
timestamp: datetime = (lambda: datetime.now(timezone.utc))(),
event_id: str = (lambda: str(uuid.uuid4()))(),
source: str | None = None,
correlation_id: str | None = None,
metadata: dict[str, Any] = dict(),
)
An event message for the event bus.
Events are immutable messages that represent something that happened. They contain a type, topic, payload, and metadata.
Attributes:
| Name | Type | Description |
|---|---|---|
type |
EventType
|
The type of event (created, updated, deleted, etc.) |
topic |
str
|
The topic/channel this event belongs to (e.g., "registry:bots") |
payload |
dict[str, Any]
|
The event data as a dictionary |
timestamp |
datetime
|
When the event was created (defaults to now) |
event_id |
str
|
Unique identifier for this event (auto-generated) |
source |
str | None
|
Optional identifier for the event source |
correlation_id |
str | None
|
Optional ID to correlate related events |
metadata |
dict[str, Any]
|
Additional metadata for the event |
Example
Methods:
| Name | Description |
|---|---|
to_dict |
Convert event to dictionary for serialization. |
from_dict |
Create event from dictionary. |
with_correlation |
Create a new event with a correlation ID. |
Functions¶
to_dict ¶
Convert event to dictionary for serialization.
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
Dictionary representation with ISO timestamp and string enum. |
Source code in packages/common/src/dataknobs_common/events/types.py
from_dict
classmethod
¶
Create event from dictionary.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
dict[str, Any]
|
Dictionary with event data |
required |
Returns:
| Type | Description |
|---|---|
Event
|
Event instance |
Source code in packages/common/src/dataknobs_common/events/types.py
with_correlation ¶
Create a new event with a correlation ID.
Useful for tracking related events through a workflow.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
correlation_id
|
str
|
The correlation ID to set |
required |
Returns:
| Type | Description |
|---|---|
Event
|
New Event with the correlation ID set |
Source code in packages/common/src/dataknobs_common/events/types.py
EventBus ¶
Bases: Protocol
Abstract event bus protocol supporting multiple backends.
The EventBus provides a publish-subscribe interface for distributing events across components. Different implementations support various deployment scenarios:
- InMemoryEventBus: Single process, no external dependencies
- PostgresEventBus: Uses LISTEN/NOTIFY, works on local and RDS
- RedisEventBus: Redis pub/sub, works with ElastiCache
All implementations follow this protocol, allowing configuration-driven backend selection without code changes.
Example
from dataknobs_common.events import create_event_bus, Event, EventType
# Create event bus from config
bus = create_event_bus({"backend": "memory"})
await bus.connect()
# Subscribe to events
async def handler(event: Event) -> None:
print(f"Got {event.type} on {event.topic}")
subscription = await bus.subscribe("registry:bots", handler)
# Publish an event
await bus.publish("registry:bots", Event(
type=EventType.CREATED,
topic="registry:bots",
payload={"bot_id": "new-bot"}
))
# Cleanup
await subscription.cancel()
await bus.close()
Pattern Matching
Some backends support wildcard patterns for subscriptions: - "registry:" matches "registry:bots", "registry:users", etc. - ":created" matches "bots:created", "users:created", etc. Check backend documentation for supported patterns.
Methods:
| Name | Description |
|---|---|
connect |
Initialize the event bus connection. |
close |
Close connections and cleanup resources. |
publish |
Publish an event to a topic. |
subscribe |
Subscribe to events on a topic. |
Functions¶
connect
async
¶
Initialize the event bus connection.
Called before the bus is used. Should be idempotent.
close
async
¶
Close connections and cleanup resources.
Should cancel all active subscriptions and release resources.
publish
async
¶
Publish an event to a topic.
The event will be delivered to all subscribers of the topic. Delivery semantics depend on the backend: - Memory: Synchronous, in-process delivery - Postgres: Fire-and-forget via NOTIFY - Redis: Fire-and-forget via PUBLISH
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
topic
|
str
|
The topic/channel to publish to |
required |
event
|
Event
|
The event to publish |
required |
Source code in packages/common/src/dataknobs_common/events/bus.py
subscribe
async
¶
subscribe(
topic: str, handler: Callable[[Event], Any], pattern: str | None = None
) -> Subscription
Subscribe to events on a topic.
The handler will be called for each event published to the topic. Handlers should be async functions that accept an Event.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
topic
|
str
|
The topic to subscribe to |
required |
handler
|
Callable[[Event], Any]
|
Async function to call with each event |
required |
pattern
|
str | None
|
Optional pattern for wildcard matching (backend-specific) |
None
|
Returns:
| Type | Description |
|---|---|
Subscription
|
Subscription handle that can be used to cancel the subscription |
Source code in packages/common/src/dataknobs_common/events/bus.py
EventType ¶
Bases: Enum
Standard event types for registry and resource changes.
These types represent common lifecycle events for managed resources.
Example
InMemoryEventBus ¶
Simple in-memory pub/sub event bus.
This implementation is suitable for: - Single-process applications - Development and testing - Scenarios where events don't need to cross process boundaries
Features: - Fast, synchronous delivery within the same process - Support for wildcard patterns using fnmatch - Thread-safe using asyncio.Lock
Limitations: - Events are not persisted - Does not work across multiple processes or machines - Events are lost if there are no subscribers
Example
from dataknobs_common.events import InMemoryEventBus, Event, EventType
bus = InMemoryEventBus()
await bus.connect()
events_received = []
async def handler(event: Event) -> None:
events_received.append(event)
# Subscribe with pattern matching
await bus.subscribe("registry:*", handler, pattern="registry:*")
# Publish
await bus.publish("registry:bots", Event(
type=EventType.CREATED,
topic="registry:bots",
payload={"bot_id": "test"}
))
assert len(events_received) == 1
await bus.close()
Initialize the in-memory event bus.
Methods:
| Name | Description |
|---|---|
connect |
Initialize the event bus. |
close |
Close the event bus and cancel all subscriptions. |
publish |
Publish an event to a topic. |
subscribe |
Subscribe to events on a topic. |
Attributes:
| Name | Type | Description |
|---|---|---|
subscription_count |
int
|
Get the number of active subscriptions. |
Source code in packages/common/src/dataknobs_common/events/memory.py
Attributes¶
Functions¶
connect
async
¶
Initialize the event bus.
For in-memory bus, this just sets the connected flag.
Source code in packages/common/src/dataknobs_common/events/memory.py
close
async
¶
Close the event bus and cancel all subscriptions.
Source code in packages/common/src/dataknobs_common/events/memory.py
publish
async
¶
Publish an event to a topic.
Delivers the event to all subscribers of the topic and any pattern subscribers that match.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
topic
|
str
|
The topic to publish to |
required |
event
|
Event
|
The event to publish |
required |
Source code in packages/common/src/dataknobs_common/events/memory.py
subscribe
async
¶
subscribe(
topic: str, handler: Callable[[Event], Any], pattern: str | None = None
) -> Subscription
Subscribe to events on a topic.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
topic
|
str
|
The topic to subscribe to |
required |
handler
|
Callable[[Event], Any]
|
Function to call with each event |
required |
pattern
|
str | None
|
Optional wildcard pattern (uses fnmatch syntax) |
None
|
Returns:
| Type | Description |
|---|---|
Subscription
|
Subscription handle for managing the subscription |
Source code in packages/common/src/dataknobs_common/events/memory.py
Subscription
dataclass
¶
Subscription(
subscription_id: str,
topic: str,
handler: Any,
pattern: str | None = None,
created_at: datetime = (lambda: datetime.now(timezone.utc))(),
_cancel_callback: Any = None,
)
Handle for managing an event subscription.
Subscriptions are returned when subscribing to events and can be used to cancel the subscription later.
Attributes:
| Name | Type | Description |
|---|---|---|
subscription_id |
str
|
Unique identifier for this subscription |
topic |
str
|
The topic pattern this subscription is for |
handler |
Any
|
Reference to the handler function |
pattern |
str | None
|
Optional wildcard pattern if using pattern matching |
created_at |
datetime
|
When the subscription was created |
Example
Methods:
| Name | Description |
|---|---|
cancel |
Cancel this subscription. |
__repr__ |
String representation. |
ConcurrencyError ¶
ConcurrencyError(
message: str,
context: Dict[str, Any] | None = None,
details: Dict[str, Any] | None = None,
)
Bases: DataknobsError
Raised when concurrent operation conflicts occur.
Use this exception for concurrency-related failures including: - Lock acquisition failures - Transaction conflicts - Race conditions - Optimistic locking failures
Example
Source code in packages/common/src/dataknobs_common/exceptions.py
ConfigurationError ¶
ConfigurationError(
message: str,
context: Dict[str, Any] | None = None,
details: Dict[str, Any] | None = None,
)
Bases: DataknobsError
Raised when configuration is invalid or missing.
Use this exception for configuration-related errors including: - Missing required configuration - Invalid configuration values - Configuration file not found - Circular references in configuration
Example
Source code in packages/common/src/dataknobs_common/exceptions.py
DataknobsError ¶
DataknobsError(
message: str,
context: Dict[str, Any] | None = None,
details: Dict[str, Any] | None = None,
)
Bases: Exception
Base exception for all dataknobs packages.
This is the root exception that all dataknobs packages should extend. It supports optional context data for rich error information, making debugging and error handling more effective.
Attributes:
| Name | Type | Description |
|---|---|---|
context |
Dictionary containing contextual information about the error |
|
details |
Alias for context (FSM-style compatibility) |
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
message
|
str
|
Human-readable error message |
required |
context
|
Dict[str, Any] | None
|
Optional dictionary with error context (field names, IDs, etc.) |
None
|
details
|
Dict[str, Any] | None
|
Alternative to context (both are supported for compatibility) |
None
|
Example
Initialize the exception with optional context.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
message
|
str
|
Error message |
required |
context
|
Dict[str, Any] | None
|
Optional context dictionary |
None
|
details
|
Dict[str, Any] | None
|
Optional details dictionary (merged with context) |
None
|
Source code in packages/common/src/dataknobs_common/exceptions.py
Functions¶
NotFoundError ¶
NotFoundError(
message: str,
context: Dict[str, Any] | None = None,
details: Dict[str, Any] | None = None,
)
Bases: DataknobsError
Raised when a requested item is not found.
Use this exception when looking up items by ID, name, or key and they don't exist. Common scenarios include: - Record not found in database - Configuration key not found - File not found - Resource not registered
Example
Source code in packages/common/src/dataknobs_common/exceptions.py
OperationError ¶
OperationError(
message: str,
context: Dict[str, Any] | None = None,
details: Dict[str, Any] | None = None,
)
Bases: DataknobsError
Raised when an operation fails.
Use this exception for general operation failures that don't fit other categories. Common scenarios include: - Database operation failures - File I/O errors - Network operation failures - State transition errors
Example
Source code in packages/common/src/dataknobs_common/exceptions.py
RateLimitError ¶
RateLimitError(
message: str = "Rate limit exceeded",
retry_after: float | None = None,
context: Dict[str, Any] | None = None,
details: Dict[str, Any] | None = None,
)
Bases: OperationError
Raised when a rate limit is exceeded.
Use this exception when an operation cannot proceed because a rate limit
has been reached. Includes an optional retry_after hint indicating
how many seconds the caller should wait before retrying.
Attributes:
| Name | Type | Description |
|---|---|---|
retry_after |
Optional number of seconds to wait before retrying. |
Example
Initialize the rate limit error.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
message
|
str
|
Error message. |
'Rate limit exceeded'
|
retry_after
|
float | None
|
Optional seconds to wait before retrying. |
None
|
context
|
Dict[str, Any] | None
|
Optional context dictionary. |
None
|
details
|
Dict[str, Any] | None
|
Optional details dictionary (merged with context). |
None
|
Source code in packages/common/src/dataknobs_common/exceptions.py
Functions¶
ResourceError ¶
ResourceError(
message: str,
context: Dict[str, Any] | None = None,
details: Dict[str, Any] | None = None,
)
Bases: DataknobsError
Raised when resource operations fail.
Use this exception for resource management failures including: - Resource acquisition failures - Connection errors - Resource pool exhaustion - Timeout errors
Example
Source code in packages/common/src/dataknobs_common/exceptions.py
SerializationError ¶
SerializationError(
message: str,
context: Dict[str, Any] | None = None,
details: Dict[str, Any] | None = None,
)
Bases: DataknobsError
Raised when serialization or deserialization fails.
Use this exception for data format conversion errors including: - JSON encoding/decoding failures - Invalid data format - Schema mismatch - Type conversion errors
Example
Source code in packages/common/src/dataknobs_common/exceptions.py
TimeoutError ¶
TimeoutError(
message: str,
context: Dict[str, Any] | None = None,
details: Dict[str, Any] | None = None,
)
Bases: DataknobsError
Raised when an operation times out.
Use this exception when operations exceed their time limit including: - Connection timeouts - Query timeouts - Resource acquisition timeouts - Operation execution timeouts
Example
Source code in packages/common/src/dataknobs_common/exceptions.py
ValidationError ¶
ValidationError(
message: str,
context: Dict[str, Any] | None = None,
details: Dict[str, Any] | None = None,
)
Bases: DataknobsError
Raised when validation fails.
Use this exception when data or configuration fails validation checks. Common scenarios include: - Invalid input data - Schema validation failures - Constraint violations - Type mismatches
Example
Source code in packages/common/src/dataknobs_common/exceptions.py
InMemoryRateLimiter ¶
Sliding-window rate limiter backed by in-memory data structures.
This implementation is suitable for: - Single-process applications - Development and testing - Scenarios where rate limiting does not need to cross process boundaries
Features:
- Sliding window log algorithm for accurate rate tracking
- Per-category rate configuration with fallback to default rates
- Weighted acquire support
- Non-blocking (try_acquire) and blocking (acquire) modes
- Thread-safe using asyncio.Lock
Limitations:
- State is not persisted; restarting the process resets all counters
- Does not work across multiple processes or machines
- For distributed rate limiting, use PyrateRateLimiter with a
Redis or PostgreSQL bucket
Example
from dataknobs_common.ratelimit import InMemoryRateLimiter, RateLimiterConfig, RateLimit
config = RateLimiterConfig(
default_rates=[RateLimit(limit=10, interval=60)],
categories={
"api_write": [RateLimit(limit=5, interval=60)],
},
)
limiter = InMemoryRateLimiter(config)
# Non-blocking check
if await limiter.try_acquire("api_write"):
await make_api_call()
# Blocking — waits until capacity is available
await limiter.acquire("api_read")
await make_api_call()
Initialize the in-memory rate limiter.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
RateLimiterConfig
|
Rate limiter configuration with default rates and optional per-category overrides. |
required |
Methods:
| Name | Description |
|---|---|
try_acquire |
Attempt to acquire capacity without blocking. |
acquire |
Acquire capacity, blocking until available. |
get_status |
Get the current status of a rate limiter bucket. |
reset |
Reset rate limiter state. |
close |
Release resources. |
Source code in packages/common/src/dataknobs_common/ratelimit/memory.py
Functions¶
try_acquire
async
¶
Attempt to acquire capacity without blocking.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Category name. Uses category-specific rates if configured, otherwise falls back to default rates. |
'default'
|
weight
|
int
|
Weight of the operation (default 1). |
1
|
Returns:
| Type | Description |
|---|---|
bool
|
True if the acquire succeeded, False if the rate limit would |
bool
|
be exceeded. |
Source code in packages/common/src/dataknobs_common/ratelimit/memory.py
acquire
async
¶
Acquire capacity, blocking until available.
Polls at 50 ms intervals until capacity is available or the timeout is exceeded.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Category name. |
'default'
|
weight
|
int
|
Weight of the operation (default 1). |
1
|
timeout
|
float | None
|
Maximum seconds to wait. |
None
|
Raises:
| Type | Description |
|---|---|
TimeoutError
|
If the timeout is exceeded before capacity becomes available. |
Source code in packages/common/src/dataknobs_common/ratelimit/memory.py
get_status
async
¶
Get the current status of a rate limiter bucket.
Reports against the tightest (smallest limit) applicable rate.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Category name. |
'default'
|
Returns:
| Type | Description |
|---|---|
RateLimitStatus
|
Current status including count, limit, remaining capacity, |
RateLimitStatus
|
and time until the oldest entry expires. |
Source code in packages/common/src/dataknobs_common/ratelimit/memory.py
reset
async
¶
Reset rate limiter state.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str | None
|
Category to reset. If |
None
|
Source code in packages/common/src/dataknobs_common/ratelimit/memory.py
close
async
¶
Release resources.
For the in-memory implementation this is a no-op, but it
satisfies the RateLimiter protocol.
RateLimit
dataclass
¶
A single rate limit rule.
Defines the maximum number of operations (or total weight) allowed within a time interval.
Attributes:
| Name | Type | Description |
|---|---|---|
limit |
int
|
Maximum operations (or total weight) per interval. |
interval |
float
|
Window duration in seconds. |
Example
RateLimiter ¶
Bases: Protocol
Abstract rate limiter protocol supporting multiple backends.
The RateLimiter provides both blocking and non-blocking rate limiting with per-category rate configuration. Different implementations support various deployment scenarios:
- InMemoryRateLimiter: Single process, no external dependencies
- PyrateRateLimiter: Wraps pyrate-limiter for distributed backends (Redis, PostgreSQL, SQLite)
All implementations follow this protocol, allowing configuration-driven backend selection without code changes.
Example
from dataknobs_common.ratelimit import create_rate_limiter
limiter = create_rate_limiter({
"default_rates": [{"limit": 100, "interval": 60}],
"categories": {
"api_write": {"rates": [{"limit": 10, "interval": 60}]},
},
})
# Non-blocking
if await limiter.try_acquire("api_write"):
await make_api_call()
# Blocking with timeout
await limiter.acquire("api_read", timeout=5.0)
Methods:
| Name | Description |
|---|---|
acquire |
Acquire capacity, blocking until available. |
try_acquire |
Attempt to acquire capacity without blocking. |
get_status |
Get the current status of a rate limiter bucket. |
reset |
Reset rate limiter state. |
close |
Release resources held by the rate limiter. |
Functions¶
acquire
async
¶
Acquire capacity, blocking until available.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Category name for rate lookup. |
'default'
|
weight
|
int
|
Weight of the operation (default 1). |
1
|
timeout
|
float | None
|
Maximum seconds to wait. |
None
|
Raises:
| Type | Description |
|---|---|
TimeoutError
|
If the timeout is exceeded. |
Source code in packages/common/src/dataknobs_common/ratelimit/limiter.py
try_acquire
async
¶
Attempt to acquire capacity without blocking.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Category name for rate lookup. |
'default'
|
weight
|
int
|
Weight of the operation (default 1). |
1
|
Returns:
| Type | Description |
|---|---|
bool
|
True if the acquire succeeded, False otherwise. |
Source code in packages/common/src/dataknobs_common/ratelimit/limiter.py
get_status
async
¶
Get the current status of a rate limiter bucket.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Category name. |
'default'
|
Returns:
| Type | Description |
|---|---|
RateLimitStatus
|
Current status of the bucket. |
reset
async
¶
Reset rate limiter state.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str | None
|
Category to reset. If |
None
|
RateLimiterConfig
dataclass
¶
RateLimiterConfig(
default_rates: list[RateLimit],
categories: dict[str, list[RateLimit]] = dict(),
)
Configuration for a rate limiter.
Supports per-category rate overrides. When acquire() is called
with a category name, rates are looked up in categories first;
if the category is not found, default_rates are used.
Attributes:
| Name | Type | Description |
|---|---|---|
default_rates |
list[RateLimit]
|
Fallback rates applied when a category has no specific configuration. |
categories |
dict[str, list[RateLimit]]
|
Per-category rate overrides mapping category names to their rate lists. |
Example
RateLimitStatus
dataclass
¶
Current status of a rate limiter bucket.
Attributes:
| Name | Type | Description |
|---|---|---|
name |
str
|
Category or bucket name. |
current_count |
int
|
Number of operations (total weight) in the current window. |
limit |
int
|
Maximum allowed from the tightest applicable rate. |
remaining |
int
|
Operations remaining before the limit is reached. |
reset_after |
float
|
Seconds until the oldest entry expires and capacity is freed. |
Example
BackoffStrategy ¶
Bases: Enum
Backoff strategies for retries.
Attributes:
| Name | Type | Description |
|---|---|---|
FIXED |
Fixed delay between retries. |
|
LINEAR |
Delay increases linearly with each attempt. |
|
EXPONENTIAL |
Delay doubles (or multiplies by backoff_multiplier) with each attempt. |
|
JITTER |
Exponential backoff with random jitter applied. |
|
DECORRELATED |
Decorrelated jitter: each delay is random between initial_delay and 3x previous delay. |
Attributes¶
LINEAR
class-attribute
instance-attribute
¶
Delay increases linearly with each attempt.
EXPONENTIAL
class-attribute
instance-attribute
¶
Delay doubles (or multiplies by backoff_multiplier) with each attempt.
JITTER
class-attribute
instance-attribute
¶
Exponential backoff with random jitter applied.
DECORRELATED
class-attribute
instance-attribute
¶
Decorrelated jitter: each delay is random between initial_delay and 3x previous delay.
RetryConfig
dataclass
¶
RetryConfig(
max_attempts: int = 3,
initial_delay: float = 1.0,
max_delay: float = 60.0,
backoff_strategy: BackoffStrategy = BackoffStrategy.EXPONENTIAL,
backoff_multiplier: float = 2.0,
jitter_range: float = 0.1,
retry_on_exceptions: list[type] | None = None,
retry_on_result: Callable[[Any], bool] | None = None,
on_retry: Callable[[int, Exception], None] | None = None,
on_failure: Callable[[Exception], None] | None = None,
)
Configuration for retry behavior.
Attributes:
| Name | Type | Description |
|---|---|---|
max_attempts |
int
|
Maximum number of execution attempts (including the first). |
initial_delay |
float
|
Base delay in seconds before the first retry. |
max_delay |
float
|
Upper bound on delay in seconds. |
backoff_strategy |
BackoffStrategy
|
Algorithm for computing delay between retries. |
backoff_multiplier |
float
|
Multiplier for exponential and jitter strategies. |
jitter_range |
float
|
Fractional jitter range for the JITTER strategy (e.g. 0.1 = ±10%). |
retry_on_exceptions |
list[type] | None
|
If set, only retry when the exception is an instance of one of these types. Other exceptions propagate immediately. |
retry_on_result |
Callable[[Any], bool] | None
|
If set, called with the result value. Return True to trigger a retry (e.g. to retry on empty or sentinel results). |
on_retry |
Callable[[int, Exception], None] | None
|
Hook called before each retry sleep with (attempt_number, exception). |
on_failure |
Callable[[Exception], None] | None
|
Hook called when all attempts are exhausted with the final exception. |
RetryExecutor ¶
Executes a callable with retry logic and configurable backoff.
Supports both sync and async callables. Sync callables are invoked directly; async callables are awaited.
Example
Methods:
| Name | Description |
|---|---|
execute |
Execute a callable with retry logic. |
Source code in packages/common/src/dataknobs_common/retry.py
Functions¶
execute
async
¶
Execute a callable with retry logic.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
func
|
Callable[..., Any]
|
The callable to execute. May be sync or async. |
required |
*args
|
Any
|
Positional arguments forwarded to func. |
()
|
**kwargs
|
Any
|
Keyword arguments forwarded to func. |
{}
|
Returns:
| Type | Description |
|---|---|
Any
|
The return value of func on a successful attempt. |
Raises:
| Type | Description |
|---|---|
Exception
|
The exception from the final failed attempt, or any non-retryable exception immediately. |
Source code in packages/common/src/dataknobs_common/retry.py
InvalidTransitionError ¶
InvalidTransitionError(
entity: str,
current_status: str,
target_status: str,
allowed: set[str] | None = None,
)
Bases: OperationError
Raised when a status transition is not allowed.
Attributes:
| Name | Type | Description |
|---|---|---|
entity |
Name of the entity or transition graph (e.g. |
|
current_status |
The current status that was being transitioned from. |
|
target_status |
The target status that was rejected. |
|
allowed |
The set of statuses that are valid targets from |
Source code in packages/common/src/dataknobs_common/transitions.py
TransitionValidator ¶
Stateless validator for declarative transition graphs.
Declares which status transitions are allowed and validates proposed transitions. Does not manage or store state — the caller owns the current status.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Human-readable name for this transition graph, used in
error messages (e.g. |
required |
transitions
|
dict[str, set[str]]
|
Mapping from each status to the set of statuses it may transition to. Statuses that appear only as targets (not as keys) are implicitly terminal (no outgoing transitions). |
required |
Example
ORDER = TransitionValidator("order", {
"draft": {"submitted"},
"submitted": {"approved", "rejected"},
"approved": {"shipped"},
"shipped": {"delivered"},
"rejected": set(),
"delivered": set(),
})
ORDER.validate("draft", "submitted") # ok
ORDER.validate("shipped", "draft") # raises InvalidTransitionError
Methods:
| Name | Description |
|---|---|
validate |
Validate a proposed transition. |
is_valid |
Check whether a transition is allowed without raising. |
get_reachable |
Compute all statuses reachable from a given status (transitive closure). |
Attributes:
| Name | Type | Description |
|---|---|---|
name |
str
|
The name of this transition graph. |
allowed_transitions |
dict[str, set[str]]
|
Return a copy of the full transition graph. |
statuses |
set[str]
|
Return all known statuses (sources and targets). |
Source code in packages/common/src/dataknobs_common/transitions.py
Attributes¶
allowed_transitions
property
¶
Return a copy of the full transition graph.
Functions¶
validate ¶
Validate a proposed transition.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
current_status
|
str | None
|
The current status. If |
required |
target_status
|
str
|
The desired target status. |
required |
Raises:
| Type | Description |
|---|---|
InvalidTransitionError
|
If the transition is not allowed. |
Source code in packages/common/src/dataknobs_common/transitions.py
is_valid ¶
Check whether a transition is allowed without raising.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
current_status
|
str | None
|
The current status. If |
required |
target_status
|
str
|
The desired target status. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
|
bool
|
|
Source code in packages/common/src/dataknobs_common/transitions.py
get_reachable ¶
Compute all statuses reachable from a given status (transitive closure).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
from_status
|
str
|
The starting status. |
required |
Returns:
| Type | Description |
|---|---|
set[str]
|
Set of all statuses reachable via one or more transitions. |
set[str]
|
Does not include |
Raises:
| Type | Description |
|---|---|
InvalidTransitionError
|
If |
Source code in packages/common/src/dataknobs_common/transitions.py
AsyncRegistry ¶
Bases: Generic[T]
Async-safe registry for managing named items.
Similar to Registry but uses asyncio locks for async-safe operations. Use this when working in async contexts.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Registry name |
required |
enable_metrics
|
bool
|
Enable metrics tracking |
False
|
Example
registry = AsyncRegistryTool await registry.register("tool1", my_tool) tool = await registry.get("tool1")
Initialize async registry.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Registry name |
required |
enable_metrics
|
bool
|
Enable metrics tracking |
False
|
Methods:
| Name | Description |
|---|---|
register |
Register an item by key. |
unregister |
Unregister and return an item. |
get |
Get an item by key. |
get_optional |
Get an item, returning None if not found. |
has |
Check if item exists. |
list_keys |
List all registered keys. |
list_items |
List all registered items. |
items |
Get all key-item pairs. |
count |
Get count of registered items. |
clear |
Clear all items. |
get_metrics |
Get registration metrics. |
__len__ |
Get number of registered items using len(). |
__contains__ |
Check if item exists using 'in' operator. |
__iter__ |
Iterate over registered items. |
Attributes:
| Name | Type | Description |
|---|---|---|
name |
str
|
Get registry name. |
Source code in packages/common/src/dataknobs_common/registry.py
Attributes¶
Functions¶
register
async
¶
register(
key: str,
item: T,
metadata: Dict[str, Any] | None = None,
allow_overwrite: bool = False,
) -> None
Register an item by key.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
Unique identifier |
required |
item
|
T
|
Item to register |
required |
metadata
|
Dict[str, Any] | None
|
Optional metadata |
None
|
allow_overwrite
|
bool
|
Allow overwriting existing items |
False
|
Raises:
| Type | Description |
|---|---|
OperationError
|
If item exists and allow_overwrite is False |
Source code in packages/common/src/dataknobs_common/registry.py
unregister
async
¶
Unregister and return an item.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
Key to unregister |
required |
Returns:
| Type | Description |
|---|---|
T
|
The unregistered item |
Raises:
| Type | Description |
|---|---|
NotFoundError
|
If item not found |
Source code in packages/common/src/dataknobs_common/registry.py
get
async
¶
Get an item by key.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
Key to retrieve |
required |
Returns:
| Type | Description |
|---|---|
T
|
The registered item |
Raises:
| Type | Description |
|---|---|
NotFoundError
|
If item not found |
Source code in packages/common/src/dataknobs_common/registry.py
get_optional
async
¶
Get an item, returning None if not found.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
Key to retrieve |
required |
Returns:
| Type | Description |
|---|---|
T | None
|
The item or None |
Source code in packages/common/src/dataknobs_common/registry.py
has
async
¶
Check if item exists.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
Key to check |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if exists |
list_keys
async
¶
List all registered keys.
Returns:
| Type | Description |
|---|---|
List[str]
|
List of keys |
list_items
async
¶
List all registered items.
Returns:
| Type | Description |
|---|---|
List[T]
|
List of items |
items
async
¶
Get all key-item pairs.
Returns:
| Type | Description |
|---|---|
List[tuple[str, T]]
|
List of (key, item) tuples |
count
async
¶
Get count of registered items.
Returns:
| Type | Description |
|---|---|
int
|
Number of items |
clear
async
¶
get_metrics
async
¶
Get registration metrics.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str | None
|
Optional specific key |
None
|
Returns:
| Type | Description |
|---|---|
Dict[str, Any]
|
Metrics dictionary |
Source code in packages/common/src/dataknobs_common/registry.py
__len__ ¶
__contains__ ¶
Check if item exists using 'in' operator.
CachedRegistry ¶
Bases: Registry[T]
Registry with time-based caching support.
Extends the base registry with caching capabilities. Items can be retrieved from cache with automatic expiration and refresh based on TTL. Implements LRU eviction when cache size exceeds limits.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Registry name |
required |
cache_ttl
|
int
|
Cache time-to-live in seconds (default: 300) |
300
|
max_cache_size
|
int
|
Maximum number of cached items (default: 1000) |
1000
|
Example
Initialize cached registry.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Registry name |
required |
cache_ttl
|
int
|
Time-to-live for cached items in seconds |
300
|
max_cache_size
|
int
|
Maximum cache size before eviction |
1000
|
Methods:
| Name | Description |
|---|---|
get_cached |
Get item from cache with automatic refresh. |
invalidate_cache |
Invalidate cache for a key or all keys. |
get_cache_stats |
Get cache statistics. |
Source code in packages/common/src/dataknobs_common/registry.py
Functions¶
get_cached ¶
Get item from cache with automatic refresh.
If item exists in cache and is not expired, returns cached version. Otherwise, calls factory to create new item and caches it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
Cache key |
required |
factory
|
Callable[[], T]
|
Callable that creates the item if not cached |
required |
force_refresh
|
bool
|
Force refresh even if cached |
False
|
Returns:
| Type | Description |
|---|---|
T
|
Cached or newly created item |
Source code in packages/common/src/dataknobs_common/registry.py
invalidate_cache ¶
Invalidate cache for a key or all keys.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str | None
|
Specific key to invalidate, or None to invalidate all |
None
|
Example
Source code in packages/common/src/dataknobs_common/registry.py
get_cache_stats ¶
Get cache statistics.
Returns:
| Type | Description |
|---|---|
Dict[str, Any]
|
Dictionary with cache statistics |
Source code in packages/common/src/dataknobs_common/registry.py
PluginRegistry ¶
PluginRegistry(
name: str,
default_factory: type[T] | Callable[..., T] | None = None,
validate_type: type | None = None,
)
Bases: Generic[T]
Registry for plugins with factory support and defaults.
A specialized registry pattern for managing plugins (adapters, handlers, providers, etc.) that supports: - Class or factory function registration - Lazy instantiation with configuration - Default fallback when plugin not found - Instance caching - Type validation
This pattern is useful when you need to: - Register different implementations of an interface - Create instances on-demand with configuration - Provide graceful fallbacks for unregistered keys
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Registry name |
required |
default_factory
|
type[T] | Callable[..., T] | None
|
Default factory to use when key not found |
None
|
Example
from dataknobs_common.registry import PluginRegistry
# Define base class
class Handler:
def __init__(self, name: str, config: dict):
self.name = name
self.config = config
class DefaultHandler(Handler):
pass
class CustomHandler(Handler):
pass
# Create registry with default
registry = PluginRegistry[Handler]("handlers", default_factory=DefaultHandler)
# Register plugins
registry.register("custom", CustomHandler)
# Get instances
handler = registry.get("custom", config={"timeout": 30})
default = registry.get("unknown", config={}) # Uses default
With async factories
Initialize plugin registry.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Registry name for identification |
required |
default_factory
|
type[T] | Callable[..., T] | None
|
Default class or factory to use when key not found |
None
|
validate_type
|
type | None
|
Optional base type to validate registrations against |
None
|
Methods:
| Name | Description |
|---|---|
register |
Register a plugin class or factory. |
unregister |
Unregister a plugin. |
is_registered |
Check if a plugin is registered. |
get |
Get a plugin instance. |
get_async |
Get a plugin instance, supporting async factories. |
list_keys |
List all registered plugin keys. |
clear_cache |
Clear cached instances. |
get_factory |
Get the registered factory for a key. |
set_default_factory |
Set the default factory. |
bulk_register |
Register multiple plugins at once. |
copy |
Get a copy of all registered factories. |
__len__ |
Get number of registered plugins. |
__contains__ |
Check if plugin is registered using 'in' operator. |
__repr__ |
Get string representation. |
Attributes:
| Name | Type | Description |
|---|---|---|
name |
str
|
Get registry name. |
cached_instances |
Dict[str, T]
|
Get the dictionary of cached instances. |
Source code in packages/common/src/dataknobs_common/registry.py
Attributes¶
cached_instances
property
¶
Get the dictionary of cached instances.
Returns:
| Type | Description |
|---|---|
Dict[str, T]
|
Dictionary mapping keys to cached instances |
Note
This returns the internal cache dictionary. Modifications will affect the cache directly.
Functions¶
register ¶
Register a plugin class or factory.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
Unique identifier for the plugin |
required |
factory
|
type[T] | Callable[..., T]
|
Plugin class or factory function that creates instances |
required |
override
|
bool
|
If True, allow overriding existing registration |
False
|
Raises:
| Type | Description |
|---|---|
OperationError
|
If key already registered and override=False |
TypeError
|
If factory doesn't match validate_type |
Example
Source code in packages/common/src/dataknobs_common/registry.py
unregister ¶
Unregister a plugin.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
Key to unregister |
required |
Raises:
| Type | Description |
|---|---|
NotFoundError
|
If key not registered |
Source code in packages/common/src/dataknobs_common/registry.py
is_registered ¶
Check if a plugin is registered.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
Key to check |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if registered |
get ¶
get(
key: str,
config: Dict[str, Any] | None = None,
use_cache: bool = True,
use_default: bool = True,
) -> T
Get a plugin instance.
Creates instance if not cached, using the registered factory.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
Plugin identifier |
required |
config
|
Dict[str, Any] | None
|
Configuration dictionary passed to factory |
None
|
use_cache
|
bool
|
Return cached instance if available |
True
|
use_default
|
bool
|
Use default factory if key not registered |
True
|
Returns:
| Type | Description |
|---|---|
T
|
Plugin instance |
Raises:
| Type | Description |
|---|---|
NotFoundError
|
If key not registered and use_default=False |
Source code in packages/common/src/dataknobs_common/registry.py
get_async
async
¶
get_async(
key: str,
config: Dict[str, Any] | None = None,
use_cache: bool = True,
use_default: bool = True,
) -> T
Get a plugin instance, supporting async factories.
Like get() but awaits the factory if it's a coroutine function.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
Plugin identifier |
required |
config
|
Dict[str, Any] | None
|
Configuration dictionary |
None
|
use_cache
|
bool
|
Return cached instance if available |
True
|
use_default
|
bool
|
Use default factory if key not registered |
True
|
Returns:
| Type | Description |
|---|---|
T
|
Plugin instance |
Source code in packages/common/src/dataknobs_common/registry.py
957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 | |
list_keys ¶
List all registered plugin keys.
Returns:
| Type | Description |
|---|---|
List[str]
|
List of registered keys |
clear_cache ¶
Clear cached instances.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str | None
|
Specific key to clear, or None for all |
None
|
Source code in packages/common/src/dataknobs_common/registry.py
get_factory ¶
Get the registered factory for a key.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
Plugin identifier |
required |
Returns:
| Type | Description |
|---|---|
type[T] | Callable[..., T] | None
|
Factory class or function, or None if not registered |
Source code in packages/common/src/dataknobs_common/registry.py
set_default_factory ¶
Set the default factory.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
factory
|
type[T] | Callable[..., T]
|
New default factory |
required |
Raises:
| Type | Description |
|---|---|
TypeError
|
If factory doesn't match validate_type |
Source code in packages/common/src/dataknobs_common/registry.py
bulk_register ¶
Register multiple plugins at once.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
factories
|
Dict[str, type[T] | Callable[..., T]]
|
Dictionary mapping keys to factories |
required |
override
|
bool
|
Allow overriding existing registrations |
False
|
Source code in packages/common/src/dataknobs_common/registry.py
copy ¶
Get a copy of all registered factories.
Returns:
| Type | Description |
|---|---|
Dict[str, type[T] | Callable[..., T]]
|
Dictionary of key to factory mappings |
__len__ ¶
__contains__ ¶
__repr__ ¶
Get string representation.
Registry ¶
Bases: Generic[T]
Base registry for managing named items with optional metrics.
This is a thread-safe registry that manages a collection of items by unique keys. It provides core operations for registration, lookup, and enumeration.
The registry is generic, so you can specify the type of items it manages for better type safety.
Attributes:
| Name | Type | Description |
|---|---|---|
name |
str
|
Name of the registry (for logging/debugging) |
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Name for this registry instance |
required |
enable_metrics
|
bool
|
Whether to track registration metrics |
False
|
Example
Initialize the registry.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Registry name for identification |
required |
enable_metrics
|
bool
|
Enable metrics tracking |
False
|
Methods:
| Name | Description |
|---|---|
register |
Register an item by key. |
unregister |
Unregister and return an item by key. |
get |
Get an item by key. |
get_optional |
Get an item by key, returning None if not found. |
has |
Check if item exists. |
list_keys |
List all registered keys. |
list_items |
List all registered items. |
items |
Get all key-item pairs. |
count |
Get count of registered items. |
clear |
Clear all items from registry. |
get_metrics |
Get registration metrics. |
__len__ |
Get number of registered items using len(). |
__contains__ |
Check if item exists using 'in' operator. |
__iter__ |
Iterate over registered items. |
Source code in packages/common/src/dataknobs_common/registry.py
Attributes¶
Functions¶
register ¶
register(
key: str,
item: T,
metadata: Dict[str, Any] | None = None,
allow_overwrite: bool = False,
) -> None
Register an item by key.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
Unique identifier for the item |
required |
item
|
T
|
Item to register |
required |
metadata
|
Dict[str, Any] | None
|
Optional metadata about the item |
None
|
allow_overwrite
|
bool
|
Whether to allow overwriting existing items |
False
|
Raises:
| Type | Description |
|---|---|
OperationError
|
If item already exists and allow_overwrite is False |
Source code in packages/common/src/dataknobs_common/registry.py
unregister ¶
Unregister and return an item by key.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
Key of item to unregister |
required |
Returns:
| Type | Description |
|---|---|
T
|
The unregistered item |
Raises:
| Type | Description |
|---|---|
NotFoundError
|
If item not found |
Source code in packages/common/src/dataknobs_common/registry.py
get ¶
Get an item by key.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
Key of item to retrieve |
required |
Returns:
| Type | Description |
|---|---|
T
|
The registered item |
Raises:
| Type | Description |
|---|---|
NotFoundError
|
If item not found |
Source code in packages/common/src/dataknobs_common/registry.py
get_optional ¶
Get an item by key, returning None if not found.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
Key of item to retrieve |
required |
Returns:
| Type | Description |
|---|---|
T | None
|
The registered item or None |
Source code in packages/common/src/dataknobs_common/registry.py
has ¶
Check if item exists.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
Key to check |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if item exists |
Source code in packages/common/src/dataknobs_common/registry.py
list_keys ¶
List all registered keys.
Returns:
| Type | Description |
|---|---|
List[str]
|
List of registered keys |
Source code in packages/common/src/dataknobs_common/registry.py
list_items ¶
List all registered items.
Returns:
| Type | Description |
|---|---|
List[T]
|
List of registered items |
Source code in packages/common/src/dataknobs_common/registry.py
items ¶
Get all key-item pairs.
Returns:
| Type | Description |
|---|---|
List[tuple[str, T]]
|
List of (key, item) tuples |
Source code in packages/common/src/dataknobs_common/registry.py
count ¶
Get count of registered items.
Returns:
| Type | Description |
|---|---|
int
|
Number of items in registry |
Source code in packages/common/src/dataknobs_common/registry.py
clear ¶
Clear all items from registry.
Source code in packages/common/src/dataknobs_common/registry.py
get_metrics ¶
Get registration metrics.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str | None
|
Optional specific key to get metrics for |
None
|
Returns:
| Type | Description |
|---|---|
Dict[str, Any]
|
Metrics dictionary |
Example
Source code in packages/common/src/dataknobs_common/registry.py
__len__ ¶
__contains__ ¶
Serializable ¶
Bases: Protocol
Protocol for objects that can be serialized to/from dict.
Implement this protocol by providing to_dict() and from_dict() methods. The @runtime_checkable decorator allows isinstance() checks at runtime.
Methods:
| Name | Description |
|---|---|
to_dict |
Convert object to dictionary representation |
from_dict |
Create object from dictionary representation |
Example
Functions¶
to_dict ¶
Convert object to dictionary representation.
Returns:
| Type | Description |
|---|---|
Dict[str, Any]
|
Dictionary with serialized data |
Raises:
| Type | Description |
|---|---|
SerializationError
|
If serialization fails |
from_dict
classmethod
¶
Create object from dictionary representation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
Dict[str, Any]
|
Dictionary with serialized data |
required |
Returns:
| Type | Description |
|---|---|
T
|
Deserialized object instance |
Raises:
| Type | Description |
|---|---|
SerializationError
|
If deserialization fails |
Source code in packages/common/src/dataknobs_common/serialization.py
Functions¶
safe_eval ¶
safe_eval(
code: str,
scope: dict[str, Any] | None = None,
*,
coerce_bool: bool = False,
restrict_builtins: bool = True,
default: Any = None,
) -> ExpressionResult
Evaluate a Python expression string safely.
Wraps the expression in a function body, executes with restricted globals, and returns the native result. This is the shared core used by wizard conditions and derivation expressions.
Security model (when restrict_builtins=True):
__builtins__restricted toSAFE_BUILTINS(blocksexec,eval,__import__,open, etc.)- AST validation blocks dunder attribute access (prevents
MRO traversal via
__class__.__bases__.__subclasses__)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
code
|
str
|
Python expression string. If it does not start with
|
required |
scope
|
dict[str, Any] | None
|
Variables available in the expression. Merged on top
of |
None
|
coerce_bool
|
bool
|
If True, coerce the result to |
False
|
restrict_builtins
|
bool
|
If True (default), set |
True
|
default
|
Any
|
Value to return on evaluation failure. Defaults
to |
None
|
Returns:
| Type | Description |
|---|---|
ExpressionResult
|
ExpressionResult with the evaluated value and success status. |
Source code in packages/common/src/dataknobs_common/expressions.py
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 | |
safe_eval_value ¶
Convenience wrapper returning just the value.
Same as safe_eval(...).value. Suitable for call sites that
only need the result and handle errors via the default value.
Source code in packages/common/src/dataknobs_common/expressions.py
create_event_bus ¶
Create an event bus from configuration.
Factory function that creates the appropriate EventBus implementation based on the 'backend' key in the config.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
dict[str, Any]
|
Configuration dict with 'backend' key and backend-specific options |
required |
Returns:
| Type | Description |
|---|---|
EventBus
|
EventBus instance |
Raises:
| Type | Description |
|---|---|
ValueError
|
If backend type is not recognized |
Example
Source code in packages/common/src/dataknobs_common/events/bus.py
create_rate_limiter ¶
Create a rate limiter from configuration.
Factory function that creates the appropriate RateLimiter implementation
based on the backend key in the config.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
dict[str, Any]
|
Configuration dict. See below for keys. |
required |
Returns:
| Type | Description |
|---|---|
RateLimiter
|
RateLimiter instance. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the backend is not recognized or required config is missing. |
Config keys
backend: "memory" (default) or "pyrate".
rates: Shorthand for default_rates.
default_rates: List of {"limit": int, "interval": float} dicts.
categories: Dict mapping category names to
{"rates": [{"limit": ..., "interval": ...}]}.
bucket: Pyrate bucket backend ("memory", "sqlite",
"redis", "postgres").
redis: Redis connection config (for pyrate redis bucket).
postgres: Postgres config (for pyrate postgres bucket).
sqlite: SQLite config (for pyrate sqlite bucket).
Example
# Simple in-memory limiter
limiter = create_rate_limiter({
"rates": [{"limit": 10, "interval": 60}],
})
# Per-category with pyrate + Redis
limiter = create_rate_limiter({
"backend": "pyrate",
"bucket": "redis",
"default_rates": [{"limit": 100, "interval": 60}],
"categories": {
"api_write": {"rates": [{"limit": 10, "interval": 60}]},
},
"redis": {"url": "redis://localhost:6379"},
})
Source code in packages/common/src/dataknobs_common/ratelimit/limiter.py
deserialize ¶
Deserialize dictionary into an object.
Convenience function that calls from_dict() with error handling.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cls
|
Type[T]
|
Class to deserialize into (must have from_dict classmethod) |
required |
data
|
Dict[str, Any]
|
Dictionary with serialized data |
required |
Returns:
| Type | Description |
|---|---|
T
|
Deserialized object instance |
Raises:
| Type | Description |
|---|---|
SerializationError
|
If class doesn't support deserialization or deserialization fails |
Example
Source code in packages/common/src/dataknobs_common/serialization.py
deserialize_list ¶
Deserialize a list of dictionaries into objects.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cls
|
Type[T]
|
Class to deserialize into |
required |
data_list
|
list[Dict[str, Any]]
|
List of serialized dictionaries |
required |
Returns:
| Type | Description |
|---|---|
list[T]
|
List of deserialized objects |
Raises:
| Type | Description |
|---|---|
SerializationError
|
If any item cannot be deserialized |
Example
Source code in packages/common/src/dataknobs_common/serialization.py
is_deserializable ¶
Check if a class is deserializable.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cls
|
Type
|
Class to check |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if class has from_dict classmethod |
Example
Source code in packages/common/src/dataknobs_common/serialization.py
is_serializable ¶
Check if an object is serializable.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
obj
|
Any
|
Object to check |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if object has to_dict method |
Example
Source code in packages/common/src/dataknobs_common/serialization.py
serialize ¶
Serialize an object to dictionary.
Convenience function that calls to_dict() with error handling.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
obj
|
Any
|
Object to serialize (must have to_dict method) |
required |
Returns:
| Type | Description |
|---|---|
Dict[str, Any]
|
Serialized dictionary |
Raises:
| Type | Description |
|---|---|
SerializationError
|
If object doesn't support serialization or serialization fails |
Example
Source code in packages/common/src/dataknobs_common/serialization.py
serialize_list ¶
Serialize a list of objects to list of dictionaries.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
items
|
list[Any]
|
List of serializable objects |
required |
Returns:
| Type | Description |
|---|---|
list[Dict[str, Any]]
|
List of serialized dictionaries |
Raises:
| Type | Description |
|---|---|
SerializationError
|
If any item cannot be serialized |
Source code in packages/common/src/dataknobs_common/serialization.py
create_test_json_files ¶
Create test JSON files.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tmp_path
|
Path
|
Temporary directory path (from pytest fixture) |
required |
Returns:
| Type | Description |
|---|---|
list[str]
|
List of created file paths as strings |
Source code in packages/common/src/dataknobs_common/testing.py
create_test_markdown_files ¶
Create test markdown files for ingestion.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tmp_path
|
Path
|
Temporary directory path (from pytest fixture) |
required |
Returns:
| Type | Description |
|---|---|
list[str]
|
List of created file paths as strings |
Example
Source code in packages/common/src/dataknobs_common/testing.py
get_test_bot_config ¶
get_test_bot_config(
use_echo_llm: bool = True,
use_in_memory_storage: bool = True,
include_memory: bool = False,
system_prompt: str | None = None,
) -> dict[str, Any]
Get a test bot configuration.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
use_echo_llm
|
bool
|
Use echo LLM instead of real LLM (default: True) |
True
|
use_in_memory_storage
|
bool
|
Use in-memory conversation storage (default: True) |
True
|
include_memory
|
bool
|
Include buffer memory configuration (default: False) |
False
|
system_prompt
|
str | None
|
Optional system prompt content |
None
|
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
Bot configuration dictionary suitable for DynaBot.from_config() |
Example
Source code in packages/common/src/dataknobs_common/testing.py
get_test_rag_config ¶
get_test_rag_config(
use_in_memory_store: bool = True,
embedding_provider: str = "ollama",
embedding_model: str = "nomic-embed-text",
) -> dict[str, Any]
Get a test RAG/knowledge base configuration.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
use_in_memory_store
|
bool
|
Use in-memory vector store (default: True) |
True
|
embedding_provider
|
str
|
Embedding provider (default: "ollama") |
'ollama'
|
embedding_model
|
str
|
Embedding model name (default: "nomic-embed-text") |
'nomic-embed-text'
|
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
Knowledge base configuration dictionary |
Example
Source code in packages/common/src/dataknobs_common/testing.py
is_chromadb_available ¶
Check if ChromaDB is available.
Returns:
| Type | Description |
|---|---|
bool
|
True if ChromaDB can be imported, False otherwise |
is_faiss_available ¶
Check if FAISS is available.
Returns:
| Type | Description |
|---|---|
bool
|
True if FAISS can be imported, False otherwise |
is_ollama_available ¶
Check if Ollama service is available.
Returns:
| Type | Description |
|---|---|
bool
|
True if Ollama is running, False otherwise |
Source code in packages/common/src/dataknobs_common/testing.py
is_ollama_model_available ¶
Check if a specific Ollama model is available.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model_name
|
str
|
Name of the model to check (default: nomic-embed-text) |
'nomic-embed-text'
|
Returns:
| Type | Description |
|---|---|
bool
|
True if model is available, False otherwise |
Source code in packages/common/src/dataknobs_common/testing.py
is_package_available ¶
Check if a Python package is available.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
package_name
|
str
|
Name of the package to check |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if package can be imported, False otherwise |
Source code in packages/common/src/dataknobs_common/testing.py
is_redis_available ¶
Check if Redis service is available.
Reads REDIS_HOST and REDIS_PORT environment variables when
explicit arguments are not provided, falling back to localhost:6379.
This ensures the check works both on the host and inside Docker
where Redis runs on a network hostname.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
host
|
str | None
|
Redis host (default: |
None
|
port
|
int | None
|
Redis port (default: |
None
|
Returns:
| Type | Description |
|---|---|
bool
|
True if Redis is available, False otherwise |