Skip to main content

A lightweight Python library for lazy-loading registries with namespace support and type safety.

Project description

lazyregistry

CI codecov pypi Python Versions License: MIT Code style: ruff

A lightweight Python library for lazy-loading registries with namespace support and type safety

Installation

# Install with pip
$ pip install lazyregistry

# Add to your project with uv
$ uv add "lazyregistry~=0.1.1"

Versioning Policy: We follow semantic versioning. Patch releases contain only bug fixes and performance improvements with no API changes. Minor releases may introduce new features while maintaining backward compatibility. Use ~=0.1.1 to automatically receive patch updates.

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

ImportString - String that represents an import path with lazy loading capability

from lazyregistry import ImportString

# Create an import string
import_str = ImportString("json:dumps")

# Load the object when needed
func = import_str.load()
func({"key": "value"})  # '{"key": "value"}'

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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

lazyregistry-0.1.2.tar.gz (14.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

lazyregistry-0.1.2-py3-none-any.whl (8.8 kB view details)

Uploaded Python 3

File details

Details for the file lazyregistry-0.1.2.tar.gz.

File metadata

  • Download URL: lazyregistry-0.1.2.tar.gz
  • Upload date:
  • Size: 14.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.9.7

File hashes

Hashes for lazyregistry-0.1.2.tar.gz
Algorithm Hash digest
SHA256 0110533bc7561abce5b1b90d80150621347078cb7ea73f8c62cfca586e1d7ffa
MD5 89d2206b745454cef443abdcf5142d5c
BLAKE2b-256 13f22e2ca4f2ba809da0f714e65b1e8d65e4a88118bdee4103c1129c90939cdd

See more details on using hashes here.

File details

Details for the file lazyregistry-0.1.2-py3-none-any.whl.

File metadata

File hashes

Hashes for lazyregistry-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 10e348fd8ace547a33bce814f9f073bfb54dc6a73bb61eb30465ef97fca42a70
MD5 7368d78e1e3203e7546ec4fadfb65373
BLAKE2b-256 d36957f199d96b3c7ee3bb5357ef400973da57942e7b928d2217f3e18869b8ff

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page