-
Notifications
You must be signed in to change notification settings - Fork 930
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add guide on how to handle missing extras
- Loading branch information
1 parent
363e4a6
commit debb36e
Showing
1 changed file
with
66 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
.. _handling-missing-extras-at-runtime: | ||
|
||
============================================================ | ||
Handling missing optional dependencies ("extras") at runtime | ||
============================================================ | ||
|
||
If your package has :ref:`optional dependencies ("extras") | ||
<metadata_provides_extra>` which the package consumer hasn't installed, the | ||
default outcome is an ordinary `ModuleNotFoundError` exception being raised at | ||
the first attempted import of a missing module. | ||
|
||
This can make for a bad user experience, because there is no guidance about why | ||
the module is missing - users might think they've found a bug. If you're not | ||
careful, it can even make your package unusable without the extras installed, | ||
e.g. if your package is a library that imports the affected modules from the | ||
top-level module or from the application entry point if it's an application. | ||
|
||
As of the time of writing, there is no *great* way to handle this issue in | ||
the Python packaging ecosystem, but there are a few options that might be | ||
better than nothing: | ||
|
||
|
||
Overall approach | ||
================ | ||
|
||
TODO General guidance about how to isolate imports in question | ||
|
||
TODO Optimistic vs pessimistic handling? | ||
|
||
|
||
Handling failing imports | ||
======================== | ||
|
||
TODO example | ||
|
||
TODO mention it doesn't check versions, so a bit dangerous | ||
|
||
|
||
Using ``pkg_resources`` | ||
======================= | ||
|
||
The now-deprecated ``pkg_resources`` package (part of the ``setuptools`` | ||
distribution) provides a ``require`` function that you can use to check if a | ||
given optional dependency of your package is installed or not: | ||
|
||
|
||
.. code-block:: python | ||
from pkg_resources import require, DistributionNotFound, VersionConflict | ||
try: | ||
require(["your-package-name[your-extra]"]) | ||
except DistributionNotFound: | ||
... # handle package(s) not being installed at all | ||
except VersionConflict: | ||
... # handle version mismatches | ||
Unfortunately, no replacement for this functionality exists in the | ||
``pkg_resources``'s successor packages yet | ||
(`packaging-problems #664 <packaging-problems #664>`_). | ||
|
||
|
||
------------------ | ||
|
||
.. _packaging-problems-664: https://github.com/pypa/packaging-problems/issues/664 | ||
|