Skip to main content

No project description provided

Project description

liblaf-lazy-loader lets Python packages expose stub-driven lazy exports with both absolute imports and package-relative imports.

✨ Features

  • 💤 Stub-driven lazy imports: Parse a sibling .pyi file and turn its import and from ... import ... statements into on-demand attribute loaders.
  • 📦 Module-friendly exports: Preserve __all__ and enrich dir() so interactive use and star exports stay aligned with the stub definition.
  • 🔁 Absolute and relative import support: Handle both local package imports and external modules, including aliased imports.
  • Optional eager mode: Set EAGER_IMPORT=1 to resolve every declared export at import time when startup indirection is not wanted.
  • 🧭 Typed, tiny surface area: Ship as a typed package with no runtime dependencies and a small public API centered on attach_stub and LazyLoader.
  • 🔄 Drop-in attach_stub call: Support the familiar attach_stub(__name__, __file__) signature, with an optional trailing __package__ override when needed.

📦 Installation

[!NOTE] liblaf-lazy-loader requires Python 3.12 or newer.

uv add liblaf-lazy-loader

🚀 Quick Start

In mypkg/__init__.py, wire the package up once:

from liblaf.lazy_loader import attach_stub

__getattr__, __dir__, __all__ = attach_stub(__name__, __file__)

If you need to pass an explicit package anchor, use the optional third argument:

__getattr__, __dir__, __all__ = attach_stub(__name__, __file__, __package__)

In the sibling mypkg/__init__.pyi, declare the exports you want to load lazily:

from . import cli
from ._config import Settings
from ._factory import make_settings
from rich import get_console
import rich.console as rich_console

__all__ = ["Settings", "cli", "get_console", "make_settings", "rich_console"]

With that wiring in place, Settings, cli, make_settings, get_console, and rich_console are imported only when first accessed. When the third argument is omitted entirely, attach_stub uses __name__ as the package anchor, which makes the two-argument form work as a drop-in replacement for lazy_loader.attach_stub in package __init__.py files. Passing None explicitly preserves None. The sibling .pyi file is part of the runtime configuration here, not only a type-checking aid.

🧩 Supported Stub Forms

The stub parser understands the explicit import forms that the test suite covers:

  • import rich
  • import rich.console as rich_console
  • from rich import get_console
  • from . import cli
  • from ._factory import make_settings
  • from ._factory import make_settings as build_settings

__all__ stays aligned with the stub definition, and dir() includes both declared exports and any names already materialized on the module.

⚡ Eager Import Mode

Lazy loading defers import errors until the first attribute access. During development or tests, set EAGER_IMPORT=1 before importing the package to resolve every declared export immediately.

The current test suite also covers EAGER_IMPORT=0 for normal lazy behavior and raises a ValueError when EAGER_IMPORT is set to an invalid boolean string.

🚧 Limitations and Errors

  • Accessing a name that is not declared in the stub raises AttributeError.
  • Import failures surface when the lazy attribute is accessed, or earlier if eager mode is enabled.
  • The package expects explicit import statements in the sibling stub file and uses that stub file at runtime.

🔍 Compared With Alternatives

This project parses the sibling stub AST directly, so the runtime behavior is defined by the same file that type checkers read.

  • scientific-python/lazy-loader.attach_stub parses stubs into its older attach(...) API. In its current implementation, the stub visitor only accepts within-package from . import ... and from .foo import ... forms and raises ValueError for other patterns, so it cannot express absolute entries like import rich.console as rich_console in the stub. See the README and source.
  • etils.epy.lazy_api_imports records imports by temporarily wrapping builtins.__import__. Its underlying lazy import helper rejects relative imports with a ValueError, so it is not a drop-in fit for sibling package-relative exports. See the API docs and source.

⌨️ Local Development

Clone the repository, install all dependency groups with uv, and run the maintained nox test matrix:

gh repo clone liblaf/lazy-loader
cd lazy-loader
mise run install
nox

Build the documentation locally with:

mise run docs:build

🤝 Contributing

Issues and pull requests are welcome, especially around import edge cases, typing behavior, and documentation improvements.

PR Welcome

Contributors


📝 License

Copyright © 2026 liblaf.
This project is MIT licensed.

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

liblaf_lazy_loader-0.2.1.tar.gz (9.6 kB view details)

Uploaded Source

Built Distribution

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

liblaf_lazy_loader-0.2.1-py3-none-any.whl (11.8 kB view details)

Uploaded Python 3

File details

Details for the file liblaf_lazy_loader-0.2.1.tar.gz.

File metadata

  • Download URL: liblaf_lazy_loader-0.2.1.tar.gz
  • Upload date:
  • Size: 9.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for liblaf_lazy_loader-0.2.1.tar.gz
Algorithm Hash digest
SHA256 460f4dab119de7d26dabb8f7bb711ad8b601b0ba03407e1c441103767599bd86
MD5 eb0fa7c3ee5d3b8d7a39a2f0d7d725f9
BLAKE2b-256 e46e55daf4de0bdbdfea763d04e3ec542ef2395a3cb839526c422d1c2d753c8a

See more details on using hashes here.

Provenance

The following attestation bundles were made for liblaf_lazy_loader-0.2.1.tar.gz:

Publisher: python-release.yaml on liblaf/lazy-loader

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file liblaf_lazy_loader-0.2.1-py3-none-any.whl.

File metadata

File hashes

Hashes for liblaf_lazy_loader-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 d5b13f221249641d8028cbe149d3f96fd5c9dbe2d0e6762722d66cc024172771
MD5 350b2df3a45855f6379137394b065338
BLAKE2b-256 f7c91da42aee3e1c611aa1971aa334703a5b774c182ed74a0cb83750e131d666

See more details on using hashes here.

Provenance

The following attestation bundles were made for liblaf_lazy_loader-0.2.1-py3-none-any.whl:

Publisher: python-release.yaml on liblaf/lazy-loader

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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