Skip to content

Comments

Add support for processing .pth files in project plugins#10661

Merged
radoering merged 13 commits intopython-poetry:mainfrom
BlackGad:main
Dec 30, 2025
Merged

Add support for processing .pth files in project plugins#10661
radoering merged 13 commits intopython-poetry:mainfrom
BlackGad:main

Conversation

@BlackGad
Copy link
Contributor

@BlackGad BlackGad commented Dec 16, 2025

Handle .pth files for plugins in editable mode.

Pull Request Check List

Related to: #6742, #6529

  • Added tests for changed code.
  • Updated documentation for changed code.

Summary by Sourcery

Handle plugin .pth files when loading plugins so editable/develop-mode plugins have their dependencies available.

New Features:

  • Process .pth files for plugin distributions when loading plugin entry points to make editable-mode plugin dependencies available.

Documentation:

  • Document support for installing plugins in editable mode using path dependencies with develop = true, including an example in the plugin configuration docs.

Tests:

  • Add tests covering plugin loading behavior when a .pth file is present, absent, or when the distribution has no files.

@sourcery-ai
Copy link

sourcery-ai bot commented Dec 16, 2025

Reviewer's Guide

Adds support for processing .pth files when loading plugins so editable/develop-installed plugins have their dependencies available, with accompanying tests and documentation updates.

Sequence diagram for loading a plugin with .pth processing

sequenceDiagram
    actor Developer
    participant PoetryCLI
    participant PluginManager
    participant EntryPoint as metadata_EntryPoint
    participant Dist as Distribution
    participant Site as site_addpackage
    participant PluginClass

    Developer->>PoetryCLI: run poetry command
    PoetryCLI->>PluginManager: load_plugins()
    PluginManager->>EntryPoint: _load_plugin_entry_point(ep)
    EntryPoint-->>PluginManager: ep with dist and files

    PluginManager->>Dist: check ep.dist and ep.dist.files
    Dist-->>PluginManager: list of files including pth_file
    PluginManager->>PluginManager: locate pth_file
    PluginManager->>PluginManager: pth_path = Path(ep.dist.locate_file(pth_file))
    PluginManager->>Site: addpackage(str(pth_path.parent), pth_path.name, None)

    PluginManager->>EntryPoint: ep.load()
    EntryPoint-->>PluginManager: PluginClass
    PluginManager->>PluginManager: issubclass(PluginClass, Plugin or ApplicationPlugin)
    PluginManager-->>PoetryCLI: plugin loaded with dependencies available
    PoetryCLI-->>Developer: command executes using plugin
Loading

File-Level Changes

Change Details Files
Process .pth files for plugin distributions during entry point loading to support editable/develop installs.
  • Extend plugin entry point loading to inspect the distribution’s files for any .pth file.
  • Locate and resolve the .pth file path from the distribution.
  • Call site.addpackage with the resolved .pth path so that paths specified in the .pth file are added before loading the plugin.
  • Guard .pth handling for missing distributions and for distributions with no files.
src/poetry/plugins/plugin_manager.py
Add tests verifying .pth handling behavior when loading plugins.
  • Add test ensuring a .pth file for a plugin distribution is detected, processed via site.addpackage, and the plugin loads successfully.
  • Add test ensuring no addpackage call when the distribution has an empty files list.
  • Add test ensuring no addpackage call when the distribution.files attribute is None, while still loading the plugin.
tests/plugins/test_plugin_manager.py
Document editable plugin installation via path dependencies for plugin development.
  • Update plugin documentation to show an example of a plugin installed from a path with develop = true.
  • Clarify that plugins can be installed in editable mode using path dependencies, which is useful during development.
docs/plugins.md

Assessment against linked issues

Issue Objective Addressed Explanation
#6742 Allow poetry self add to correctly install plugins from local directory paths (e.g., poetry self add ../mypoetryplugin) as advertised in the help output. The PR only adds logic to process .pth files when loading already-installed plugins (handling editable/develop mode) and updates plugin documentation accordingly. It does not modify the poetry self add command or dependency resolution for path-based plugins, so it does not fix the failure to add a plugin from a local directory.

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey there - I've reviewed your changes - here's some feedback:

  • The inline from site import addpackage inside _load_plugin_entry_point would be clearer and more conventional as a top-level import, avoiding repeated imports and making dependencies of the module more obvious.
  • The if ep.dist and (pth_file := next((f for f in (ep.dist.files or []) if f.suffix == ".pth"), None)): line is quite dense; consider extracting the .pth detection into a small helper method to improve readability and make the behaviour easier to test in isolation.
  • Currently only the first .pth file found is processed; if a distribution can reasonably have multiple .pth files, consider iterating over all matching files instead of short-circuiting on the first one.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The inline `from site import addpackage` inside `_load_plugin_entry_point` would be clearer and more conventional as a top-level import, avoiding repeated imports and making dependencies of the module more obvious.
