A flexible registry system for Python applications with auto-loading capabilities
Project description
Any Registries
A flexible and powerful registry system for Python applications with auto-loading capabilities. This package provides a generic registry pattern that can be used to register and retrieve any type of object (functions, classes, constants, etc.) with support for automatic module discovery and loading.
Features
- Generic Type Support: Register any type of object (functions, classes, constants)
- Auto-loading: Automatically discover and load modules based on glob patterns
- Multiple Registration Keys: Register objects with multiple keys simultaneously
- Key Functions: Use custom functions to generate registration keys
- Environment Integration: Respects
PROJECT_ROOTandBASE_DIRenvironment variables - Lazy Loading: Optional lazy loading for better performance
- Type Hints: Full typing support for better IDE experience
Installation
pip install any-registries
Quick Start
Basic Usage
from any_registries import Registry
# Create a registry
my_registry = Registry()
# Register a function
@my_registry.register("my_function")
def my_function():
return "Hello, World!"
# Register a class
@my_registry.register("my_class")
class MyClass:
def __init__(self, name):
self.name = name
# Retrieve and use registered items
func = my_registry.get("my_function")
print(func()) # Output: Hello, World!
cls = my_registry.get("my_class")
instance = cls("test")
print(instance.name) # Output: test
Auto-loading Modules
The registry can automatically discover and load modules based on file patterns:
from any_registries import Registry
# Create registry with auto-loading
registry = Registry()
registry.auto_load("**/handlers/*.py", "**/processors/*.py")
# Or chain the calls
registry = Registry().auto_load("**/handlers/*.py").auto_load("**/processors/*.py")
# Force loading (if lazy loading is disabled)
registry.force_load()
Custom Key Functions
Use a custom function to generate registration keys:
def name_key(obj):
return obj.__name__
registry = Registry(key=name_key)
@registry.register() # No key needed, will use function name
def my_named_function():
return "Named function"
# Retrieve using the function name
func = registry.get("my_named_function")
Environment Variables
The registry respects environment variables for base path discovery:
import os
# Set environment variable
os.environ["PROJECT_ROOT"] = "/my/project/root"
# Registry will use PROJECT_ROOT as base_path
registry = Registry()
# Or use BASE_DIR if PROJECT_ROOT is not set
os.environ["BASE_DIR"] = "/my/base/dir"
registry = Registry()
Advanced Usage
Plugin System Example
Create a simple plugin system:
from any_registries import Registry
# Create a plugin registry
plugins = Registry()
@plugins.register("database")
class DatabasePlugin:
def connect(self):
return "Connected to database"
@plugins.register("cache")
class CachePlugin:
def get(self, key):
return f"Cache value for {key}"
# Use plugins
db = plugins.get("database")()
print(db.connect()) # Output: Connected to database
cache = plugins.get("cache")()
print(cache.get("user:123")) # Output: Cache value for user:123
Handler Registry Example
Register and use different handlers:
from any_registries import Registry
# Create handler registry
handlers = Registry()
@handlers.register("json")
def handle_json(data):
import json
return json.loads(data)
@handlers.register("csv")
def handle_csv(data):
import csv
import io
return list(csv.reader(io.StringIO(data)))
# Use handlers
json_handler = handlers.get("json")
result = json_handler('{"name": "test"}')
print(result) # Output: {'name': 'test'}
Factory Pattern Example
Use registry as a factory:
from any_registries import Registry
# Vehicle factory
vehicles = Registry()
@vehicles.register("car")
class Car:
def __init__(self, model):
self.model = model
def start(self):
return f"{self.model} car started"
@vehicles.register("bike")
class Bike:
def __init__(self, model):
self.model = model
def start(self):
return f"{self.model} bike started"
# Factory function
def create_vehicle(vehicle_type, model):
vehicle_class = vehicles.get(vehicle_type)
return vehicle_class(model)
# Use factory
my_car = create_vehicle("car", "Toyota")
print(my_car.start()) # Output: Toyota car started
API Reference
Registry Class
class Registry(Generic[TYPE_KEY, TYPE_TARGET]):
def __init__(
self,
base_path: str | None = None,
auto_loads: list | None = None,
key: Callable | None = None,
lazy_load: bool = True,
) -> None:
"""
Initialize a new Registry.
Args:
base_path: Base path for module discovery (defaults to environment variables)
auto_loads: List of glob patterns for auto-loading modules
key: Function to generate keys from registered objects
lazy_load: Whether to load modules lazily (default: True)
"""
Methods
get(key): Retrieve a registered object by keyauto_load(*patterns): Add patterns for auto-loading modulesforce_load(): Force loading of all auto-load modulesregistry: Property to access the internal registry dictionary
Exceptions
ItemNotRegistered: Raised when trying to retrieve a non-existent key
Configuration Options
Lazy Loading
By default, modules are loaded lazily when first accessed. Disable lazy loading:
registry = Registry(lazy_load=False)
Base Path Priority
The registry determines the base path in this order:
- Explicit
base_pathparameter PROJECT_ROOTenvironment variableBASE_DIRenvironment variable- Current working directory (
os.getcwd())
Testing
Run the test suite:
# Install development dependencies
pip install -e .[dev]
# Run core tests
pytest tests/test_registry.py
# Run tests with coverage
pytest --cov=any_registries
Development
Setting up Development Environment
# Clone the repository
git clone https://github.com/Starscribers/python-packages.git
cd python-packages/any-registries
# Create virtual environment
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install in development mode
pip install -e .[dev]
# Install pre-commit hooks
pre-commit install
# Run tests
pytest
# Format code
ruff format src/ tests/
ruff check src/ tests/
# Type checking
mypy src/
Use Cases
- Plugin Systems: Register and discover plugins dynamically
- Handler Registries: Map keys to handler functions or classes
- Factory Patterns: Register classes and create instances by key
- Command Patterns: Register command handlers
- Strategy Patterns: Register different algorithms or strategies
- Configuration Management: Register configuration handlers
- Data Processing: Register different data processors or transformers
Contributing
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Add tests for new functionality
- Ensure tests pass (
pytest) - Format code (
ruff formatandruff check) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
This project is licensed under the MIT License - see the LICENSE file for details.
Changelog
Version 0.2.0
- Initial release
- Basic registry functionality
- Auto-loading support
- Type hints and comprehensive tests
- Python 3.8+ support
Support
If you encounter any issues or have questions:
- Check the Issues page
- Create a new issue with detailed information
- Include Python version and error traceback
Related Projects
- Python Design Patterns - Background on registry and other patterns
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file any_registries-0.3.0.tar.gz.
File metadata
- Download URL: any_registries-0.3.0.tar.gz
- Upload date:
- Size: 8.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
065b5aa496a509ffa346a7ce21e8a3934cbe58a29a4cb32fd8232c020ded66f9
|
|
| MD5 |
48061ce6bcf79afac5c11eb955cce187
|
|
| BLAKE2b-256 |
af25554da4f2c47b59ce8ed4f5ee5aa8542f1cac6e65dfdff391e42c1bd96023
|
File details
Details for the file any_registries-0.3.0-py3-none-any.whl.
File metadata
- Download URL: any_registries-0.3.0-py3-none-any.whl
- Upload date:
- Size: 6.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fc95c58ef597d0ac0886837a121018df35cc32ecc673b72482bc48048efb37bf
|
|
| MD5 |
3458e870b3e1edbb04f0f0e7a46aadfc
|
|
| BLAKE2b-256 |
8217ce5eb1dccf1b08d0ac6696cad6e45d3dff80bb8d606cde093c036cb206de
|