Skip to content

Commit 4b5a038

Browse files
authored
Feature/optional dependencies (#387)
Add import_optional_dependency util function
1 parent f3a19b1 commit 4b5a038

2 files changed

Lines changed: 65 additions & 0 deletions

File tree

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ dependencies = [
3939
"pydicom>=3.0.1",
4040
"pyjpegls>=1.0.0",
4141
"typing-extensions>=4.0.0",
42+
"packaging>=25.0"
4243
]
4344

4445
[project.optional-dependencies]

src/highdicom/_dependency_utils.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
from importlib import import_module, metadata
2+
from packaging.requirements import Requirement
3+
from types import ModuleType
4+
5+
6+
def import_optional_dependency(
7+
module_name: str,
8+
feature: str
9+
) -> ModuleType:
10+
"""Import an optional dependency.
11+
12+
This function is designed to support interaction with other common
13+
libraries that are not required for `highdicom` by default.
14+
15+
Parameters
16+
----------
17+
module_name: str
18+
Name of the module to be imported.
19+
feature: str
20+
Name or description of the feature that requires this dependency.
21+
This is used for improving the clarity of error messages.
22+
23+
Returns
24+
-------
25+
ModuleType:
26+
Imported module.
27+
28+
Raises
29+
------
30+
ImportError:
31+
When the specified module cannot be imported.
32+
33+
"""
34+
for req_str in metadata.requires('highdicom'):
35+
req = Requirement(req_str)
36+
if req.name == module_name:
37+
break
38+
39+
else:
40+
raise ValueError(
41+
f'`{module_name}` is not a requirement of highdicom '
42+
f'but is required for {feature}.'
43+
)
44+
45+
try:
46+
module = import_module(name=module_name)
47+
48+
except ImportError as error:
49+
raise ImportError(
50+
f'Optional dependency `{module_name}` could not be imported'
51+
f' but is required for {feature}.'
52+
f' highdicom requires {module_name}{req.specifier}.'
53+
) from error
54+
55+
installed_version = metadata.version(module_name)
56+
57+
if installed_version not in req.specifier:
58+
raise ImportError(
59+
f'Optional dependency `{module_name}` has an unsuitable '
60+
f'version. Found {module_name}=={installed_version}, but '
61+
f'highdicom requires {module_name}{req.specifier}.'
62+
)
63+
64+
return module

0 commit comments

Comments
 (0)