- The `if ep.dist and (pth_file := next((f for f in (ep.dist.files or []) if f.suffix == ".pth"), None)):` line is quite dense; consider extracting the `.pth` detection into a small helper method to improve readability and make the behaviour easier to test in isolation.
- Currently only the first `.pth` file found is processed; if a distribution can reasonably have multiple `.pth` files, consider iterating over all matching files instead of short-circuiting on the first one.

## Individual Comments

### Comment 1
<location> `tests/plugins/test_plugin_manager.py:179-191` </location>
<code_context>
+    mock_ep.dist = mock_dist
+    mock_ep.load.return_value = MyPlugin
+
+    mock_addpackage = mocker.patch("site.addpackage")
+    mocker.patch.object(metadata, "entry_points", return_value=[mock_ep])
+
+    manager = manager_factory()
+    manager.load_plugins()
+
+    mock_addpackage.assert_called_once_with(
+        str(pth_file_path.parent), pth_file_path.name, None
+    )
+    assert len(manager._plugins) == 1
+
+
</code_context>

<issue_to_address>
**suggestion (testing):** Consider asserting that `.pth` processing happens before the plugin is loaded

The key behavior to verify is that the `.pth` side effects occur before the plugin is imported. Right now you only assert that `addpackage` is called, not that it happens before `ep.load`. Consider making `mock_ep.load` a `Mock`/spy as well and asserting call order (e.g. with `mocker.spy` + `assert_has_calls` or by comparing the recorded calls) so the test guards against regressions where these calls are reordered.

