Skip to content

fix(pip): normalize names in list_freeze_parse and detect modern pip …#68784

Open
cdalvaro wants to merge 1 commit intosaltstack:masterfrom
cdalvaro:bugfix/install_pip_packages_with_modern_pip
Open

fix(pip): normalize names in list_freeze_parse and detect modern pip …#68784
cdalvaro wants to merge 1 commit intosaltstack:masterfrom
cdalvaro:bugfix/install_pip_packages_with_modern_pip

Conversation

@cdalvaro
Copy link
Contributor

@cdalvaro cdalvaro commented Mar 5, 2026

What does this PR do?

Two related bugs in the pip state and module cause a Python package to be "installed" (and reported as changed) on every Salt state run, even when the package is already at the correct version.

Bug 1 — list_freeze_parse does not normalize package names

Commit 68728e6 updated list_() to return normalized package names (lowercase, hyphens) via normalize(). However, list_freeze_parse, which is the fallback used for pip < 9.0, was not updated. It still returns names exactly as they appear in pip freeze output (e.g. "requests_oauthlib" with an underscore).

Because _check_if_installed now receives a normalized prefix (e.g. "requests-oauthlib") and compares it against a CaseInsensitiveDict that only handles case — not underscore vs. hyphen — the lookup always fails. The package is added to target_pkgs and pip is called on every run.

Bug 2 — Post-install detection uses an outdated pip message

After calling pip.install, the state checks pip's stdout to determine whether a package was already present, to avoid reporting it as a change.

The check was:

if line.startswith("Requirement already up-to-date: "):

Modern pip (≥ 10.0) outputs "Requirement already satisfied: ..." instead.

Because the message never matched, already_installed_packages stayed empty and every pip call resulted in the package being reported as "Installed" in the state changes dict.

Fix

  • salt/modules/pip.pylist_freeze_parse now computes a normal_prefix and stores each package under its normalized name (normalize(name)), consistent with list_().
  • salt/states/pip_state.py — The post-install check now also matches "Requirement already satisfied: ". The package name is extracted by stripping any version specifier with re.split, then normalized with pip.normalize before being stored in already_installed_packages. The comparison with prefix (already normalized) no longer calls .lower() unnecessarily.

Merge requirements satisfied?

Commits signed with GPG?

Yes

@cdalvaro cdalvaro requested a review from a team as a code owner March 5, 2026 13:09
@cdalvaro cdalvaro changed the title fix(pip): normalize names in list_freeze_parse and detect modern pip … Draft: fix(pip): normalize names in list_freeze_parse and detect modern pip … Mar 5, 2026
@cdalvaro cdalvaro changed the base branch from 3006.x to master March 5, 2026 14:42
@cdalvaro cdalvaro force-pushed the bugfix/install_pip_packages_with_modern_pip branch from 25fdad8 to 201df65 Compare March 5, 2026 14:49
@cdalvaro cdalvaro changed the title Draft: fix(pip): normalize names in list_freeze_parse and detect modern pip … fix(pip): normalize names in list_freeze_parse and detect modern pip … Mar 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant