pip install optional_dependencies
This package allows for easy construction of checks for optional dependencies.
As every Python project can have its own unique set of optional dependencies,
optional_dependencies
provides the enum.Enum
base class
OptionalDependencyEnum
for enumerating the optional dependencies.
A constructed OptionalDependencyEnum
enum.Enum
has members that
are the package names with values that are either a
packaging.Version
or a NOT_INSTALLED
sentinel value.
As an example:
# Note that `auto` is a convenience re-export of enum.auto
from optional_dependencies import OptionalDependencyEnum, auto
class OptDeps(OptionalDependencyEnum):
PACKAGING = auto()
THIS_IS_NOT_INSTALLED = auto()
OptDeps.PACKAGING
# <OptDeps.PACKAGING: <Version('...')>>
OptDeps.PACKAGING.installed
# True
OptDeps.PACKAGING.version
# <Version('...')>
OptDeps.THIS_IS_NOT_INSTALLED
# <OptDeps.THIS_IS_NOT_A_PACKAGE: <InstalledState.NOT_INSTALLED: False>>
enum.auto
on a OptionalDependencyEnum
passes version parsing to
packaging.utils.canonicalize_name
then
importlib.metadata.version
then packaging.version.parse
. If the package cannot be found
then it is considered InstalledState.NOT_INSTALLED
InstalledState.NOT_INSTALLED
is an enum.Enum
member that has a
truthy value of False
. This can be useful for boolean checks, as
packaging.Version
always has a truthy value of True
.
if not OptDeps.THIS_IS_NOT_INSTALLED:
print("NOT_INSTALLED has a truthy value of False")
# NOT_INSTALLED has a truthy value of False
if OptDeps.PACKAGING: # truthy value of `True`
print(OptDeps.PACKAGING)
# OptDeps.PACKAGING
Sometimes the high-level API is insufficient to determine whether an optional dependency is present. For example, this can sometimes happen with compiled packages, where the package appears to be installed, but something is wrong. In these cases you can customize the enum members using the low-level API.
The low-level functions are:
-
optional_dependencies.utils.is_installed(pkg_name: str, /) -> bool
: a regularized form ofimportlib.util.find_spec
. -
optional_dependencies.utils.get_version(pkg_name: str, /) -> Version | Literal[InstalledState.NOT_INSTALLED]
: for getting thepackaging.Version
of a package if it is installed, or returningNOT_INSTALLED
otherwise. -
optional_dependencies.utils.chain_checks(version: Version, /, *checks: bool)
: for chaining checks together and ensuring the returned value is still apackaging.Version
orNOT_INSTALLED
.
As a pseudo-code example of a package with c-compiled code that :
from optional_dependencies.utils import is_installed, get_version, chain_checks
# A subpackage needs to be checked.
chain_checks(get_version("package1"), is_installed("package1.subpackage"))
# <Version('...')>
# This package is not installed correctly
chain_checks(get_version("package2"), is_installed("package2.subpackage"))
# <InstalledState.NOT_INSTALLED: False>
The low-level API can be used with OptionalDependencyEnum
class OptDeps(OptionalDependencyEnum):
PACKAGING = auto()
THIS_IS_NOT_INSTALLED = chain_checks(
get_version("package2"), is_installed("package2.subpackage")
)
If you found this library to be useful and want to support the development and maintenance of lower-level code libraries for the scientific community, please consider citing this work.
We welcome contributions!