```suggestion
    mock_ep.dist = mock_dist

    mock_addpackage = mocker.patch("site.addpackage")
    mocker.patch.object(metadata, "entry_points", return_value=[mock_ep])

    def _load_side_effect(*args, **kwargs):
        # Ensure .pth processing (via site.addpackage) happens before plugin load
        assert mock_addpackage.called
        return MyPlugin

    mock_ep.load.side_effect = _load_side_effect

    manager = manager_factory()
    manager.load_plugins()

    mock_addpackage.assert_called_once_with(
        str(pth_file_path.parent), pth_file_path.name, None
    )
    assert len(manager._plugins) == 1
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@BlackGad
Copy link
Contributor Author

@radoering Hi! Can you make review of this PR?

@BlackGad
Copy link
Contributor Author

Any update on this?

@BlackGad BlackGad requested a review from radoering December 29, 2025 16:21
@Odechree

This comment was marked as spam.

@radoering radoering added the impact/docs Contains or requires documentation changes label Dec 30, 2025
@github-actions
Copy link

Deploy preview for website ready!

✅ Preview
https://website-7phf6mi81-python-poetry.vercel.app

Built with commit fb4c2a9.
This pull request is being automatically deployed with vercel-action

@radoering radoering changed the title Add support for processing .pth files in plugins Add support for processing .pth files in project plugins Dec 30, 2025
@radoering radoering merged commit f0b5263 into python-poetry:main Dec 30, 2025
57 checks passed
@BlackGad
Copy link
Contributor Author

@radoering Thank you!

mwalbeck pushed a commit to mwalbeck/docker-python-poetry that referenced this pull request Jan 19, 2026
This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [poetry](https://github.com/python-poetry/poetry) ([changelog](https://python-poetry.org/history/)) | minor | ` 2.2.1` -> `2.3.0` |

---

### Release Notes

<details>
<summary>python-poetry/poetry (poetry)</summary>

### [`v2.3.0`](https://github.com/python-poetry/poetry/blob/HEAD/CHANGELOG.md#230---2026-01-18)

[Compare Source](python-poetry/poetry@2.2.1...2.3.0)

##### Added

- **Add support for exporting `pylock.toml` files with `poetry-plugin-export`** ([#&#8203;10677](python-poetry/poetry#10677)).
- Add support for specifying build constraints for dependencies ([#&#8203;10388](python-poetry/poetry#10388)).
- Add support for publishing artifacts whose version is determined dynamically by the build-backend ([#&#8203;10644](python-poetry/poetry#10644)).
- Add support for editable project plugins ([#&#8203;10661](python-poetry/poetry#10661)).
- Check `requires-poetry` before any other validation ([#&#8203;10593](python-poetry/poetry#10593)).
- Validate the content of `project.readme` when running `poetry check` ([#&#8203;10604](python-poetry/poetry#10604)).
- Add the option to clear all caches by making the cache name in `poetry cache clear` optional ([#&#8203;10627](python-poetry/poetry#10627)).
- Automatically update the cache for packages where the locked files differ from cached files ([#&#8203;10657](python-poetry/poetry#10657)).
- Suggest to clear the cache if running a command with `--no-cache` solves an issue ([#&#8203;10585](python-poetry/poetry#10585)).
- Propose `poetry init` when trying `poetry new` for an existing directory ([#&#8203;10563](python-poetry/poetry#10563)).
- Add support for `poetry publish --skip-existing` for new Nexus OSS versions ([#&#8203;10603](python-poetry/poetry#10603)).
- Show Poetry's own Python's path in `poetry debug info` ([#&#8203;10588](python-poetry/poetry#10588)).

##### Changed

- **Drop support for Python 3.9** ([#&#8203;10634](python-poetry/poetry#10634)).
- **Change the default of `installer.re-resolve` from `true` to `false`** ([#&#8203;10622](python-poetry/poetry#10622)).
- **PEP 735 dependency groups are considered in the lock file hash** ([#&#8203;10621](python-poetry/poetry#10621)).
- Deprecate `poetry.utils._compat.metadata`, which is sometimes used in plugins, in favor of `importlib.metadata` ([#&#8203;10634](python-poetry/poetry#10634)).
- Improve managing free-threaded Python versions with `poetry python` ([#&#8203;10606](python-poetry/poetry#10606)).
- Prefer JSON API to HTML API in legacy repositories ([#&#8203;10672](python-poetry/poetry#10672)).
- When running `poetry init`, only add the readme field in the `pyproject.toml` if the readme file exists ([#&#8203;10679](python-poetry/poetry#10679)).
- Raise an error if no hash can be determined for any distribution link of a package ([#&#8203;10673](python-poetry/poetry#10673)).
- Require `dulwich>=0.25.0` ([#&#8203;10674](python-poetry/poetry#10674)).

##### Fixed

- Fix an issue where `poetry remove` did not work for PEP 735 dependency groups with `include-group` items ([#&#8203;10587](python-poetry/poetry#10587)).
- Fix an issue where `poetry remove` caused dangling `include-group` references in PEP 735 dependency groups ([#&#8203;10590](python-poetry/poetry#10590)).
- Fix an issue where `poetry add` did not work for PEP 735 dependency groups with `include-group` items ([#&#8203;10636](python-poetry/poetry#10636)).
- Fix an issue where PEP 735 dependency groups were not considered in the lock file hash ([#&#8203;10621](python-poetry/poetry#10621)).
- Fix an issue where wrong markers were locked for a dependency that was required by several groups with different markers ([#&#8203;10613](python-poetry/poetry#10613)).
- Fix an issue where non-deterministic markers were created in a method used by `poetry-plugin-export` ([#&#8203;10667](python-poetry/poetry#10667)).
- Fix an issue where wrong wheels were chosen for installation in free-threaded Python environments if Poetry itself was not installed with free-threaded Python ([#&#8203;10614](python-poetry/poetry#10614)).
- Fix an issue where `poetry publish` used the metadata of the project instead of the metadata of the build artifact ([#&#8203;10624](python-poetry/poetry#10624)).
- Fix an issue where `poetry env use` just used another Python version instead of failing when the requested version was not supported by the project ([#&#8203;10685](python-poetry/poetry#10685)).
- Fix an issue where `poetry env activate` returned the wrong command for `dash` ([#&#8203;10696](python-poetry/poetry#10696)).
- Fix an issue where `data-dir` and `python.installation-dir` could not be set ([#&#8203;10595](python-poetry/poetry#10595)).
- Fix an issue where Python and pip executables were not correctly detected on Windows ([#&#8203;10645](python-poetry/poetry#10645)).
- Fix an issue where invalid template variables in `virtualenvs.prompt` caused an incomprehensible error message ([#&#8203;10648](python-poetry/poetry#10648)).

##### Docs

- Add a warning about `~/.netrc` for Poetry credential configuration ([#&#8203;10630](python-poetry/poetry#10630)).
- Clarify that the local configuration takes precedence over the global configuration ([#&#8203;10676](python-poetry/poetry#10676)).
- Add an explanation in which cases `packages` are automatically detected ([#&#8203;10680](python-poetry/poetry#10680)).

##### poetry-core ([`2.3.0`](https://github.com/python-poetry/poetry-core/releases/tag/2.3.0))

- Normalize versions ([#&#8203;893](python-poetry/poetry-core#893)).
- Fix an issue where unsatisfiable requirements did not raise an error ([#&#8203;891](python-poetry/poetry-core#891)).
- Fix an issue where the implicit main group did not exist if it was explicitly declared as not having any dependencies ([#&#8203;892](python-poetry/poetry-core#892)).
- Fix an issue where `python_full_version` markers with pre-release versions were parsed incorrectly ([#&#8203;893](python-poetry/poetry-core#893)).

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS4xNDYuMCIsInVwZGF0ZWRJblZlciI6IjQxLjE0Ni4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Reviewed-on: https://git.walbeck.it/walbeck-it/docker-python-poetry/pulls/1654
Co-authored-by: renovate-bot <[email protected]>
Co-committed-by: renovate-bot <[email protected]>
@github-actions
Copy link

This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jan 30, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

impact/docs Contains or requires documentation changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants