Fix pip idempotence in check mode
PIP package names must be case insensitive, and must consider hyphens and underscores to be equivalent (https://www.python.org/dev/peps/pep-0426/#name), because of this the module didn't work correctly in check mode. For example if the passed package name had a different case or an underscore instead of a hyphen (or the other way around) compared to the installed package, check mode reported as changed, even though packages were installed. Now the module ignores case and hyphens/underscores in package names, so check mode works correctly.
This commit is contained in:
parent
96c2375692
commit
b89b688d52
3 changed files with 33 additions and 2 deletions
|
@ -0,0 +1,2 @@
|
||||||
|
bugfixes:
|
||||||
|
- "pip - idempotence in check mode now works correctly."
|
|
@ -350,10 +350,11 @@ def _is_present(module, req, installed_pkgs, pkg_command):
|
||||||
for pkg in installed_pkgs:
|
for pkg in installed_pkgs:
|
||||||
if '==' in pkg:
|
if '==' in pkg:
|
||||||
pkg_name, pkg_version = pkg.split('==')
|
pkg_name, pkg_version = pkg.split('==')
|
||||||
|
pkg_name = Package.canonicalize_name(pkg_name)
|
||||||
else:
|
else:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if pkg_name.lower() == req.package_name and req.is_satisfied_by(pkg_version):
|
if pkg_name == req.package_name and req.is_satisfied_by(pkg_version):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
@ -499,6 +500,8 @@ class Package:
|
||||||
test whether a package is already satisfied.
|
test whether a package is already satisfied.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
_CANONICALIZE_RE = re.compile(r'[-_.]+')
|
||||||
|
|
||||||
def __init__(self, name_string, version_string=None):
|
def __init__(self, name_string, version_string=None):
|
||||||
self._plain_package = False
|
self._plain_package = False
|
||||||
self.package_name = name_string
|
self.package_name = name_string
|
||||||
|
@ -515,7 +518,7 @@ class Package:
|
||||||
self.package_name = "setuptools"
|
self.package_name = "setuptools"
|
||||||
self._requirement.project_name = "setuptools"
|
self._requirement.project_name = "setuptools"
|
||||||
else:
|
else:
|
||||||
self.package_name = self._requirement.project_name
|
self.package_name = Package.canonicalize_name(self._requirement.project_name)
|
||||||
self._plain_package = True
|
self._plain_package = True
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
pass
|
pass
|
||||||
|
@ -539,6 +542,11 @@ class Package:
|
||||||
for op, ver in self._requirement.specs
|
for op, ver in self._requirement.specs
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def canonicalize_name(name):
|
||||||
|
# This is taken from PEP 503.
|
||||||
|
return Package._CANONICALIZE_RE.sub("-", name).lower()
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
if self._plain_package:
|
if self._plain_package:
|
||||||
return to_native(self._requirement)
|
return to_native(self._requirement)
|
||||||
|
|
|
@ -213,6 +213,27 @@
|
||||||
that:
|
that:
|
||||||
- "not (q_check_mode is changed)"
|
- "not (q_check_mode is changed)"
|
||||||
|
|
||||||
|
# Case with package name that has a different package name case and an
|
||||||
|
# underscore instead of a hyphen
|
||||||
|
- name: check for Junit-XML package
|
||||||
|
pip:
|
||||||
|
name: Junit-XML
|
||||||
|
virtualenv: "{{ output_dir }}/pipenv"
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: check for Junit-XML package in check_mode
|
||||||
|
pip:
|
||||||
|
name: Junit-XML
|
||||||
|
virtualenv: "{{ output_dir }}/pipenv"
|
||||||
|
state: present
|
||||||
|
check_mode: True
|
||||||
|
register: diff_case_check_mode
|
||||||
|
|
||||||
|
- name: make sure Junit-XML in check_mode doesn't report changed
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- "diff_case_check_mode is not changed"
|
||||||
|
|
||||||
# ansible#23204
|
# ansible#23204
|
||||||
- name: ensure is a fresh virtualenv
|
- name: ensure is a fresh virtualenv
|
||||||
file:
|
file:
|
||||||
|
|
Loading…
Reference in a new issue