Skip to content

Commit 5373f1e

Browse files
committed
RF: Split requirement check into function, prefer importlib.metadata
1 parent 5bd725d commit 5373f1e

File tree

3 files changed

+37
-24
lines changed

3 files changed

+37
-24
lines changed

lazy_loader/__init__.py

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -194,27 +194,15 @@ def myfunc():
194194
if not have_module:
195195
not_found_message = f"No module named '{fullname}'"
196196
elif require is not None:
197-
import packaging.requirements
198-
199-
try:
200-
import importlib_metadata
201-
except ImportError:
202-
import importlib.metadata as importlib_metadata
203-
204-
req = packaging.requirements.Requirement(require)
205197
try:
206-
have_module = req.specifier.contains(
207-
importlib_metadata.version(req.name),
208-
prereleases=True,
209-
)
210-
except importlib_metadata.PackageNotFoundError as e:
198+
have_module = _check_requirement(require)
199+
except ModuleNotFoundError as e:
211200
raise ValueError(
212201
f"Found module '{fullname}' but cannot test requirement '{require}'. "
213202
"Requirements must match distribution name, not module name."
214203
) from e
215204

216-
if not have_module:
217-
not_found_message = f"No distribution can be found matching '{require}'"
205+
not_found_message = f"No distribution can be found matching '{require}'"
218206

219207
if not have_module:
220208
if error_on_import:
@@ -247,6 +235,37 @@ def myfunc():
247235
return module
248236

249237

238+
def _check_requirement(require: str) -> bool:
239+
"""Verify that a package requirement is satisfied
240+
241+
If the package is required, a ``ModuleNotFoundError`` is raised
242+
by ``importlib.metadata``.
243+
244+
Parameters
245+
----------
246+
require : str
247+
A dependency requirement as defined in PEP-508
248+
249+
Returns
250+
-------
251+
satisfied : bool
252+
True if the installed version of the dependency matches
253+
the specified version, False otherwise.
254+
"""
255+
import packaging.requirements
256+
257+
try:
258+
import importlib.metadata as importlib_metadata
259+
except ImportError: # PY37
260+
import importlib_metadata
261+
262+
req = packaging.requirements.Requirement(require)
263+
return req.specifier.contains(
264+
importlib_metadata.version(req.name),
265+
prereleases=True,
266+
)
267+
268+
250269
def have_module(module_like: types.ModuleType) -> bool:
251270
return not isinstance(module_like, DelayedImportErrorModule)
252271

lazy_loader/tests/test_lazy_loader.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,6 @@
77

88
import lazy_loader as lazy
99

10-
try:
11-
import importlib_metadata # noqa
12-
13-
have_importlib_metadata = True
14-
except ImportError:
15-
have_importlib_metadata = False
16-
1710

1811
def test_lazy_import_basics():
1912
math = lazy.load("math")
@@ -160,7 +153,8 @@ def test_stub_loading_errors(tmp_path):
160153

161154

162155
def test_require_kwarg():
163-
dot = "_" if have_importlib_metadata else "."
156+
have_importlib_metadata = importlib.util.find_spec("importlib.metadata") is not None
157+
dot = "." if have_importlib_metadata else "_"
164158
# Test with a module that definitely exists, behavior hinges on requirement
165159
with mock.patch(f"importlib{dot}metadata.version") as version:
166160
version.return_value = "1.0.0"

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ classifiers = [
2323
description = "Makes it easy to load subpackages and functions on demand."
2424
dependencies = [
2525
"packaging",
26-
"importlib_metadata; python_version < '3.9'",
26+
"importlib_metadata; python_version < '3.8'",
2727
]
2828

2929
[project.optional-dependencies]

0 commit comments

Comments
 (0)