pull/83221/head
Martin Krizek 1 month ago
parent a5b922ab8c
commit 4412ceec76

@ -9,17 +9,14 @@ from __future__ import annotations
import itertools
import os
import os.path
import pkgutil
import re
import sys
from keyword import iskeyword
from tokenize import Name as _VALID_IDENTIFIER_REGEX
# DO NOT add new non-stdlib import deps here, this loader is used by external tools (eg ansible-test import sanity)
# that only allow stdlib and module_utils
from ansible.module_utils.common.text.converters import to_native, to_text, to_bytes
from ansible.module_utils.six import string_types, PY3
from ._collection_config import AnsibleCollectionConfig
from contextlib import contextmanager
@ -33,7 +30,22 @@ except ImportError:
return sys.modules[name]
from importlib import reload as reload_module
from importlib.resources.abc import TraversableResources
try:
try:
# Available on Python >= 3.11
# We ignore the import error that will trigger when running mypy with
# older Python versions.
from importlib.resources.abc import TraversableResources # type: ignore[import]
except ImportError:
# Used with Python 3.9 and 3.10 only
# This member is still available as an alias up until Python 3.14 but
# is deprecated as of Python 3.12.
from importlib.abc import TraversableResources # deprecated: description='TraversableResources move' python_version='3.10'
except ImportError:
# Python < 3.9
# deprecated: description='TraversableResources fallback' python_version='3.8'
TraversableResources = object # type: ignore[assignment,misc]
try:
from importlib.util import find_spec, spec_from_loader
@ -181,7 +193,7 @@ class _AnsibleTraversableResources(TraversableResources):
parts = package.split('.')
is_ns = parts[0] == 'ansible_collections' and len(parts) < 3
if isinstance(package, string_types):
if isinstance(package, str):
if is_ns:
# Don't use ``spec_from_loader`` here, because that will point
# to exactly 1 location for a namespace. Use ``find_spec``
@ -203,7 +215,7 @@ class _AnsibleCollectionFinder:
# TODO: accept metadata loader override
self._ansible_pkg_path = to_native(os.path.dirname(to_bytes(sys.modules['ansible'].__file__)))
if isinstance(paths, string_types):
if isinstance(paths, str):
paths = [paths]
elif paths is None:
paths = []
@ -288,7 +300,7 @@ class _AnsibleCollectionFinder:
return paths
def set_playbook_paths(self, playbook_paths):
if isinstance(playbook_paths, string_types):
if isinstance(playbook_paths, str):
playbook_paths = [playbook_paths]
# track visited paths; we have to preserve the dir order as-passed in case there are duplicate collections (first one wins)
@ -374,19 +386,17 @@ class _AnsiblePathHookFinder:
# when called from a path_hook, find_module doesn't usually get the path arg, so this provides our context
self._pathctx = to_native(pathctx)
self._collection_finder = collection_finder
if PY3:
# cache the native FileFinder (take advantage of its filesystem cache for future find/load requests)
self._file_finder = None
# cache the native FileFinder (take advantage of its filesystem cache for future find/load requests)
self._file_finder = None
# class init is fun- this method has a self arg that won't get used
def _get_filefinder_path_hook(self=None):
_file_finder_hook = None
if PY3:
# try to find the FileFinder hook to call for fallback path-based imports in Py3
_file_finder_hook = [ph for ph in sys.path_hooks if 'FileFinder' in repr(ph)]
if len(_file_finder_hook) != 1:
raise Exception('need exactly one FileFinder import hook (found {0})'.format(len(_file_finder_hook)))
_file_finder_hook = _file_finder_hook[0]
# try to find the FileFinder hook to call for fallback path-based imports in Py3
_file_finder_hook = [ph for ph in sys.path_hooks if 'FileFinder' in repr(ph)]
if len(_file_finder_hook) != 1:
raise Exception('need exactly one FileFinder import hook (found {0})'.format(len(_file_finder_hook)))
_file_finder_hook = _file_finder_hook[0]
return _file_finder_hook
@ -407,20 +417,16 @@ class _AnsiblePathHookFinder:
# out what we *shouldn't* be loading with the limited info it has. So we'll just delegate to the
# normal path-based loader as best we can to service it. This also allows us to take advantage of Python's
# built-in FS caching and byte-compilation for most things.
if PY3:
# create or consult our cached file finder for this path
if not self._file_finder:
try:
self._file_finder = _AnsiblePathHookFinder._filefinder_path_hook(self._pathctx)
except ImportError:
# FUTURE: log at a high logging level? This is normal for things like python36.zip on the path, but
# might not be in some other situation...
return None
return self._file_finder
# create or consult our cached file finder for this path
if not self._file_finder:
try:
self._file_finder = _AnsiblePathHookFinder._filefinder_path_hook(self._pathctx)
except ImportError:
# FUTURE: log at a high logging level? This is normal for things like python36.zip on the path, but
# might not be in some other situation...
return None
# call py2's internal loader
return pkgutil.ImpImporter(self._pathctx)
return self._file_finder
def find_module(self, fullname, path=None):
# we ignore the passed in path here- use what we got from the path hook init
@ -1086,7 +1092,7 @@ class AnsibleCollectionRef:
def _get_collection_path(collection_name):
collection_name = to_native(collection_name)
if not collection_name or not isinstance(collection_name, string_types) or len(collection_name.split('.')) != 2:
if not collection_name or not isinstance(collection_name, str) or len(collection_name.split('.')) != 2:
raise ValueError('collection_name must be a non-empty string of the form namespace.collection')
try:
collection_pkg = import_module('ansible_collections.' + collection_name)
@ -1269,7 +1275,7 @@ def _iter_modules_impl(paths, prefix=''):
def _get_collection_metadata(collection_name):
collection_name = to_native(collection_name)
if not collection_name or not isinstance(collection_name, string_types) or len(collection_name.split('.')) != 2:
if not collection_name or not isinstance(collection_name, str) or len(collection_name.split('.')) != 2:
raise ValueError('collection_name must be a non-empty string of the form namespace.collection')
try:

Loading…
Cancel
Save