ACB Documentation: Main | Core Systems | Actions | Adapters
Asynchronous Component Base (ACB)

What is ACB?
ACB is a modular Python framework for building asynchronous applications with pluggable components. It provides a collection of self-contained actions and flexible adapters that integrate with various systems, along with a dynamic configuration and dependency injection system.
Key Features
- Modular Architecture: Mix and match components to build your application
- Asynchronous First: Built for high-performance async operations
- Pluggable Adapters: Swap implementations without changing your code
- Automatic Discovery: Components are automatically discovered and registered
- Configuration-Driven: Change behavior through configuration rather than code
- Type Safety: Built on Pydantic for validation and type safety
Table of Contents
Installation
Install ACB using pdm:
pdm add acb
Optional Dependencies
ACB supports various optional dependencies for different adapters and functionality:
Redis | Cache, NoSQL | pdm add "acb[redis]" |
SQL | Database (MySQL, PostgreSQL) | pdm add "acb[sql]" |
NoSQL | Database (MongoDB, Firestore, Redis) | pdm add "acb[nosql]" |
Storage | File storage (S3, GCS, Azure, local) | pdm add "acb[storage]" |
Logging | Loguru, structlog | pdm add "acb[logging]" |
Compression | gzip, brotli | pdm add "acb[compression]" |
Serialization | JSON, YAML, TOML, MsgPack | pdm add "acb[serialization]" |
Multiple Features | Combined dependencies | pdm add "acb[redis,sql,nosql]" |
Web Application | Typical web app stack | pdm add "acb[redis,sql,storage]" |
Complete | All dependencies | pdm add "acb[all]" |
Architecture Overview
ACB follows a component-based architecture with automatic discovery and registration of modules:
acb/
├── actions/ # Reusable utility functions (compress, encode, hash)
├── adapters/ # Integration modules for external systems
│ ├── cache/ # Memory and Redis caching
│ ├── dns/ # DNS management
│ ├── logger/ # Logging adapters (Loguru, structlog)
│ ├── sql/ # Database adapters (MySQL, PostgreSQL)
│ ├── nosql/ # NoSQL adapters (MongoDB, Firestore, Redis)
│ ├── storage/ # Storage adapters (S3, GCS, Azure, local)
│ └── ... # Additional adapter categories
├── config.py # Configuration system using Pydantic
├── depends.py # Dependency injection framework
└── ...
Core Components
ACB is structured around these fundamental building blocks:
Actions
Actions are modular, self-contained utility functions that perform specific tasks. They are automatically discovered and registered, making them immediately available throughout your application.
Available Actions
Compress/Decompress | Efficient data compression | gzip, brotli |
Encode/Decode | Data serialization | JSON, YAML, TOML, MsgPack |
Hash | Secure hashing functions | blake3, crc32c, md5 |
Example: Using the compress action
from acb.actions.compress import compress, decompress
compressed = compress.brotli("Hello, ACB!", level=3)
original = decompress.brotli(compressed)
For more detailed documentation on actions, see the Actions README.
Adapters
Adapters provide standardized interfaces to external systems and services. Each adapter category includes a base class that defines the interface and multiple implementations.
Key Adapter Categories
Cache | Data caching | Memory, Redis |
DNS | Domain name management | Cloud DNS |
FTP/SFTP | File transfer protocols | FTP, SFTP |
Logger | Structured logging | Loguru, structlog |
Database | Data persistence | SQL (MySQL, PostgreSQL), NoSQL (MongoDB, Firestore, Redis) |
Storage | File storage | File, Memory, S3, Cloud Storage, Azure |
Secret | Secret management | Infisical, Secret Manager |
Example: Using the cache adapter
from acb.depends import depends
from acb.adapters import import_adapter
Cache = import_adapter("cache")
cache = depends.get(Cache)
await cache.set("my_key", "my_value", ttl=60)
value = await cache.get("my_key")
For more detailed documentation on adapters, see the Adapters README.
Configuration System
ACB's configuration system is built on Pydantic and supports multiple configuration sources:
- YAML Files: Environment-specific settings in YAML format
- Secret Files: Secure storage of sensitive information
- Secret Managers: Integration with external secret management services
Example: Defining custom settings
from acb.config import Settings
from pydantic import SecretStr
class MyServiceSettings(Settings):
api_url: str = "https://api.example.com"
api_version: str = "v1"
timeout: int = 30
max_retries: int = 3
api_key: SecretStr = SecretStr("default-key")
Dependency Injection
ACB features a simple yet powerful dependency injection system that makes component wiring automatic and testable.
Example: Using dependency injection
from acb.depends import depends
from acb.config import Config
depends.set(MyService)
@depends.inject
def process_data(data, config: Config = depends(), logger = depends("logger")):
logger.info(f"Processing data with app: {config.app.name}")
return result
Getting Started
Basic Application Setup
- Create a new project with PDM:
mkdir myapp
cd myapp
pdm init
pdm add acb
- Create a basic application structure:
myapp/
├── myapp/
│ ├── __init__.py
│ ├── actions/
│ │ └── __init__.py
│ ├── adapters/
│ │ └── __init__.py
│ └── main.py
└── settings/
├── app.yml
├── debug.yml
└── adapters.yml
- Initialize ACB in your main.py:
from acb import register_pkg
from acb.depends import depends
from acb.config import Config
register_pkg()
config = depends.get(Config)
Logger = depends.get("logger")
async def main():
Logger.info(f"Starting {config.app.name} application")
if __name__ == "__main__":
import asyncio
asyncio.run(main())
Configuration Files
Create your initial configuration files:
settings/app.yml
app:
name: "MyApp"
title: "My ACB Application"
domain: "myapp.example.com"
version: "0.1.0"
settings/adapters.yml
cache: memory
logger: loguru
storage: file
Built-in Components
Debug Module
ACB provides comprehensive debugging tools to help troubleshoot your application:
- Granular debug levels: Control debug output for specific components
- Pretty-printed output: Human-readable debug information
- Performance timers: Measure and optimize execution time
Logging
The framework includes a robust logging system with structured logging and multiple output formats:
- Asynchronous logging: Non-blocking log operations
- Structured data: JSON-formatted logs for better analysis
- Multiple adapters: Choose between different logging implementations
Advanced Usage
Creating Custom Actions
Create your own reusable actions by adding Python modules to the actions directory:
from pydantic import BaseModel
class Validate(BaseModel):
@staticmethod
def email(email: str) -> bool:
"""Validate an email address"""
import re
pattern = r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
return bool(re.match(pattern, email))
validate = Validate()
Implementing Custom Adapters
Extend ACB with your own adapters to integrate with additional services:
- Create the adapter directory structure:
myapp/adapters/payment/
├── __init__.py
├── _base.py
├── stripe.py
└── paypal.py
- Define the base interface in
_base.py
:
from acb.config import AdapterBase, Settings
class PaymentBaseSettings(Settings):
currency: str = "USD"
default_timeout: int = 30
class PaymentBase(AdapterBase):
async def charge(self, amount: float, description: str) -> str:
"""Charge a payment and return a transaction ID"""
raise NotImplementedError()
async def refund(self, transaction_id: str) -> bool:
"""Refund a previous transaction"""
raise NotImplementedError()
- Implement specific providers like
stripe.py
:
from ._base import PaymentBase, PaymentBaseSettings
from pydantic import SecretStr
import stripe
class StripeSettings(PaymentBaseSettings):
api_key: SecretStr = SecretStr("sk_test_default")
class Stripe(PaymentBase):
settings: StripeSettings = None
async def init(self) -> None:
stripe.api_key = self.settings.api_key.get_secret_value()
async def charge(self, amount: float, description: str) -> str:
response = await stripe.PaymentIntent.create(
amount=int(amount * 100),
currency=self.settings.currency,
description=description
)
return response.id
Documentation
For more detailed documentation about ACB components:
- Core Systems: Configuration, dependency injection, debugging, and logging
- Actions: Detailed guide to built-in actions and creating custom ones
- Adapters: Comprehensive documentation on adapter system and implementations
Acknowledgements
ACB "blocks" logo used by permission from Andy Coe Band.
Special thanks to the following open-source projects for powering ACB:
License
This project is licensed under the terms of the BSD 3-Clause license.
Projects Using ACB
Here are some notable projects built with ACB:
- FastBlocks: A rapid development framework that leverages ACB's asynchronous components to build scalable web applications.
Contributing
Contributions to ACB are welcome! We follow a workflow inspired by the Crackerjack development guidelines. To ensure consistency and high quality, please adhere to the following steps when contributing:
-
Fork and Clone
Fork the repository and clone it locally.
-
Set Up Your Development Environment
Use PDM for dependency and virtual environment management. Add ACB as a development dependency:
pdm add -G dev acb
-
Run Pre-commit Hooks & Tests
Before submitting a pull request, ensure your changes pass all quality checks and tests. We recommend running the following command (which is inspired by Crackerjack's automated workflow):
python -m crackerjack -x -t -p <version> -c
Alternatively, you can use:
python -m crackerjack -a <version>
This command cleans your code, runs linting, tests, bumps the version (micro, minor, or major), and commits changes.
-
Submit a Pull Request
If everything passes, submit a pull request describing your changes. Include details about your contribution and reference any related issues.
-
Feedback and Review
Our maintainers will review your changes. Please be responsive to feedback and be prepared to update your pull request as needed.
For more detailed development guidelines and the Crackerjack philosophy that influences our workflow, please refer to our internal development documentation.
Happy contributing!