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.0.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.0-py3-none-any.whl (11.8 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: liblaf_lazy_loader-0.2.0.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.0.tar.gz
Algorithm Hash digest
SHA256 145284d6d1b74dcd257c0d2c0b613fa4fc2610988da408769ae839e60dc63ad4
MD5 8dca266c3f236ebdbae0a4604520c894
BLAKE2b-256 64cea8787c1893b227701f28ec96d70b7eaa433923e0a6925aa747a8153fa2f2

See more details on using hashes here.

Provenance

The following attestation bundles were made for liblaf_lazy_loader-0.2.0.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.0-py3-none-any.whl.

File metadata

File hashes

Hashes for liblaf_lazy_loader-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 46cbb2468a5a5b19162375c911899d5491d6f2b1cd0b69d05d74bfdb9e21d836
MD5 7200bc3b45af4b2a6a20954a18e66509
BLAKE2b-256 7c4137b19ab6ddaf54032c8f58d20b2a94b8d625f75cfbeb77ef5370406cf684

See more details on using hashes here.

Provenance

The following attestation bundles were made for liblaf_lazy_loader-0.2.0-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