In your "plugin loader" (whatever happens to find the entry point, either by name or by enumerating the full set of available entry points for a given namespace) you need to do something like the following:
import pkg_resources
# Get a reference to an EntryPoint, somehow.
plug = pkg_resources.get_entry_info('pip', 'console_scripts', 'pip')
# This is sub-optimal because it raises on the first failure.
# Can't capture a full list of failed dependencies.
# plug.require()
# Instead, we find the individual dependencies.
failed = []
for extra in sorted(plug.extras):
if extra not in plug.dist._dep_map:
continue # Not actually a valid extras_require dependency?
for requirement in i.dist._dep_map[extra]:
try:
pkg_resources.require(str(requirement))
except pkg_resources.DistributionNotFound:
failed.append((plug.name, extra, str(requirement)))
And there we go; for a given plugin you'll get a list of failed dependencies (or not failed
in the event of success) listing the entry_point
plugin name, [foo]
extra tag, and specific unsatisfied package requirement.
An example of this in action comes from the web.command package's web versions --namespace
sub-command. Note how the waitress
extras_require
is satisfied, where the gevent
one is explicitly specifying the gevent
package is missing:

Unfortunately I don't actually have a multiple-dependency entry_point
example handy to show, and it's important to note that the package listed as "missing" might not always match up with the name of the extras_require
.