From cb17703c3664f6e4a41accc79badf35f4e9e2233 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Wed, 11 Feb 2026 07:12:04 +0100 Subject: [PATCH] [PR #11495/88adca3f backport][stable-12] python_requirements_info: use importlib.metadata when available (#11496) python_requirements_info: use importlib.metadata when available (#11495) Use importlib.metadata when available. (cherry picked from commit 88adca3fb4b88d4470debf5479ee55aea62803e3) Co-authored-by: Felix Fontein --- .mypy.ini | 2 + .../fragments/11492-python_requires_info.yml | 4 ++ plugins/modules/python_requirements_info.py | 40 +++++++++++++------ 3 files changed, 34 insertions(+), 12 deletions(-) create mode 100644 changelogs/fragments/11492-python_requires_info.yml diff --git a/.mypy.ini b/.mypy.ini index 88a3d011da..c92232878c 100644 --- a/.mypy.ini +++ b/.mypy.ini @@ -158,6 +158,8 @@ ignore_missing_imports = True ignore_missing_imports = True [mypy-pingdom.*] ignore_missing_imports = True +[mypy-pkg_resources.*] +ignore_missing_imports = True [mypy-portage.*] ignore_missing_imports = True [mypy-potatoes_that_will_never_be_there.*] diff --git a/changelogs/fragments/11492-python_requires_info.yml b/changelogs/fragments/11492-python_requires_info.yml new file mode 100644 index 0000000000..aa52ffca43 --- /dev/null +++ b/changelogs/fragments/11492-python_requires_info.yml @@ -0,0 +1,4 @@ +bugfixes: + - "python_requirements_info - use ``importlib.metadata`` if ``pkg_resources`` from ``setuptools`` cannot be imported. + That module has been removed from setuptools 82.0.0 + (https://github.com/ansible-collections/community.general/issues/11491, https://github.com/ansible-collections/community.general/pull/11492)." diff --git a/plugins/modules/python_requirements_info.py b/plugins/modules/python_requirements_info.py index 98f07cebfd..ecf87edb7d 100644 --- a/plugins/modules/python_requirements_info.py +++ b/plugins/modules/python_requirements_info.py @@ -121,18 +121,26 @@ import operator import re import sys +from ansible.module_utils.basic import AnsibleModule + +from ansible_collections.community.general.plugins.module_utils.version import LooseVersion + +HAS_IMPORTLIB_METADATA = False +try: + import importlib.metadata + + HAS_IMPORTLIB_METADATA = True +except ImportError: + pass + HAS_DISTUTILS = False try: import pkg_resources - from ansible_collections.community.general.plugins.module_utils.version import LooseVersion - HAS_DISTUTILS = True except ImportError: pass -from ansible.module_utils.basic import AnsibleModule - operations = { "<=": operator.le, ">=": operator.ge, @@ -155,9 +163,9 @@ def main(): argument_spec=dict(dependencies=dict(type="list", elements="str", default=[])), supports_check_mode=True, ) - if not HAS_DISTUTILS: + if not HAS_DISTUTILS and not HAS_IMPORTLIB_METADATA: module.fail_json( - msg='Could not import "distutils" and "pkg_resources" libraries to introspect python environment.', + msg='Could not import "pkg_resources" or "importlib.metadata" libraries to introspect Python environment.', python=sys.executable, python_version=sys.version, python_version_info=python_version_info, @@ -180,12 +188,20 @@ def main(): module.fail_json( msg=f"Failed to parse version requirement '{dep}'. Operator must be one of >, <, <=, >=, or ==" ) - try: - existing = pkg_resources.get_distribution(pkg).version - except pkg_resources.DistributionNotFound: - # not there - results["not_found"].append(pkg) - continue + if HAS_DISTUTILS: + try: + existing = pkg_resources.get_distribution(pkg).version + except pkg_resources.DistributionNotFound: + # not there + results["not_found"].append(pkg) + continue + else: + try: + existing = importlib.metadata.version(pkg) + except importlib.metadata.PackageNotFoundError: + # not there + results["not_found"].append(pkg) + continue if op is None and version is None: results["valid"][pkg] = { "installed": existing,