fix(show): pick the env-compatible version for duplicated lock entries - #11003
fix(show): pick the env-compatible version for duplicated lock entries#11003tarann26 wants to merge 2 commits into
Conversation
`poetry show <package>` selected the first lock-file entry matching the package name, ignoring environment markers. When poetry.lock contains several marker-conditioned entries for the same package (e.g. one per platform), the single-package view could report a version that does not apply to the current environment, disagreeing with the all-packages `poetry show`. Compute the environment-appropriate locked packages the same way the all-packages path does, via a shared `_required_locked_packages` helper, and select the matching entry from that set. Fall back to the first match when none applies so the command still displays a version.
There was a problem hiding this comment.
Hey - I've found 1 issue
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="tests/console/commands/test_show.py" line_range="1918-1927" />
<code_context>
+def test_show_single_package_with_duplicate_falls_back_when_env_excluded_8945(
</code_context>
<issue_to_address>
**suggestion (testing):** Fallback behavior when no env-compatible duplicate exists is only tested for text output; JSON output for the same scenario is untested.
Since the new env-compatible test already parametrizes `output_format` for both text and JSON, it would be good to do the same here so the fallback-to-first-match behavior is covered for `-f json` as well as text. You can either parametrize this test with `output_format_parametrize` to include JSON, or add a dedicated JSON test using `tester.execute("cachy -f json")` and asserting the result still falls back to version `0.1.0` when no lock entry matches the current environment.
Suggested implementation:
```python
@pytest.mark.parametrize("output_format", output_format_parametrize)
def test_show_single_package_with_duplicate_falls_back_when_env_excluded_8945(
tester: CommandTester,
poetry: Poetry,
installed: Repository,
repo: DummyRepository,
output_format: str,
) -> None:
```
To fully implement the suggestion, the body of `test_show_single_package_with_duplicate_falls_back_when_env_excluded_8945` must be updated to:
1. Use `output_format` when invoking the command, e.g. `tester.execute(["show", "cachy", "-f", output_format])` or matching whatever convention other `output_format_parametrize` tests in this file already use.
2. Add conditional assertions similar to the existing env-compatible duplicate test:
- For JSON: `result = json.loads(tester.io.fetch_output()); assert result["version"] == "0.1.0"`.
- For text: `output = tester.io.fetch_output(); assert "0.1.0" in output` and assert that no other duplicate version is shown (e.g. `"0.1.1" not in output`), matching the expected fallback-to-first-match behavior.
3. Ensure any setup that currently assumes text output (e.g. checking strings directly) is moved under the `else` branch, with JSON-specific checks under the `if "json" in output_format:` branch, consistent with the pattern used in the existing parametrized duplicate-env-compatible test above.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| def test_show_single_package_with_duplicate_falls_back_when_env_excluded_8945( | ||
| tester: CommandTester, | ||
| poetry: Poetry, | ||
| installed: Repository, | ||
| repo: DummyRepository, | ||
| ) -> None: | ||
| # https://github.com/python-poetry/poetry/issues/8945 | ||
| # If none of the duplicate lock entries applies to the current environment, | ||
| # `poetry show <package>` should still display a version (the first match) | ||
| # rather than raising. |
There was a problem hiding this comment.
suggestion (testing): Fallback behavior when no env-compatible duplicate exists is only tested for text output; JSON output for the same scenario is untested.
Since the new env-compatible test already parametrizes output_format for both text and JSON, it would be good to do the same here so the fallback-to-first-match behavior is covered for -f json as well as text. You can either parametrize this test with output_format_parametrize to include JSON, or add a dedicated JSON test using tester.execute("cachy -f json") and asserting the result still falls back to version 0.1.0 when no lock entry matches the current environment.
Suggested implementation:
@pytest.mark.parametrize("output_format", output_format_parametrize)
def test_show_single_package_with_duplicate_falls_back_when_env_excluded_8945(
tester: CommandTester,
poetry: Poetry,
installed: Repository,
repo: DummyRepository,
output_format: str,
) -> None:To fully implement the suggestion, the body of test_show_single_package_with_duplicate_falls_back_when_env_excluded_8945 must be updated to:
- Use
output_formatwhen invoking the command, e.g.tester.execute(["show", "cachy", "-f", output_format])or matching whatever convention otheroutput_format_parametrizetests in this file already use. - Add conditional assertions similar to the existing env-compatible duplicate test:
- For JSON:
result = json.loads(tester.io.fetch_output()); assert result["version"] == "0.1.0". - For text:
output = tester.io.fetch_output(); assert "0.1.0" in outputand assert that no other duplicate version is shown (e.g."0.1.1" not in output), matching the expected fallback-to-first-match behavior.
- For JSON:
- Ensure any setup that currently assumes text output (e.g. checking strings directly) is moved under the
elsebranch, with JSON-specific checks under theif "json" in output_format:branch, consistent with the pattern used in the existing parametrized duplicate-env-compatible test above.
Parametrize test_show_single_package_with_duplicate_falls_back_when_env_excluded_8945 over text and json output, matching the env-compatible duplicate test, so the fall-back-to-first-match behaviour is verified for both formats.
Pull Request Check List
Resolves: #8945
Problem
poetry show <package>reports the wrong version when the lock file contains multiple entries for the same package (e.g. marker-conditioned variants for different Python versions or platforms)._display_single_package_information()picks the first name-match and ignores environment markers:So
poetry show <pkg>can print a different version thanpoetry show(all packages) does for the same environment — the two views disagree, and the single-package view is the wrong one.Fix
Make the single-package path select the environment-appropriate entry the same way the all-packages path already does. The solver-based environment resolution (
Solver(...).use_environment(self.env)→required_locked_packages) is extracted into a shared helper_required_locked_packages()used by both paths, so they can no longer disagree.To keep the common case free of any new cost, the solver is only consulted when a package actually has more than one lock entry; for the usual single-entry case, selection and output are byte-identical to before. If none of the duplicate entries applies to the current environment, it falls back to the first match (so
showstill displays something rather than erroring). The fix is marker-agnostic — it works forpython_version,sys_platform, and any other environment markers, since it defers entirely to the solver's environment resolution.Note on a behaviour change
Because the single-package path now reuses the group-activated project root (needed so its selection matches the all-packages view),
poetry show <pkg>now validates--only/--with/--withoutgroup names the same waypoetry showalready does: an undeclared group name now raisesGroupNotFoundErrorinstead of being silently ignored. Valid invocations and the plainpoetry show <pkg>are unaffected. Happy to scope this out (only activate groups when duplicates are present) if you'd prefer to preserve the previous lenient behaviour for the single-package path.Test
Adds tests in
tests/console/commands/test_show.py(mirroringtest_show_hides_incompatible_package_with_duplicate): a package with two marker-conditioned lock entries is shown with the environment-appropriate version, in both text and JSON output, plus a fallback case for when no entry applies to the current environment.