A lightweight Python library for lazy-loading registries with namespace support and type safety.
Project description
lazyregistry
A lightweight Python library for lazy-loading registries with namespace support and type safety
Installation
pip install lazyregistry
Quick Start
from lazyregistry import Registry
registry = Registry(name="plugins")
# Register by import string (lazy - imported on access)
registry.register("json", "json:dumps")
# Register by instance (immediate - already imported)
import pickle
registry.register("pickle", pickle.dumps, is_instance=True)
# Import happens here
serializer = registry["json"]
Features
- Lazy imports - Defer expensive imports until first access
- Instance registration - Register both import strings and direct objects
- Namespaces - Organize multiple registries
- Type-safe - Full generic type support
- Eager loading - Optional immediate import for critical components
- Pretrained models - Built-in support for save_pretrained/from_pretrained pattern
Examples
Run examples: uv run python examples/<example>.py
1. Plugin System
examples/plugin_system.py - Extensible plugin architecture with decorator-based registration:
from lazyregistry import Registry
PLUGINS = Registry(name="plugins")
def plugin(name: str):
def decorator(cls):
PLUGINS.register(name, cls, is_instance=True)
return cls
return decorator
@plugin("uppercase")
class UppercasePlugin:
def process(self, text: str) -> str:
return text.upper()
# Execute plugins
PluginManager.execute("uppercase", "hello") # "HELLO"
PluginManager.pipeline("hello", "uppercase", "reverse") # "OLLEH"
2. Pretrained Models
examples/pretrained.py - HuggingFace-style save/load with two patterns:
Basic (config only):
from pydantic import BaseModel
from lazyregistry import NAMESPACE
from lazyregistry.pretrained import AutoRegistry, PretrainedMixin
class ModelConfig(BaseModel):
model_type: str
hidden_size: int = 768
class AutoModel(AutoRegistry):
registry = NAMESPACE["models"]
config_class = ModelConfig
type_key = "model_type"
@AutoModel.register("bert")
class BertModel(PretrainedMixin[ModelConfig]):
config_class = ModelConfig
# Save and auto-load
model = BertModel(ModelConfig(model_type="bert"))
model.save_pretrained("./model")
loaded = AutoModel.from_pretrained("./model") # Auto-detects type
Advanced (config + custom state):
class Tokenizer(PretrainedMixin[TokenizerConfig]):
def __init__(self, config, vocab: dict[str, int] | None = None):
super().__init__(config)
self.vocab = vocab or {}
def save_pretrained(self, path):
super().save_pretrained(path)
# Save additional state (vocabulary)
Path(path).joinpath("vocab.txt").write_text(...)
@classmethod
def from_pretrained(cls, path):
config = cls.config_class.model_validate_json(...)
vocab = ... # Load vocabulary
return cls(config, vocab=vocab)
API Reference
Core Classes
Registry[K, V] - Named registry with lazy import support
registry = Registry(name="plugins")
registry.register("key", "module:object") # Lazy
registry.register("key", obj, is_instance=True) # Immediate
registry.register("key", "module:object", eager_load=True) # Load now
value = registry["key"]
Namespace - Container for multiple registries
from lazyregistry import NAMESPACE
NAMESPACE["models"].register("bert", "transformers:BertModel")
model = NAMESPACE["models"]["bert"]
LazyImportDict[K, V] - Base class for custom implementations (same API as Registry without name)
Pretrained Pattern
PretrainedMixin[ConfigT] - Save/load with Pydantic config
class MyModel(PretrainedMixin[MyConfig]):
config_class = MyConfig
model.save_pretrained("./path")
loaded = MyModel.from_pretrained("./path")
AutoRegistry - Auto-detect model type from config
class AutoModel(AutoRegistry):
registry = NAMESPACE["models"]
config_class = ModelConfig
type_key = "model_type"
@AutoModel.register("bert")
class BertModel(PretrainedMixin[ModelConfig]):
config_class = ModelConfig
loaded = AutoModel.from_pretrained("./path") # Auto-detects type
Why?
Before:
# All imports happen upfront
from heavy_module_1 import ClassA
from heavy_module_2 import ClassB
from heavy_module_3 import ClassC
REGISTRY = {"a": ClassA, "b": ClassB, "c": ClassC}
After:
# Import only what you use
from lazyregistry import Registry
registry = Registry(name="components")
registry.register("a", "heavy_module_1:ClassA")
registry.register("b", "heavy_module_2:ClassB")
registry.register("c", "heavy_module_3:ClassC")
# Only ClassA is imported
component = registry["a"]
Testing
Run tests with coverage:
uv run pytest tests/ --cov=lazyregistry --cov-report=term-missing
The test suite includes:
- Core registry tests - LazyImportDict, Registry, Namespace functionality
- Pretrained tests - save/load patterns, AutoRegistry, custom state
- Example tests - Verify all examples run correctly
License
MIT
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 lazyregistry-0.1.0.tar.gz.
File metadata
- Download URL: lazyregistry-0.1.0.tar.gz
- Upload date:
- Size: 13.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.9.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
11655d0218d567d80e8edd35a152734cb998e32b963e5c1600f4401c39536fa0
|
|
| MD5 |
b0c97f72abecdc26a5db4e21dd293746
|
|
| BLAKE2b-256 |
9084380173069f63ff374c048ecf1b2491ff1550404cdfc57da147d8a688de3d
|
File details
Details for the file lazyregistry-0.1.0-py3-none-any.whl.
File metadata
- Download URL: lazyregistry-0.1.0-py3-none-any.whl
- Upload date:
- Size: 8.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.9.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bc46b6cf0a7acfa796107f0bd796772a128f12c505efa3503c3286ee73b2b177
|
|
| MD5 |
c1fef812fd416f1a14293f84a8ffadd3
|
|
| BLAKE2b-256 |
510e33ae372807df13ab0c1412a321ce1add6be823c04b8d745f9e5c9eaa2843
|