Skip to content

Print friendly plugin names, and print both plugins' names for conflicting plugins - #16166

Merged
kenodegard merged 24 commits into
conda:mainfrom
agriyakhetarpal:conda-plugins-conflict
Jun 29, 2026
Merged

Print friendly plugin names, and print both plugins' names for conflicting plugins#16166
kenodegard merged 24 commits into
conda:mainfrom
agriyakhetarpal:conda-plugins-conflict

Conversation

@agriyakhetarpal

@agriyakhetarpal agriyakhetarpal commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

Description

In the CI for a project at wntrblm/nox#1095, I recently ran into the following error:

PluginError: Conflicting plugins found for `post_solves`:

  - CondaPostSolve(name='signature-verification', action=<conda.trust.signature_verification._SignatureVerification object at 0x10774b770>)

Multiple conda plugins are registered via the `conda_post_solves` hook. Please make sure that you don't have any incompatible plugins installed.

The reason for this is that the CI setup uses conda 25.11.1 with setup-miniconda@v3. That means there is an older version of conda that still implements the signature-verification post_solves hook, and a newer conda-content-trust that does the same. In this scenario, run_constrained: conda-content-trust >=0.3.0 was added only with conda 26.3.

After talking to @kenodegard and @jaimergp, we can do two things, which this PR does:

  1. Use importlib.metadata.packages_distributions to output friendly plugin names. We fall back to the raw pluggy plugin name in case this isn't possible, which may happen when plugin developers perform editable installations, and they should understand a module path just fine. However, this won't be the case for a majority of plugin users, of course.
  2. Restructure the conflict detection for plugins from a flat list to one where we print out plugins grouped by name, so both sides of each conflict appear on the same line.

Therefore, the old output was - CondaPostSolve(name='signature-verification', action=<...object...>), and the new output should be something along the lines of - 'signature-verification' provided by: split on one line per provider, like this (for example):

Conflicting plugins found for `<hook>`:
  - 'archspec' provided by:
    - conda 26.1.0
    - conda-content-trust 0.2.0

Checklist - did you ...

  • Add a file to the news directory (using the template) for the next release's release notes?
  • Add / update necessary tests?
  • Add / update outdated documentation?

@agriyakhetarpal
agriyakhetarpal requested a review from a team as a code owner June 1, 2026 10:07
@github-project-automation github-project-automation Bot moved this to 🆕 New in 🔎 Review Jun 1, 2026
@conda-bot conda-bot added the cla-signed [bot] added once the contributor has signed the CLA label Jun 1, 2026
@codspeed-hq

codspeed-hq Bot commented Jun 1, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 35 untouched benchmarks
⏩ 25 skipped benchmarks1


Comparing agriyakhetarpal:conda-plugins-conflict (06bf417) with main (4572fe6)

Open in CodSpeed

Footnotes

  1. 25 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@agriyakhetarpal

Copy link
Copy Markdown
Contributor Author

The test failures are unrelated; it looks like the tests are getting cancelled for some reason. Thanks!

Comment thread conda/plugins/manager.py Outdated
log = logging.getLogger(__name__)


def _plugin_source(impl_plugin_name: str) -> str:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nice followup to the impl.plugin_name work from #15840

there are probably other places adding this distname+version would also be useful (e.g., conda info)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in cb8cf6a and 76473fc. There are some other uses of plugin names, but these two are the only ones that are applicable in this context.

