Regman : Thread-Safe Registry Framework for Python
Regman is a lightweight and flexible Python package to manage registries in a thread-safe way. It provides a simple yet powerful infrastructure for registering and managing classes, functions, and objects in a centralized, thread-safe manner.
Why Regman ?
The Problem
When building complex Python applications, you often need to:
- Manage multiple implementations of the same interface (e.g., different payment methods, data processors, or notification channels)
- Dynamically select components at runtime based on configuration or user input
- Implement design patterns like Strategy, Factory, Observer, or Plugin architectures
- Ensure thread safety when multiple threads access the same registry
- Avoid tight coupling between components and their instantiation logic
Common Solutions and Their Limitations
Manual dictionaries:
# ❌ Not thread-safe, error-prone
strategies = {
"credit_card": CreditCardStrategy,
"paypal": PayPalStrategy
}
strategy = strategies["credit_card"]() # KeyError if key doesn't exist
Simple registry classes:
# ❌ Not thread-safe, basic functionality
class SimpleRegistry:
def __init__(self):
self._items = {}
def register(self, key, value):
self._items[key] = value # Race condition in multi-threaded apps
Complex dependency injection frameworks:
# ❌ Overkill for simple use cases, heavy dependencies
from some_di_framework import Container, Service
container = Container()
container.register(Service(IPaymentStrategy), CreditCardStrategy)
# Too much boilerplate for simple registries
The Regman Solution
regman provides a simple, thread-safe, and flexible solution:
# ✅ Thread-safe, clean, and powerful
from regman import Registry, register
registry = Registry("payment_strategies")
@register(registry, "credit_card")
class CreditCardStrategy:
def pay(self, amount):
return f"Paid ${amount} with credit card"
# Safe to use from multiple threads
strategy_class = registry.get("credit_card")
strategy = strategy_class()
Key Benefits
- Thread Safety: Built-in locking ensures safe concurrent access
- Simplicity: Clean API with minimal boilerplate
- Flexibility: Works with any Python object (classes, functions, instances)
- Performance: Optimized for high-frequency access patterns
- Type Safety: Full type hints support for better IDE integration
- Design Pattern Ready: Perfect for implementing common architectural patterns
Real-World Use Cases
- Payment Processing: Different payment methods (credit card, PayPal, crypto)
- Plugin Systems: Dynamic loading and execution of plugins
- Data Processing Pipelines: Various data transformers and validators
- Notification Systems: Multiple notification channels (email, SMS, push)
- Configuration Management: Different configuration providers
- API Versioning: Multiple API implementations for different versions
Features
- Thread-Safe Registry: Store and manage objects with automatic locking for concurrent access
- Registry Manager: Centralize multiple registries for your project
- Decorator Support: Convenient
@registerdecorator for easy registration - Type Safety: Full type hints support for better IDE integration
- Lightweight: Minimal dependencies, fast performance
- Flexible: Works with any Python object (classes, functions, instances)
- Design Patterns: Perfect for implementing Strategy, Factory, Observer, and Plugin patterns
Installation
pip install regman
Or with Poetry:
poetry add regman
Quick Start
Basic Usage
from regman import Registry, register
# Create a registry
registry = Registry("my_components")
# Register a class
@register(registry, "calculator")
class Calculator:
def add(self, a: int, b: int) -> int:
return a + b
# Register a function
@register(registry, "multiplier")
def multiply(x: float, y: float) -> float:
return x * y
# Use registered objects
calc_class = registry.get("calculator")
calculator = calc_class()
result = calculator.add(5, 3) # 8
mult_func = registry.get("multiplier")
result = mult_func(4.5, 2.0) # 9.0
Registry Manager
from regman import RegistryManager, register
# Create a manager
manager = RegistryManager()
# Create multiple registries
plugins = manager.create_registry("plugins")
strategies = manager.create_registry("strategies")
# Register components
@register(plugins, "data_processor")
class DataProcessor:
def process(self, data):
return data * 2
@register(strategies, "payment_credit")
class CreditCardStrategy:
def pay(self, amount):
return f"Paid ${amount} with credit card"
# Access registries
data_processor = plugins.get("data_processor")
payment_strategy = strategies.get("payment_credit")
Advanced Usage
Strategy Pattern
from abc import ABC, abstractmethod
from regman import Registry, register
class PaymentStrategy(ABC):
@abstractmethod
def pay(self, amount: float) -> str:
pass
# Register strategies directly
registry = Registry("payment_strategies")
@register(registry, "credit_card")
class CreditCardStrategy(PaymentStrategy):
def pay(self, amount: float) -> str:
return f"Paid ${amount} with credit card"
@register(registry, "paypal")
class PayPalStrategy(PaymentStrategy):
def pay(self, amount: float) -> str:
return f"Paid ${amount} with PayPal"
# Use strategies
strategy_class = registry.get("credit_card")
strategy = strategy_class()
result = strategy.pay(100.0)
Plugin System
from abc import ABC, abstractmethod
from regman import Registry, register
class Plugin(ABC):
@abstractmethod
def execute(self, data):
pass
# Register plugins directly
registry = Registry("plugins")
@register(registry, "data_processor")
class DataProcessor(Plugin):
def execute(self, data):
return [x * 2 for x in data]
@register(registry, "text_formatter")
class TextFormatter(Plugin):
def execute(self, data):
return str(data).upper()
# Execute plugins
for plugin_name in registry.keys():
plugin_class = registry.get(plugin_name)
plugin = plugin_class()
result = plugin.execute("hello")
API Reference
Registry
The main registry class for storing and managing objects.
from regman import Registry
registry = Registry("my_registry")
Methods
add(key: str, value: Any) -> None: Add an object to the registryget(key: str) -> Any: Retrieve an object from the registryunregister(key: str) -> None: Remove an object from the registrykeys() -> List[str]: Get all registered keysclear() -> None: Remove all objects from the registry__contains__(key: str) -> bool: Check if a key exists__len__() -> int: Get the number of registered objects
RegistryManager
Manages multiple registries in a centralized way.
from regman import RegistryManager
manager = RegistryManager()
Methods
create_registry(name: str) -> Registry: Create a new registryget_registry(name: str) -> Registry: Get an existing registryall() -> Dict[str, Registry]: Get all registries
Decorators
@register
Register a class or function with a registry.
from regman import register
@register(registry, "my_key")
class MyClass:
pass
@register(registry, "my_function")
def my_function():
pass
Thread Safety
regman is designed to be thread-safe. All registry operations are protected by locks, making it safe to use in multi-threaded environments.
import threading
from regman import Registry, register
registry = Registry("thread_safe")
@register(registry, "worker")
class Worker:
def work(self):
return "Working safely!"
# Safe to use from multiple threads
def worker_thread():
worker_class = registry.get("worker")
worker = worker_class()
print(worker.work())
# Start multiple threads
threads = []
for i in range(5):
thread = threading.Thread(target=worker_thread)
threads.append(thread)
thread.start()
for thread in threads:
thread.join()
Examples
Check out the examples directory for comprehensive usage examples:
- Basic Usage - Getting started with regman
- Plugin System - Building a plugin architecture
- Strategy Pattern - Implementing payment strategies
- Observer Pattern - Event notification system
- Factory Pattern - Object creation patterns
- Concurrent Usage - Multi-threaded applications
Run all examples:
python examples/run_all_examples.py
Testing
The package includes comprehensive tests covering:
- Unit tests for all components
- Thread safety tests
- Integration tests
- Error handling tests
Run tests:
# With pytest
pytest tests/
# With poetry
poetry run pytest
# With coverage
pytest --cov=regman tests/
Performance
regman is designed for performance:
- Minimal overhead with efficient locking
- Fast object retrieval with O(1) average case
- Memory efficient with no unnecessary allocations
- Optimized for high-frequency access patterns
Contributing
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Development
Setup
# Clone the repository
git clone https://github.com/mawuva/regman.git
cd regman
# Install with poetry
poetry install
# Install pre-commit hooks
poetry run pre-commit install
Code Quality
The project uses several tools to maintain code quality:
- Black: Code formatting
- isort: Import sorting
- flake8: Linting
- mypy: Type checking
- pytest: Testing
Run all quality checks:
poetry run pre-commit run --all-files
License
This project is licensed under the MIT License - see the LICENSE file for details.
Support
If you have any questions or need help, please:
- Check the examples directory
- Read the documentation
- Open an issue
Acknowledgments
- Inspired by the need for a simple, thread-safe registry system
- Built with modern Python best practices
- Designed for extensibility and performance
Metadata
Release files for regman 0.2.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 | |
|---|---|---|---|---|
| regman-0.2.0.tar.gz | 9.5 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| regman-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 19.4 kB
Release files / regman-0.2.0.tar.gz
| Download URL | regman-0.2.0.tar.gz |
|---|---|
| Size | 9.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4efd9e1d22f4beaf06b4580ba806c9e226ef00d393f6e9fb9959094ab5c05115
|
|
BLAKE2b-256 checksum How to use checksums |
7e21095380e3cfd91a89fdc4cb3e1b811d26bc9956ee916ff21cb6f61d61d434
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.1.4 CPython/3.13.5 Windows/11
|
Release files / regman-0.2.0-py3-none-any.whl
| Download URL | regman-0.2.0-py3-none-any.whl |
|---|---|
| Size | 9.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ba9bb2f9c68f948a510f022dcb3a6abdb0a4f873332eb48d436774099eb5f646
|
|
BLAKE2b-256 checksum How to use checksums |
4f5a1a3a4dce9c48b38a09c6168ea6ce70445c532ee9eb9696cb2bd35c420d17
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.1.4 CPython/3.13.5 Windows/11
|
Security for regman 0.2.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.