{"id":9986,"library":"npe2","title":"napari Plugin Engine v2 (npe2)","description":"npe2 (napari plugin engine v2) is the modern, robust plugin system for napari. It facilitates explicit plugin discovery and contribution management through manifest files and package entry points, aiming for better isolation, explicit dependency management, and improved testability compared to its predecessor. The current version is 0.8.2, and it follows the napari release cycle, with frequent updates during active development phases.","status":"active","version":"0.8.2","language":"en","source_language":"en","source_url":"https://github.com/napari/npe2","tags":["napari","plugins","plugin-engine","GUI","imaging"],"install":[{"cmd":"pip install npe2","lang":"bash","label":"Install npe2"}],"dependencies":[{"reason":"npe2 is the plugin engine for napari. While npe2 itself doesn't directly depend on napari for its core logic, it is meaningless without a napari environment to provide and consume plugins. Most users interact with npe2 through napari.","package":"napari","optional":false}],"imports":[{"symbol":"PluginManager","correct":"from npe2 import PluginManager"},{"note":"Primarily used by plugin developers to create or manipulate manifest objects directly, less common for general users.","symbol":"Manifest","correct":"from npe2.manifest import Manifest"},{"note":"This is napari's primary interface for its plugin system, which internally uses npe2. Often the preferred way to interact with plugins when napari is running.","symbol":"napari_plugin_manager","correct":"from napari.plugins.manager import napari_plugin_manager"}],"quickstart":{"code":"from npe2 import PluginManager\n\npm = PluginManager.instance() # Get the singleton PluginManager instance\n\n# Discover all plugins, including older npe1 plugins if present\npm.discover(include_npe1=True)\n\nprint(f\"Discovered {len(pm.plugins)} plugin packages.\")\n\n# Example: List contributions from a specific plugin (e.g., 'napari-svg')\n# This assumes 'napari-svg' is installed and has contributions\nif \"napari-svg\" in pm.plugins:\n    print(f\"\\nContributions from napari-svg:\")\n    for contribution_type in pm.get_plugin_contributions(\"napari-svg\"):\n        contributions = pm.get_plugin_contributions(\"napari-svg\")[contribution_type]\n        if contributions:\n            print(f\"  {contribution_type}: {list(contributions.keys())}\")\nelse:\n    print(\"\\nnapari-svg not found or has no contributions. Try another installed plugin.\")\n","lang":"python","description":"This quickstart demonstrates how to initialize the npe2 PluginManager, discover available plugins (including npe1 plugins), and then inspect the contributions provided by a specific plugin. It shows how the engine itself can be used to query the plugin ecosystem."},"warnings":[{"fix":"Plugin developers must create a `napari.yaml` manifest file and update `pyproject.toml` or `setup.cfg` with a `napari.plugin` entry point. Refer to npe2 migration guides and the `napari` plugin tutorial for details.","message":"Migration from npe1 (legacy) to npe2 (modern) requires significant changes for plugin developers. npe2 introduces a manifest-based plugin declaration system, replacing the implicit `napari_` prefixed package discovery of npe1. Plugins developed for npe1 will not be discovered or function correctly under npe2 without migration.","severity":"breaking","affected_versions":"All napari versions using npe2 (typically napari>=0.4.16)."},{"fix":"Verify that your plugin's `pyproject.toml` (or `setup.cfg`) contains a `[project.entry-points.\"napari.plugin\"]` entry pointing to a valid `napari.yaml` file relative to your package root. Ensure the plugin package is correctly installed.","message":"npe2 plugin discovery is explicit and relies on correctly configured package entry points and `napari.yaml` manifests. If a plugin's `pyproject.toml` or `setup.cfg` is not correctly configured, or if the `napari.yaml` manifest is missing or malformed, the plugin will not be found by the PluginManager.","severity":"gotcha","affected_versions":"All npe2 versions."},{"fix":"If you need to discover and interact with legacy `npe1` plugins directly through `npe2.PluginManager`, ensure you call `pm.discover(include_npe1=True)`.","message":"The `PluginManager.discover()` method has an `include_npe1` argument (default `False` when called directly). If this is not set to `True`, older `npe1` plugins will not be discovered by the standalone `npe2.PluginManager`. Note that `napari`'s internal plugin manager often sets this to `True` for compatibility.","severity":"gotcha","affected_versions":"All npe2 versions."}],"env_vars":null,"last_verified":"2026-04-17T00:00:00.000Z","next_check":"2026-07-16T00:00:00.000Z","problems":[{"fix":"1. Ensure the plugin package is installed (`pip install my-plugin`). 2. Verify the plugin's `pyproject.toml` (or `setup.cfg`) has a correct `[project.entry-points.\"napari.plugin\"]` entry pointing to its `napari.yaml` manifest. 3. Ensure the `napari.yaml` file exists at the specified relative path.","cause":"The specified plugin's manifest could not be discovered or loaded by the `npe2.PluginManager`. This often means the plugin is not correctly installed or its entry points are misconfigured.","error":"KeyError: 'Plugin \"my-plugin\" not found'"},{"fix":"Check the `napari.plugin` entry point configuration to ensure the path is correct relative to the package root, and that the `napari.yaml` file is present in the plugin's source and installed package.","cause":"The path specified in the `napari.plugin` entry point (in `pyproject.toml` or `setup.cfg`) does not match the actual location of the `napari.yaml` manifest file within the installed plugin package.","error":"FileNotFoundError: [Errno 2] No such file or directory: '/path/to/my_plugin/napari.yaml'"},{"fix":"Use the `PluginManager`'s methods to retrieve and execute the actual callable. For example, use `pm.execute_command(\"my-plugin.my_command_id\", **kwargs)` or `pm.get_function_contributions(\"my-plugin\")` to get the functions.","cause":"You are likely trying to directly call a string identifier (e.g., a `command_id` or `function_id`) instead of the actual Python callable it represents. `npe2` contributions are often registered as identifiers.","error":"TypeError: 'str' object is not callable"}]}