blob: 4ce911622e62c9f3a7f2a77e92aa00b7743e5fa6 [file] [edit]
#####################
Plugin architecture
#####################
This page explains how virtualenv's plugin system works internally.
**************
Entry points
**************
virtualenv uses Python entry points (``setuptools`` / ``importlib.metadata``) to discover plugins. Each plugin registers
under one of four entry point groups:
- ``virtualenv.discovery``
- ``virtualenv.create``
- ``virtualenv.seed``
- ``virtualenv.activate``
At startup, virtualenv loads all registered entry points from these groups and makes them available as CLI options.
Built-in implementations are registered in virtualenv's own ``pyproject.toml``, while third-party plugins register their
entry points in their own package metadata.
When a package with virtualenv plugins is installed in the same environment as virtualenv, the plugins become
immediately available without additional configuration.
******************
Plugin lifecycle
******************
The following diagram shows how plugins are discovered and executed:
.. mermaid::
sequenceDiagram
participant User
participant CLI
participant EntryPoints
participant Discovery
participant Creator
participant Seeder
participant Activator
rect rgba(37, 99, 235, 0.15)
User->>CLI: virtualenv myenv
CLI->>EntryPoints: Load plugins from all groups
EntryPoints-->>CLI: Available plugins
CLI->>CLI: Build argument parser with plugin options
CLI->>User: Parse CLI arguments
User-->>CLI: Selected options
end
rect rgba(22, 163, 106, 0.15)
CLI->>Discovery: Run selected discovery plugin
Discovery-->>CLI: PythonInfo
CLI->>Creator: Create environment with PythonInfo
Creator-->>CLI: Created environment
CLI->>Seeder: Seed packages into environment
Seeder-->>CLI: Seeded environment
CLI->>Activator: Generate activation scripts
Activator-->>CLI: Complete environment
end
The lifecycle follows these stages:
1. virtualenv starts and discovers all entry points from the four plugin groups
2. The CLI parser is built dynamically, incorporating options from all discovered plugins
3. User arguments are parsed to select which discovery, creator, seeder, and activator plugins to use
4. Selected plugins execute in sequence: discover create seed activate
5. Each stage passes its output to the next stage
************************
Extension point design
************************
Each extension point follows a consistent pattern:
Base abstract class
Each extension point defines a base abstract class (``Discover``, ``Creator``, ``Seeder``, ``Activator``) that
specifies the interface plugins must implement.
Built-in implementations
virtualenv includes built-in implementations registered as entry points in its own ``pyproject.toml``. For example,
the built-in CPython creator is registered as ``cpython3-posix``.
Third-party plugins
External packages implement the base interface and register their own entry points under the same group. When
installed, they appear alongside built-in options.
CLI selection
Command-line flags (``--discovery``, ``--creator``, ``--seeder``, ``--activators``) allow users to select which
implementation to use. Multiple activators can be selected simultaneously.
Parser integration
Each plugin can contribute CLI arguments through the ``add_parser_arguments`` classmethod. These arguments appear in
``virtualenv --help`` and are available when the plugin is selected.
**********************
How plugins interact
**********************
Plugins execute in a pipeline where each stage depends on the previous one:
Discovery Creator
The discovery plugin produces a ``PythonInfo`` object describing the source Python interpreter. This object contains
metadata about the Python version, platform, paths, and capabilities. The creator plugin receives this
``PythonInfo`` and uses it to determine how to build the virtual environment structure.
Creator Seeder
The creator plugin produces a ``Creator`` object representing the newly created virtual environment. This includes
paths to the environment's ``bin`` directory, site-packages, and Python executable. The seeder plugin uses these
paths to install packages.
Seeder → Activator
After seeding completes, activator plugins use the ``Creator`` object to generate shell activation scripts. These
scripts reference the environment's bin directory and other paths to configure the shell environment.
This pipeline ensures that each plugin has the information it needs from previous stages. The ``PythonInfo`` flows from
discovery to creator, and the ``Creator`` object flows from creator to both seeder and activators.
Plugin isolation
================
Plugins within the same extension point do not interact with each other. Only one discovery and one creator plugin can
run per invocation, though multiple activators can run simultaneously. This isolation keeps plugins simple and focused
on their specific task.