Skip to content

Entry-point discovery

The most realistic packaging story: a plugin is a separate installed distribution the host has never heard of. The host discovers it through a named entry-point group with one call:

pm.load_entrypoints("kitchen")

This reads importlib.metadata entry points - the standard library, no setuptools and no third-party dependency. Any installed package that advertises itself under the group is registered without the host importing it.

Declaring a plugin

A plugin package declares its entry point in pyproject.toml:

[project.entry-points.kitchen]
extra = "smoothie_extra"

After a plain install, load_entrypoints("kitchen") finds it. The host code does not change. This repo ships two such plugins:

  • pluginkit_tour.contrib.honey - an entry point inside the host's own distribution.
  • examples/external-plugin/ - an external uv project, installed alongside.

Resilient loading

A broken plugin should not take down discovery. load_entrypoints loads each plugin in isolation and, by default, raises a PluginValidationError naming the offending plugin. Pass ignore_errors=True to skip failures instead:

loaded = pm.load_entrypoints("kitchen", ignore_errors=True)

Already-registered and blocked names are skipped automatically.

For a production host that must continue and report every outcome, use the structured API:

report = pm.load_entrypoints_report("kitchen")
print(report.loaded, report.already_loaded, report.blocked)
for failure in report.failed:
    print(failure.name, failure.error)

This method always continues after individual failures and retains each original exception. The existing strict load_entrypoints() behavior and its partial progress semantics are unchanged.

Run it

make run DEMO=entrypoints
Discovered 2 plugin(s) via entry points
Registered plugins: ['honey', 'extra']
Smoothie: water, ice, honey, oats, chia seeds, almond butter

Why "entry points" and not "setuptools"

The method reads package metadata that every modern build backend writes (uv_build, hatchling, flit, setuptools). The name is historical; the mechanism is the importlib.metadata standard. setuptools is not installed in this project.