Skip to content
Snippets Groups Projects
Verified Commit 99454d48 authored by vimerbf's avatar vimerbf
Browse files

Update upstream source from tag 'upstream/0.3'

Update to upstream version '0.3'
with Debian dir 54e9f1e3ac117325744bb7d44d6c0ebf2e27b199
parents e75105a7 d7599380
No related branches found
No related tags found
No related merge requests found
# See:
#
# https://pycodestyle.readthedocs.io/en/latest/intro.html#error-codes (E, W)
# https://flake8.pycqa.org/en/latest/user/error-codes.html (F)
# https://github.com/PyCQA/flake8-bugbear
#
# for error codes. And
#
# https://flake8.pycqa.org/en/latest/user/violations.html#selecting-violations-with-flake8
#
# for error classes selected below.
[flake8]
max-line-length = 88
select = C,E,F,W,B,B950
ignore = E501, W503
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "monthly"
- package-ecosystem: "pip"
directory: "/"
schedule:
interval: "monthly"
......@@ -8,14 +8,14 @@ on:
jobs:
report:
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.10"]
steps:
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
......@@ -23,6 +23,8 @@ jobs:
run: |
python -m pip install --upgrade pip wheel setuptools
python -m pip install ".[test]"
python -m pip install --upgrade numpy
python -m pip uninstall --yes scipy
pip list
- name: Measure test coverage
......@@ -30,4 +32,6 @@ jobs:
python -m pytest --cov=lazy_loader --durations=10
# Tests fail if using `--doctest-modules`. I.e.,
# python -m pytest --cov=lazy_loader --doctest-modules --durations=20
codecov
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
......@@ -8,7 +8,17 @@ jobs:
strategy:
matrix:
os: [ubuntu, macos, windows]
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11-dev"]
python-version:
[
"3.7",
"3.8",
"3.9",
"3.10",
"3.11",
"3.12-dev",
"pypy-3.8",
"pypy-3.9",
]
steps:
- uses: actions/checkout@v3
......
......@@ -3,7 +3,7 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.3.0
rev: f71fa2c1f9cf5cb705f73dffe4b21f7c61470ba9 # v4.4.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
......@@ -15,27 +15,21 @@ repos:
- id: check-json
- id: check-toml
- id: check-added-large-files
- repo: https://github.com/psf/black
rev: 22.8.0
hooks:
- id: black
- repo: https://gitlab.com/pycqa/flake8
rev: 5.0.4
hooks:
- id: flake8
pass_filenames: true
- repo: https://github.com/pycqa/isort
rev: 5.10.1
hooks:
- id: isort
- repo: https://github.com/asottile/pyupgrade
rev: v2.38.0
hooks:
- id: pyupgrade
args: [--py37-plus]
- repo: https://github.com/pre-commit/mirrors-prettier
rev: v2.7.1
rev: 50c5478ed9e10bf360335449280cf2a67f4edb7a # v2.7.1
hooks:
- id: prettier
files: \.(html|md|yml|yaml|toml)
args: [--prose-wrap=preserve]
- repo: https://github.com/psf/black
rev: bf7a16254ec96b084a6caf3d435ec18f0f245cc7 # 23.3.0
hooks:
- id: black
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: 1ac904bbe451ef0b5a437d1d3b331a244c1f272c # v0.0.275
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix]
# Changelog
## [v0.3](https://github.com/scientific-python/lazy_loader/tree/v0.3) (2023-06-30)
[Full Changelog](https://github.com/scientific-python/lazy_loader/compare/v0.2...v0.3)
**Merged pull requests:**
- Announce Python 3.12 support [\#63](https://github.com/scientific-python/lazy_loader/pull/63) ([jarrodmillman](https://github.com/jarrodmillman))
- Ignore B028 [\#62](https://github.com/scientific-python/lazy_loader/pull/62) ([jarrodmillman](https://github.com/jarrodmillman))
- Use dependabot to update requirements [\#61](https://github.com/scientific-python/lazy_loader/pull/61) ([jarrodmillman](https://github.com/jarrodmillman))
- Use dependabot to update GH actions [\#60](https://github.com/scientific-python/lazy_loader/pull/60) ([jarrodmillman](https://github.com/jarrodmillman))
- Use ruff [\#59](https://github.com/scientific-python/lazy_loader/pull/59) ([jarrodmillman](https://github.com/jarrodmillman))
- Update requirements [\#58](https://github.com/scientific-python/lazy_loader/pull/58) ([jarrodmillman](https://github.com/jarrodmillman))
- Warn and discourage lazy.load of subpackages [\#57](https://github.com/scientific-python/lazy_loader/pull/57) ([dschult](https://github.com/dschult))
- Test on Python 3.12.0-beta.2 [\#53](https://github.com/scientific-python/lazy_loader/pull/53) ([jarrodmillman](https://github.com/jarrodmillman))
## [v0.2](https://github.com/scientific-python/lazy_loader/tree/v0.2)
[Full Changelog](https://github.com/scientific-python/lazy_loader/compare/v0.1...v0.2)
There were no changes since the release candidate, so
see release notes for v0.2rc0 below for details.
## [v0.2rc0](https://github.com/scientific-python/lazy_loader/tree/v0.2rc0)
[Full Changelog](https://github.com/scientific-python/lazy_loader/compare/v0.1...v0.2rc0)
**Closed issues:**
- Allow to not fail on stub attach in frozen apps [\#38](https://github.com/scientific-python/lazy_loader/issues/38)
- Stub files with absolute imports [\#36](https://github.com/scientific-python/lazy_loader/issues/36)
- Help to packaging Debian package [\#35](https://github.com/scientific-python/lazy_loader/issues/35)
- conda upload [\#33](https://github.com/scientific-python/lazy_loader/issues/33)
- Possible issues with partial lazy loading [\#32](https://github.com/scientific-python/lazy_loader/issues/32)
- Type hints/Mypy best practices? [\#28](https://github.com/scientific-python/lazy_loader/issues/28)
- Re-export non descendant attribute? [\#27](https://github.com/scientific-python/lazy_loader/issues/27)
- This is awesome [\#6](https://github.com/scientific-python/lazy_loader/issues/6)
**Merged pull requests:**
- Add information that `pyi` files are used in runtime when use `attach\_stub` [\#47](https://github.com/scientific-python/lazy_loader/pull/47) ([Czaki](https://github.com/Czaki))
- Update tests to improve coverage [\#45](https://github.com/scientific-python/lazy_loader/pull/45) ([jarrodmillman](https://github.com/jarrodmillman))
- Use codecov GH action [\#44](https://github.com/scientific-python/lazy_loader/pull/44) ([jarrodmillman](https://github.com/jarrodmillman))
- Update year [\#43](https://github.com/scientific-python/lazy_loader/pull/43) ([jarrodmillman](https://github.com/jarrodmillman))
- Update GH actions [\#42](https://github.com/scientific-python/lazy_loader/pull/42) ([jarrodmillman](https://github.com/jarrodmillman))
- Update pre-commit [\#41](https://github.com/scientific-python/lazy_loader/pull/41) ([jarrodmillman](https://github.com/jarrodmillman))
- Update optional depedencies [\#40](https://github.com/scientific-python/lazy_loader/pull/40) ([jarrodmillman](https://github.com/jarrodmillman))
- Fix extension substitution to work with `\*.pyc` files [\#39](https://github.com/scientific-python/lazy_loader/pull/39) ([Czaki](https://github.com/Czaki))
- Sort returned \_\_all\_\_ [\#34](https://github.com/scientific-python/lazy_loader/pull/34) ([stefanv](https://github.com/stefanv))
## [v0.1](https://github.com/scientific-python/lazy_loader/tree/v0.1) (2022-09-21)
[Full Changelog](https://github.com/scientific-python/lazy_loader/compare/v0.1rc3...v0.1)
......
BSD 3-Clause License
Copyright (c) 2022, Scientific Python project
Copyright (c) 2022--2023, Scientific Python project
All rights reserved.
Redistribution and use in source and binary forms, with or without
......
......@@ -77,7 +77,15 @@ Except that all subpackages (such as `rank`) and functions (such as `sobel`) are
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`.
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).
......@@ -96,10 +104,16 @@ internal imports.
Use `lazy.load` to lazily import external libraries:
```python
linalg = lazy.load('scipy.linalg') # `linalg` will only be loaded when accessed
sp = lazy.load('scipy') # `sp` will only be loaded when accessed
sp.linalg.norm(...)
```
You can also ask `lazy.load` to raise import errors as soon as it is called:
_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:
```
linalg = lazy.load('scipy.linalg', error_on_import=True)
......
lazy-loader (0.3-1) UNRELEASED; urgency=medium
* New upstream version 0.3
-- Bo YU <tsu.yubo@gmail.com> Sat, 08 Jul 2023 00:06:14 +0800
lazy-loader (0.1-2) unstable; urgency=medium
* Team upload.
......
......@@ -11,6 +11,7 @@ import inspect
import os
import sys
import types
import warnings
__all__ = ["attach", "load", "attach_stub"]
......@@ -66,7 +67,7 @@ def attach(package_name, submodules=None, submod_attrs=None):
attr: mod for mod, attrs in submod_attrs.items() for attr in attrs
}
__all__ = list(submodules | attr_to_modules.keys())
__all__ = sorted(submodules | attr_to_modules.keys())
def __getattr__(name):
if name in submodules:
......@@ -121,26 +122,36 @@ def load(fullname, error_on_import=False):
We often see the following pattern::
def myfunc():
from numpy import linalg as la
la.norm(...)
import numpy as np
np.norm(...)
....
This is to prevent a module, in this case `numpy`, from being
imported at function definition time, since that can be slow.
Putting the import inside the function prevents, in this case,
`numpy`, from being imported at function definition time.
That saves time if `myfunc` ends up not being called.
This function provides a proxy module that, upon access, imports
This `load` function returns a proxy module that, upon access, imports
the actual module. So the idiom equivalent to the above example is::
la = lazy.load("numpy.linalg")
np = lazy.load("numpy")
def myfunc():
la.norm(...)
np.norm(...)
....
The initial import time is fast because the actual import is delayed
until the first attribute is requested. The overall import time may
decrease as well for users that don't make use of large portions
of the library.
of your library.
Warning
-------
While lazily loading *sub*packages technically works, it causes the
package (that contains the subpackage) to be eagerly loaded even
if the package is already lazily loaded.
So, you probably shouldn't use subpackages with this `load` feature.
Instead you should encourage the package maintainers to use the
`lazy_loader.attach` to make their subpackages load lazily.
Parameters
----------
......@@ -148,7 +159,7 @@ def load(fullname, error_on_import=False):
The full name of the module or submodule to import. For example::
sp = lazy.load('scipy') # import scipy as sp
spla = lazy.load('scipy.linalg') # import scipy.linalg as spla
error_on_import : bool
Whether to postpone raising import errors until the module is accessed.
If set to `True`, import errors are raised as soon as `load` is called.
......@@ -165,6 +176,14 @@ def load(fullname, error_on_import=False):
except KeyError:
pass
if "." in fullname:
msg = (
"subpackages can technically be lazily loaded, but it causes the "
"package to be eagerly loaded even if it is already lazily loaded."
"So, you probably shouldn't use subpackages with this lazy feature."
)
warnings.warn(msg, RuntimeWarning)
spec = importlib.util.find_spec(fullname)
if spec is None:
if error_on_import:
......@@ -237,7 +256,9 @@ def attach_stub(package_name: str, filename: str):
If a stub file is not found for `filename`, or if the stubfile is formmated
incorrectly (e.g. if it contains an relative import from outside of the module)
"""
stubfile = filename if filename.endswith("i") else f"{filename}i"
stubfile = (
filename if filename.endswith("i") else f"{os.path.splitext(filename)[0]}.pyi"
)
if not os.path.exists(stubfile):
raise ValueError(f"Cannot load imports from non-existent stub {stubfile!r}")
......
import importlib
import sys
import types
......@@ -15,18 +16,28 @@ def test_lazy_import_basics():
# poor-mans pytest.raises for testing errors on attribute access
try:
anything_not_real.pi
assert False # Should not get here
raise AssertionError() # Should not get here
except ModuleNotFoundError:
pass
assert isinstance(anything_not_real, lazy.DelayedImportErrorModule)
# see if it changes for second access
try:
anything_not_real.pi
assert False # Should not get here
raise AssertionError() # Should not get here
except ModuleNotFoundError:
pass
def test_lazy_import_subpackages():
with pytest.warns(RuntimeWarning):
hp = lazy.load("html.parser")
assert "html" in sys.modules
assert type(sys.modules["html"]) == type(pytest)
assert isinstance(hp, importlib.util._LazyModule)
assert "html.parser" in sys.modules
assert sys.modules["html.parser"] == hp
def test_lazy_import_impact_on_sys_modules():
math = lazy.load("math")
anything_not_real = lazy.load("anything_not_real")
......@@ -49,22 +60,16 @@ def test_lazy_import_impact_on_sys_modules():
def test_lazy_import_nonbuiltins():
sp = lazy.load("scipy")
np = lazy.load("numpy")
sp = lazy.load("scipy")
if not isinstance(np, lazy.DelayedImportErrorModule):
assert np.sin(np.pi) == pytest.approx(0, 1e-6)
if isinstance(sp, lazy.DelayedImportErrorModule):
try:
sp.pi
assert False
except ModuleNotFoundError:
pass
elif isinstance(np, lazy.DelayedImportErrorModule):
try:
np.sin(np.pi)
assert False
raise AssertionError()
except ModuleNotFoundError:
pass
else:
assert np.sin(sp.pi) == pytest.approx(0, 1e-6)
def test_lazy_attach():
......
[build-system]
requires = ["flit_core >=3.7,<4"]
requires = ["flit_core >=3.8,<4"]
build-backend = "flit_core.buildapi"
[project]
name = "lazy_loader"
version = "0.1"
version = "0.3"
requires-python = ">=3.7"
authors = [{name = "Scientific Python Developers"}]
readme = "README.md"
......@@ -18,13 +18,14 @@ classifiers = [
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
]
dynamic = ["description"]
[project.optional-dependencies]
test = ["pytest >= 7.1", "pytest-cov >= 3.0", "codecov >= 2.1"]
lint = ["pre-commit >= 2.20"]
test = ["pytest >= 7.4", "pytest-cov >= 4.1"]
lint = ["pre-commit >= 3.3"]
[project.urls]
Home = "https://scientific-python.org/specs/spec-0001/"
......@@ -32,3 +33,20 @@ Source = "https://github.com/scientific-python/lazy_loader"
[tool.flit.sdist]
exclude = ["tests/*"]
[tool.ruff]
line-length = 88
target-version = "py37"
select = [
"C",
"E",
"F",
"W",
"B",
"I",
"UP",
]
ignore = ["B018", "B028"]
exclude = [
"lazy_loader/tests/fake_pkg/__init__.pyi",
]
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment