lazy-loader


Namelazy-loader JSON
Version 0.4 PyPI version JSON
download
home_pageNone
SummaryMakes it easy to load subpackages and functions on demand.
upload_time2024-04-05 13:03:12
maintainerNone
docs_urlNone
authorScientific Python Developers
requires_python>=3.7
licenseBSD 3-Clause License Copyright (c) 2022--2023, Scientific Python project All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            [![PyPI](https://img.shields.io/pypi/v/lazy_loader)](https://pypi.org/project/lazy_loader/)
[![Test status](https://github.com/scientific-python/lazy_loader/workflows/test/badge.svg?branch=main)](https://github.com/scientific-python/lazy_loader/actions?query=workflow%3A%22test%22)
[![Test coverage](https://codecov.io/gh/scientific-python/lazy_loader/branch/main/graph/badge.svg)](https://app.codecov.io/gh/scientific-python/lazy_loader/branch/main)

`lazy_loader` makes it easy to load subpackages and functions on demand.

## Motivation

1. Allow subpackages to be made visible to users without incurring import costs.
2. Allow external libraries to be imported only when used, improving import times.

For a more detailed discussion, see [the SPEC](https://scientific-python.org/specs/spec-0001/).

## Installation

```
pip install -U lazy_loader
```

We recommend using `lazy_loader` with Python >= 3.11.
If using Python 3.11, please upgrade to 3.11.9 or later.
If using Python 3.12, please upgrade to 3.12.3 or later.
These versions [avoid](https://github.com/python/cpython/pull/114781) a [known race condition](https://github.com/python/cpython/issues/114763).

## Usage

### Lazily load subpackages

Consider the `__init__.py` from [scikit-image](https://scikit-image.org):

```python
subpackages = [
    ...,
    'filters',
    ...
]

import lazy_loader as lazy
__getattr__, __dir__, _ = lazy.attach(__name__, subpackages)
```

You can now do:

```python
import skimage as ski
ski.filters.gaussian(...)
```

The `filters` subpackages will only be loaded once accessed.

### Lazily load subpackages and functions

Consider `skimage/filters/__init__.py`:

```python
from ..util import lazy

__getattr__, __dir__, __all__ = lazy.attach(
    __name__,
    submodules=['rank'],
    submod_attrs={
        '_gaussian': ['gaussian', 'difference_of_gaussians'],
        'edges': ['sobel', 'scharr', 'prewitt', 'roberts',
                  'laplace', 'farid']
    }
)
```

The above is equivalent to:

```python
from . import rank
from ._gaussian import gaussian, difference_of_gaussians
from .edges import (sobel, scharr, prewitt, roberts,
                    laplace, farid)
```

Except that all subpackages (such as `rank`) and functions (such as `sobel`) are loaded upon access.

### Type checkers

Static type checkers and IDEs cannot infer type information from
lazily loaded imports. As a workaround you can load [type
stubs](https://mypy.readthedocs.io/en/stable/stubs.html) (`.pyi`
files) with `lazy.attach_stub`:

```python
import lazy_loader as lazy
__getattr__, __dir__, _ = lazy.attach_stub(__name__, "subpackages.pyi")
```

Note that, since imports are now defined in `.pyi` files, those
are not only necessary for type checking but also at runtime.

The SPEC [describes this workaround in more
detail](https://scientific-python.org/specs/spec-0001/#type-checkers).

### Early failure

With lazy loading, missing imports no longer fail upon loading the
library. During development and testing, you can set the `EAGER_IMPORT`
environment variable to disable lazy loading.

### External libraries

The `lazy.attach` function discussed above is used to set up package
internal imports.

Use `lazy.load` to lazily import external libraries:

```python
sp = lazy.load('scipy')  # `sp` will only be loaded when accessed
sp.linalg.norm(...)
```

_Note that lazily importing *sub*packages,
i.e. `load('scipy.linalg')` will cause the package containing the
subpackage to be imported immediately; thus, this usage is
discouraged._

You can ask `lazy.load` to raise import errors as soon as it is called:

```python
linalg = lazy.load('scipy.linalg', error_on_import=True)
```

#### Optional requirements

One use for lazy loading is for loading optional dependencies, with
`ImportErrors` only arising when optional functionality is accessed. If optional
functionality depends on a specific version, a version requirement can
be set:

```python
np = lazy.load("numpy", require="numpy >=1.24")
```

In this case, if `numpy` is installed, but the version is less than 1.24,
the `np` module returned will raise an error on attribute access. Using
this feature is not all-or-nothing: One module may rely on one version of
numpy, while another module may not set any requirement.

_Note that the requirement must use the package [distribution name][] instead
of the module [import name][]. For example, the `pyyaml` distribution provides
the `yaml` module for import._

[distribution name]: https://packaging.python.org/en/latest/glossary/#term-Distribution-Package
[import name]: https://packaging.python.org/en/latest/glossary/#term-Import-Package

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "lazy-loader",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.7",
    "maintainer_email": null,
    "keywords": null,
    "author": "Scientific Python Developers",
    "author_email": null,
    "download_url": "https://files.pythonhosted.org/packages/6f/6b/c875b30a1ba490860c93da4cabf479e03f584eba06fe5963f6f6644653d8/lazy_loader-0.4.tar.gz",
    "platform": null,
    "description": "[![PyPI](https://img.shields.io/pypi/v/lazy_loader)](https://pypi.org/project/lazy_loader/)\n[![Test status](https://github.com/scientific-python/lazy_loader/workflows/test/badge.svg?branch=main)](https://github.com/scientific-python/lazy_loader/actions?query=workflow%3A%22test%22)\n[![Test coverage](https://codecov.io/gh/scientific-python/lazy_loader/branch/main/graph/badge.svg)](https://app.codecov.io/gh/scientific-python/lazy_loader/branch/main)\n\n`lazy_loader` makes it easy to load subpackages and functions on demand.\n\n## Motivation\n\n1. Allow subpackages to be made visible to users without incurring import costs.\n2. Allow external libraries to be imported only when used, improving import times.\n\nFor a more detailed discussion, see [the SPEC](https://scientific-python.org/specs/spec-0001/).\n\n## Installation\n\n```\npip install -U lazy_loader\n```\n\nWe recommend using `lazy_loader` with Python >= 3.11.\nIf using Python 3.11, please upgrade to 3.11.9 or later.\nIf using Python 3.12, please upgrade to 3.12.3 or later.\nThese versions [avoid](https://github.com/python/cpython/pull/114781) a [known race condition](https://github.com/python/cpython/issues/114763).\n\n## Usage\n\n### Lazily load subpackages\n\nConsider the `__init__.py` from [scikit-image](https://scikit-image.org):\n\n```python\nsubpackages = [\n    ...,\n    'filters',\n    ...\n]\n\nimport lazy_loader as lazy\n__getattr__, __dir__, _ = lazy.attach(__name__, subpackages)\n```\n\nYou can now do:\n\n```python\nimport skimage as ski\nski.filters.gaussian(...)\n```\n\nThe `filters` subpackages will only be loaded once accessed.\n\n### Lazily load subpackages and functions\n\nConsider `skimage/filters/__init__.py`:\n\n```python\nfrom ..util import lazy\n\n__getattr__, __dir__, __all__ = lazy.attach(\n    __name__,\n    submodules=['rank'],\n    submod_attrs={\n        '_gaussian': ['gaussian', 'difference_of_gaussians'],\n        'edges': ['sobel', 'scharr', 'prewitt', 'roberts',\n                  'laplace', 'farid']\n    }\n)\n```\n\nThe above is equivalent to:\n\n```python\nfrom . import rank\nfrom ._gaussian import gaussian, difference_of_gaussians\nfrom .edges import (sobel, scharr, prewitt, roberts,\n                    laplace, farid)\n```\n\nExcept that all subpackages (such as `rank`) and functions (such as `sobel`) are loaded upon access.\n\n### Type checkers\n\nStatic type checkers and IDEs cannot infer type information from\nlazily loaded imports. As a workaround you can load [type\nstubs](https://mypy.readthedocs.io/en/stable/stubs.html) (`.pyi`\nfiles) with `lazy.attach_stub`:\n\n```python\nimport lazy_loader as lazy\n__getattr__, __dir__, _ = lazy.attach_stub(__name__, \"subpackages.pyi\")\n```\n\nNote that, since imports are now defined in `.pyi` files, those\nare not only necessary for type checking but also at runtime.\n\nThe SPEC [describes this workaround in more\ndetail](https://scientific-python.org/specs/spec-0001/#type-checkers).\n\n### Early failure\n\nWith lazy loading, missing imports no longer fail upon loading the\nlibrary. During development and testing, you can set the `EAGER_IMPORT`\nenvironment variable to disable lazy loading.\n\n### External libraries\n\nThe `lazy.attach` function discussed above is used to set up package\ninternal imports.\n\nUse `lazy.load` to lazily import external libraries:\n\n```python\nsp = lazy.load('scipy')  # `sp` will only be loaded when accessed\nsp.linalg.norm(...)\n```\n\n_Note that lazily importing *sub*packages,\ni.e. `load('scipy.linalg')` will cause the package containing the\nsubpackage to be imported immediately; thus, this usage is\ndiscouraged._\n\nYou can ask `lazy.load` to raise import errors as soon as it is called:\n\n```python\nlinalg = lazy.load('scipy.linalg', error_on_import=True)\n```\n\n#### Optional requirements\n\nOne use for lazy loading is for loading optional dependencies, with\n`ImportErrors` only arising when optional functionality is accessed. If optional\nfunctionality depends on a specific version, a version requirement can\nbe set:\n\n```python\nnp = lazy.load(\"numpy\", require=\"numpy >=1.24\")\n```\n\nIn this case, if `numpy` is installed, but the version is less than 1.24,\nthe `np` module returned will raise an error on attribute access. Using\nthis feature is not all-or-nothing: One module may rely on one version of\nnumpy, while another module may not set any requirement.\n\n_Note that the requirement must use the package [distribution name][] instead\nof the module [import name][]. For example, the `pyyaml` distribution provides\nthe `yaml` module for import._\n\n[distribution name]: https://packaging.python.org/en/latest/glossary/#term-Distribution-Package\n[import name]: https://packaging.python.org/en/latest/glossary/#term-Import-Package\n",
    "bugtrack_url": null,
    "license": "BSD 3-Clause License  Copyright (c) 2022--2023, Scientific Python project All rights reserved.  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.  2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.  3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ",
    "summary": "Makes it easy to load subpackages and functions on demand.",
    "version": "0.4",
    "project_urls": {
        "Home": "https://scientific-python.org/specs/spec-0001/",
        "Source": "https://github.com/scientific-python/lazy_loader"
    },
    "split_keywords": [],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "8360d497a310bde3f01cb805196ac61b7ad6dc5dcf8dce66634dc34364b20b4f",
                "md5": "9f0ab8b0139a27988ac8e5447f21369e",
                "sha256": "342aa8e14d543a154047afb4ba8ef17f5563baad3fc610d7b15b213b0f119efc"
            },
            "downloads": -1,
            "filename": "lazy_loader-0.4-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "9f0ab8b0139a27988ac8e5447f21369e",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.7",
            "size": 12097,
            "upload_time": "2024-04-05T13:03:10",
            "upload_time_iso_8601": "2024-04-05T13:03:10.514426Z",
            "url": "https://files.pythonhosted.org/packages/83/60/d497a310bde3f01cb805196ac61b7ad6dc5dcf8dce66634dc34364b20b4f/lazy_loader-0.4-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "6f6bc875b30a1ba490860c93da4cabf479e03f584eba06fe5963f6f6644653d8",
                "md5": "0ed9a697d30fbe5b7f24106b448d634d",
                "sha256": "47c75182589b91a4e1a85a136c074285a5ad4d9f39c63e0d7fb76391c4574cd1"
            },
            "downloads": -1,
            "filename": "lazy_loader-0.4.tar.gz",
            "has_sig": false,
            "md5_digest": "0ed9a697d30fbe5b7f24106b448d634d",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.7",
            "size": 15431,
            "upload_time": "2024-04-05T13:03:12",
            "upload_time_iso_8601": "2024-04-05T13:03:12.261312Z",
            "url": "https://files.pythonhosted.org/packages/6f/6b/c875b30a1ba490860c93da4cabf479e03f584eba06fe5963f6f6644653d8/lazy_loader-0.4.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-04-05 13:03:12",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "scientific-python",
    "github_project": "lazy_loader",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "lazy-loader"
}
        
Elapsed time: 0.21111s