Comment thread conda/plugins/manager.py Outdated
lines = []
for conflict_name, conflicting in sorted(conflict_groups.items()):
providers = dashlist(
[_plugin_source(p.impl.plugin_name) for p in conflicting],

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Let's also sort the list of conflicts:

Suggested change
[_plugin_source(p.impl.plugin_name) for p in conflicting],
[_plugin_source(p.impl.plugin_name) for p in sorted(conflicting)],

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks! Noting here that CondaPlugin dataclasses don't have an lt dunder, so I had to do sorted(conflicting, key=lambda p: p.impl.plugin_name) for this, to sort by the string plugin name.

Comment thread tests/plugins/test_manager.py Outdated
Comment thread conda/plugins/manager.py Outdated
@danyeaw danyeaw moved this from Sorting ⚙️ to Refinement 🃏 in conda Roadmap and Sprint Planning Jun 3, 2026
@danyeaw danyeaw moved this from Refinement 🃏 to In Progress 🏗️ in conda Roadmap and Sprint Planning Jun 3, 2026
@danyeaw danyeaw moved this from In Progress 🏗️ to In review 🔍 in conda Roadmap and Sprint Planning Jun 3, 2026
@jezdez

jezdez commented Jun 3, 2026

Copy link
Copy Markdown
Member

I opened agriyakhetarpal#5 as a concrete sketch for the plugin-manager-method version of this change.

Comment thread conda/cli/main_info.py Outdated
Comment thread conda/plugins/manager.py Outdated
Co-Authored-By: Ken Odegard <4546435+kenodegard@users.noreply.github.com>
@agriyakhetarpal

Copy link
Copy Markdown
Contributor Author

I think we might need to harden get_canonical_name a bit so that we can be more helpful:

from conda.base.context import context
from conda.plugins.hookspec import hookimpl
from conda.plugins.types import CondaSolver
from conda.exceptions import PluginError

pm = context.plugin_manager

class IntruderSolver:
    @hookimpl
    def conda_solvers(self):
        yield CondaSolver(name='classic', backend=object)

pm.register(IntruderSolver())

try:
    pm.get_hook_results('solvers')
except PluginError as e:
    print(str(e))

which gets us

Conflicting plugins found for `solvers`:

  - 'classic' provided by:
    - <unknown_module>.IntruderSolver[4392487968]
    - conda.plugins.solvers

Multiple conda plugins are registered via the `conda_solvers` hook. Please make sure that you don't have any incompatible plugins installed.

agriyakhetarpal and others added 2 commits June 4, 2026 09:15
Co-Authored-By: Ken Odegard <4546435+kenodegard@users.noreply.github.com>
@jezdez

jezdez commented Jun 9, 2026

Copy link
Copy Markdown
Member

I opened agriyakhetarpal#6 as a follow-up for the remaining review tweaks: hardening canonical names for registered plugin instances, tightening the conflict-message tests, and clarifying the entry point bookkeeping/news wording.

@github-actions

github-actions Bot commented Jun 22, 2026

Copy link
Copy Markdown

🐰 Bencher Report

Branchconda-plugins-conflict
Testbedubuntu-22.04
Click to view all benchmark results
Benchmark
tests/cli/test_startup_benchmarks.py::test_context_init
tests/cli/test_startup_benchmarks.py::test_generate_parser
tests/cli/test_startup_benchmarks.py::test_import_cli_main
tests/cli/test_startup_benchmarks.py::test_import_conda_argparse
tests/cli/test_startup_benchmarks.py::test_import_context
tests/cli/test_startup_benchmarks.py::test_version_main
tests/cli/test_subcommands.py::test_env_create[classic]
tests/cli/test_subcommands.py::test_env_create[libmamba]
tests/cli/test_subcommands.py::test_env_list_benchmark[classic]
tests/cli/test_subcommands.py::test_env_list_benchmark[libmamba]
tests/cli/test_subcommands.py::test_env_update[classic]
tests/cli/test_subcommands.py::test_env_update[libmamba]
tests/cli/test_subcommands.py::test_install[classic]
tests/cli/test_subcommands.py::test_install[libmamba]
tests/cli/test_subcommands.py::test_list[classic]
tests/cli/test_subcommands.py::test_list[libmamba]
tests/cli/test_subcommands.py::test_run[classic]
tests/cli/test_subcommands.py::test_run[libmamba]
tests/cli/test_subcommands.py::test_update[classic-update]
tests/cli/test_subcommands.py::test_update[classic-upgrade]
tests/cli/test_subcommands.py::test_update[libmamba-update]
tests/cli/test_subcommands.py::test_update[libmamba-upgrade]
tests/core/test_solve.py::test_solve_1[classic]
tests/core/test_solve.py::test_solve_1[libmamba]
tests/models/test_match_spec.py::test_match_1
tests/shards/test_shards_subset.py::test_traversal_algorithm_benchmarks[devops_automation-bfs-cold]
tests/shards/test_shards_subset.py::test_traversal_algorithm_benchmarks[devops_automation-bfs-warm]
tests/shards/test_shards_subset.py::test_traversal_algorithm_benchmarks[devops_automation-pipelined-cold]
tests/shards/test_shards_subset.py::test_traversal_algorithm_benchmarks[devops_automation-pipelined-warm]
tests/shards/test_shards_subset.py::test_traversal_algorithm_benchmarks[python-bfs-cold]
tests/shards/test_shards_subset.py::test_traversal_algorithm_benchmarks[python-bfs-warm]
tests/shards/test_shards_subset.py::test_traversal_algorithm_benchmarks[python-pipelined-cold]
tests/shards/test_shards_subset.py::test_traversal_algorithm_benchmarks[python-pipelined-warm]
🐰 View full continuous benchmarking report in Bencher

Comment thread conda/cli/main_info.py Outdated
Comment thread conda/cli/main_info.py Outdated
Comment thread conda/plugins/manager.py Outdated
@github-project-automation github-project-automation Bot moved this from 🆕 New to 🏗️ In Progress in 🔎 Review Jun 24, 2026
Co-Authored-By: Ken Odegard <4546435+kenodegard@users.noreply.github.com>
@agriyakhetarpal

Copy link
Copy Markdown
Contributor Author

Thanks @kenodegard, makes sense to me!

@github-project-automation github-project-automation Bot moved this from 🏗️ In Progress to ✅ Approved in 🔎 Review Jun 24, 2026
@kenodegard
kenodegard enabled auto-merge (squash) June 29, 2026 19:42
@kenodegard
kenodegard merged commit 01a1dec into conda:main Jun 29, 2026
89 checks passed
@github-project-automation github-project-automation Bot moved this from In review 🔍 to Done 💪🏾 in conda Roadmap and Sprint Planning Jun 30, 2026
@agriyakhetarpal
agriyakhetarpal deleted the conda-plugins-conflict branch June 30, 2026 00:15
@github-project-automation github-project-automation Bot moved this from ✅ Approved to 🏁 Done in 🔎 Review Jun 30, 2026
@travishathaway travishathaway mentioned this pull request Jul 7, 2026
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla-signed [bot] added once the contributor has signed the CLA

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

5 participants