Skip to main content
Glama

Python Dependency Manager Companion

by KemingHe
hooks.mdβ€’8.1 kB
# Lifecycle and Hooks As any Python deliverable, your project will go through the different phases of a Python project lifecycle and PDM provides commands to perform the expected tasks for those phases. It also provides hooks attached to these steps allowing for: - plugins to listen to the [signals][pdm.signals] of the same name. - developers to define custom scripts with the same name. Besides, `pre_invoke` signal is emitted before ANY command is invoked, allowing plugins to modify the project or options beforehand. The built-in commands are currently split into 3 groups: - the [initialization phase](#initialization) - the [dependencies management](#dependencies-management). - the [publication phase](#publication). You will most probably need to perform some recurrent tasks between the installation and publication phases (housekeeping, linting, testing, ...) this is why PDM lets you define your own tasks/phases using [user scripts](#user-scripts). To provides full flexibility, PDM allows to [skip some hooks and tasks](#skipping) on demand. ## Initialization The initialization phase should occur only once in a project lifetime by running the [`pdm init`](../reference/cli.md#init) command to initialize an existing project (prompt to fill the `pyproject.toml` file). They trigger the following hooks: - [`post_init`][pdm.signals.post_init] ```mermaid flowchart LR subgraph pdm-init [pdm init] direction LR post-init{{Emit post_init}} init --> post-init end ``` ## Dependencies management The dependencies management is required for the developer to be able to work and perform the following: - `lock`: compute a lock file from the `pyproject.toml` requirements. - `sync`: synchronize (add/remove/update) PEP582 packages from the lock file and install the current project as editable. - `add`: add a dependency - `remove`: remove a dependency All those steps are directly available with the following commands: - [`pdm lock`](../reference/cli.md#lock): execute the `lock` task - [`pdm sync`](../reference/cli.md#sync): execute the `sync` task - [`pdm install`](../reference/cli.md#install): execute the `sync` task, preceded from `lock` if required - [`pdm add`](../reference/cli.md#add): add a dependency requirement, re-lock and then sync - [`pdm remove`](../reference/cli.md#remove): remove a dependency requirement, re-lock and then sync - [`pdm update`](../reference/cli.md#update): re-lock dependencies from their latest versions and then sync They trigger the following hooks: - [`pre_install`][pdm.signals.pre_install] - [`post_install`][pdm.signals.post_install] - [`pre_lock`][pdm.signals.pre_lock] - [`post_lock`][pdm.signals.post_lock] ```mermaid flowchart LR subgraph pdm-install [pdm install] direction LR subgraph pdm-lock [pdm lock] direction TB pre-lock{{Emit pre_lock}} post-lock{{Emit post_lock}} pre-lock --> lock --> post-lock end subgraph pdm-sync [pdm sync] direction TB pre-install{{Emit pre_install}} post-install{{Emit post_install}} pre-install --> sync --> post-install end pdm-lock --> pdm-sync end ``` ### Switching Python version This is a special case in dependency management: you can switch the current Python version using [`pdm use`](../reference/cli.md#use) and it will emit the [`post_use`][pdm.signals.post_use] signal with the new Python interpreter. ```mermaid flowchart LR subgraph pdm-use [pdm use] direction LR post-use{{Emit post_use}} use --> post-use end ``` ## Publication As soon as you are ready to publish your package/library, you will require the publication tasks: - `build`: build/compile assets requiring it and package everything into a Python package (sdist, wheel) - `upload`: upload/publish the package to a remote PyPI index All those steps are available with the following commands: - [`pdm build`](../reference/cli.md#build) - [`pdm publish`](../reference/cli.md#publish) They trigger the following hooks: - [`pre_publish`][pdm.signals.pre_publish] - [`post_publish`][pdm.signals.post_publish] - [`pre_build`][pdm.signals.pre_build] - [`post_build`][pdm.signals.post_build] ```mermaid flowchart LR subgraph pdm-publish [pdm publish] direction LR pre-publish{{Emit pre_publish}} post-publish{{Emit post_publish}} subgraph pdm-build [pdm build] pre-build{{Emit pre_build}} post-build{{Emit post_build}} pre-build --> build --> post-build end %% subgraph pdm-upload [pdm upload] %% pre-upload{{Emit pre_upload}} %% post-upload{{Emit post_upload}} %% pre-upload --> upload --> post-upload %% end pre-publish --> pdm-build --> upload --> post-publish end ``` Execution will stop at first failure, hooks included. ## User scripts [User scripts are detailed in their own section](scripts.md) but you should know that: - each user script can define a `pre_*` and `post_*` script, including composite scripts. - each `run` execution will trigger the [`pre_run`][pdm.signals.pre_run] and [`post_run`][pdm.signals.post_run] hooks - each script execution will trigger the [`pre_script`][pdm.signals.pre_script] and [`post_script`][pdm.signals.post_script] hooks Given the following `scripts` definition: ```toml [tool.pdm.scripts] pre_script = "" post_script = "" pre_test = "" post_test = "" test = "" pre_composite = "" post_composite = "" composite = {composite = ["test"]} ``` a `pdm run test` will have the following lifecycle: ```mermaid flowchart LR subgraph pdm-run-test [pdm run test] direction LR pre-run{{Emit pre_run}} post-run{{Emit post_run}} subgraph run-test [test task] direction TB pre-script{{Emit pre_script}} post-script{{Emit post_script}} pre-test[Execute pre_test] post-test[Execute post_test] test[Execute test] pre-script --> pre-test --> test --> post-test --> post-script end pre-run --> run-test --> post-run end ``` while `pdm run composite` will have the following: ```mermaid flowchart LR subgraph pdm-run-composite [pdm run composite] direction LR pre-run{{Emit pre_run}} post-run{{Emit post_run}} subgraph run-composite [composite task] direction TB pre-script-composite{{Emit pre_script}} post-script-composite{{Emit post_script}} pre-composite[Execute pre_composite] post-composite[Execute post_composite] subgraph run-test [test task] direction TB pre-script-test{{Emit pre_script}} post-script-test{{Emit post_script}} pre-test[Execute pre_test] post-test[Execute post_test] pre-script-test --> pre-test --> test --> post-test --> post-script-test end pre-script-composite --> pre-composite --> run-test --> post-composite --> post-script-composite end pre-run --> run-composite --> post-run end ``` ## Skipping It is possible to control which task and hook runs for any built-in command as well as custom user scripts using the `--skip` option. It accepts a comma-separated list of hooks/task names to skip as well as the predefined `:all`, `:pre` and `:post` shortcuts respectively skipping all hooks, all `pre_*` hooks and all `post_*` hooks. You can also provide the skip list in `PDM_SKIP_HOOKS` environment variable but it will be overridden as soon as the `--skip` parameter is provided. Given the previous script block, running `pdm run --skip=:pre,post_test composite` will result in the following reduced lifecycle: ```mermaid flowchart LR subgraph pdm-run-composite [pdm run composite] direction LR post-run{{Emit post_run}} subgraph run-composite [composite task] direction TB post-script-composite{{Emit post_script}} post-composite[Execute post_composite] subgraph run-test [test task] direction TB post-script-test{{Emit post_script}} test --> post-script-test end run-test --> post-composite --> post-script-composite end run-composite --> post-run end ```

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/KemingHe/python-dependency-manager-companion-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server