diff --git a/lib/ansible/compat/selectors/__init__.py b/lib/ansible/compat/selectors.py similarity index 69% rename from lib/ansible/compat/selectors/__init__.py rename to lib/ansible/compat/selectors.py index 6998c2ead40..0117f362ad7 100644 --- a/lib/ansible/compat/selectors/__init__.py +++ b/lib/ansible/compat/selectors.py @@ -15,16 +15,18 @@ # You should have received a copy of the GNU General Public License # along with Ansible. If not, see . -# NOT_BUNDLED - -''' -Compat selectors library. Python-3.5 has this builtin. The selectors2 -package exists on pypi to backport the functionality as far as python-2.6. -Implementation previously resided here - maintaining this file after the -move to ansible.module_utils for code backwards compatibility. -''' from __future__ import annotations import sys -from ansible.module_utils.compat import selectors +import selectors + +from ansible.module_utils.common.warnings import deprecate + + sys.modules['ansible.compat.selectors'] = selectors + + +deprecate( + msg='The `ansible.module_utils.compat.selectors` module is deprecated.', + version='2.19', +) diff --git a/lib/ansible/module_utils/basic.py b/lib/ansible/module_utils/basic.py index a6dedcd21b7..604b69b35ec 100644 --- a/lib/ansible/module_utils/basic.py +++ b/lib/ansible/module_utils/basic.py @@ -34,6 +34,7 @@ import pwd import platform import re import select +import selectors import shlex import shutil import signal @@ -72,8 +73,6 @@ except ImportError: # Python2 & 3 way to get NoneType NoneType = type(None) -from ansible.module_utils.compat import selectors - from ._text import to_native, to_bytes, to_text from ansible.module_utils.common.text.converters import ( jsonify, diff --git a/lib/ansible/module_utils/compat/_selectors2.py b/lib/ansible/module_utils/compat/_selectors2.py deleted file mode 100644 index 7caf4c31d7f..00000000000 --- a/lib/ansible/module_utils/compat/_selectors2.py +++ /dev/null @@ -1,656 +0,0 @@ -# This file is from the selectors2.py package. It backports the PSF Licensed -# selectors module from the Python-3.5 stdlib to older versions of Python. -# The author, Seth Michael Larson, dual licenses his modifications under the -# PSF License and MIT License: -# https://github.com/SethMichaelLarson/selectors2#license -# -# Copyright (c) 2016 Seth Michael Larson -# -# PSF License (see licenses/PSF-license.txt or https://opensource.org/licenses/Python-2.0) -# MIT License (see licenses/MIT-license.txt or https://opensource.org/licenses/MIT) -# - - -# Backport of selectors.py from Python 3.5+ to support Python < 3.4 -# Also has the behavior specified in PEP 475 which is to retry syscalls -# in the case of an EINTR error. This module is required because selectors34 -# does not follow this behavior and instead returns that no file descriptor -# events have occurred rather than retry the syscall. The decision to drop -# support for select.devpoll is made to maintain 100% test coverage. -from __future__ import annotations - -import errno -import math -import select -import socket -import sys -import time -from collections import namedtuple -from ansible.module_utils.six.moves.collections_abc import Mapping - -try: - monotonic = time.monotonic -except (AttributeError, ImportError): # Python 3.3< - monotonic = time.time - -__author__ = 'Seth Michael Larson' -__email__ = 'sethmichaellarson@protonmail.com' -__version__ = '1.1.1' -__license__ = 'MIT' - -__all__ = [ - 'EVENT_READ', - 'EVENT_WRITE', - 'SelectorError', - 'SelectorKey', - 'DefaultSelector' -] - -EVENT_READ = (1 << 0) -EVENT_WRITE = (1 << 1) - -HAS_SELECT = True # Variable that shows whether the platform has a selector. -_SYSCALL_SENTINEL = object() # Sentinel in case a system call returns None. - - -class SelectorError(Exception): - def __init__(self, errcode): - super(SelectorError, self).__init__() - self.errno = errcode - - def __repr__(self): - return "".format(self.errno) - - def __str__(self): - return self.__repr__() - - -def _fileobj_to_fd(fileobj): - """ Return a file descriptor from a file object. If - given an integer will simply return that integer back. """ - if isinstance(fileobj, int): - fd = fileobj - else: - try: - fd = int(fileobj.fileno()) - except (AttributeError, TypeError, ValueError): - raise ValueError("Invalid file object: {0!r}".format(fileobj)) - if fd < 0: - raise ValueError("Invalid file descriptor: {0}".format(fd)) - return fd - - -# Python 3.5 uses a more direct route to wrap system calls to increase speed. -if sys.version_info >= (3, 5): - def _syscall_wrapper(func, dummy, *args, **kwargs): - """ This is the short-circuit version of the below logic - because in Python 3.5+ all selectors restart system calls. """ - try: - return func(*args, **kwargs) - except (OSError, IOError, select.error) as e: - errcode = None - if hasattr(e, "errno"): - errcode = e.errno - elif hasattr(e, "args"): - errcode = e.args[0] - raise SelectorError(errcode) -else: - def _syscall_wrapper(func, recalc_timeout, *args, **kwargs): - """ Wrapper function for syscalls that could fail due to EINTR. - All functions should be retried if there is time left in the timeout - in accordance with PEP 475. """ - timeout = kwargs.get("timeout", None) - if timeout is None: - expires = None - recalc_timeout = False - else: - timeout = float(timeout) - if timeout < 0.0: # Timeout less than 0 treated as no timeout. - expires = None - else: - expires = monotonic() + timeout - - args = list(args) - if recalc_timeout and "timeout" not in kwargs: - raise ValueError( - "Timeout must be in args or kwargs to be recalculated") - - result = _SYSCALL_SENTINEL - while result is _SYSCALL_SENTINEL: - try: - result = func(*args, **kwargs) - # OSError is thrown by select.select - # IOError is thrown by select.epoll.poll - # select.error is thrown by select.poll.poll - # Aren't we thankful for Python 3.x rework for exceptions? - except (OSError, IOError, select.error) as e: - # select.error wasn't a subclass of OSError in the past. - errcode = None - if hasattr(e, "errno"): - errcode = e.errno - elif hasattr(e, "args"): - errcode = e.args[0] - - # Also test for the Windows equivalent of EINTR. - is_interrupt = (errcode == errno.EINTR or (hasattr(errno, "WSAEINTR") and - errcode == errno.WSAEINTR)) - - if is_interrupt: - if expires is not None: - current_time = monotonic() - if current_time > expires: - raise OSError(errno.ETIMEDOUT) - if recalc_timeout: - if "timeout" in kwargs: - kwargs["timeout"] = expires - current_time - continue - if errcode: - raise SelectorError(errcode) - else: - raise - return result - - -SelectorKey = namedtuple('SelectorKey', ['fileobj', 'fd', 'events', 'data']) - - -class _SelectorMapping(Mapping): - """ Mapping of file objects to selector keys """ - - def __init__(self, selector): - self._selector = selector - - def __len__(self): - return len(self._selector._fd_to_key) - - def __getitem__(self, fileobj): - try: - fd = self._selector._fileobj_lookup(fileobj) - return self._selector._fd_to_key[fd] - except KeyError: - raise KeyError("{0!r} is not registered.".format(fileobj)) - - def __iter__(self): - return iter(self._selector._fd_to_key) - - -class BaseSelector(object): - """ Abstract Selector class - - A selector supports registering file objects to be monitored - for specific I/O events. - - A file object is a file descriptor or any object with a - `fileno()` method. An arbitrary object can be attached to the - file object which can be used for example to store context info, - a callback, etc. - - A selector can use various implementations (select(), poll(), epoll(), - and kqueue()) depending on the platform. The 'DefaultSelector' class uses - the most efficient implementation for the current platform. - """ - def __init__(self): - # Maps file descriptors to keys. - self._fd_to_key = {} - - # Read-only mapping returned by get_map() - self._map = _SelectorMapping(self) - - def _fileobj_lookup(self, fileobj): - """ Return a file descriptor from a file object. - This wraps _fileobj_to_fd() to do an exhaustive - search in case the object is invalid but we still - have it in our map. Used by unregister() so we can - unregister an object that was previously registered - even if it is closed. It is also used by _SelectorMapping - """ - try: - return _fileobj_to_fd(fileobj) - except ValueError: - - # Search through all our mapped keys. - for key in self._fd_to_key.values(): - if key.fileobj is fileobj: - return key.fd - - # Raise ValueError after all. - raise - - def register(self, fileobj, events, data=None): - """ Register a file object for a set of events to monitor. """ - if (not events) or (events & ~(EVENT_READ | EVENT_WRITE)): - raise ValueError("Invalid events: {0!r}".format(events)) - - key = SelectorKey(fileobj, self._fileobj_lookup(fileobj), events, data) - - if key.fd in self._fd_to_key: - raise KeyError("{0!r} (FD {1}) is already registered" - .format(fileobj, key.fd)) - - self._fd_to_key[key.fd] = key - return key - - def unregister(self, fileobj): - """ Unregister a file object from being monitored. """ - try: - key = self._fd_to_key.pop(self._fileobj_lookup(fileobj)) - except KeyError: - raise KeyError("{0!r} is not registered".format(fileobj)) - - # Getting the fileno of a closed socket on Windows errors with EBADF. - except socket.error as err: - if err.errno != errno.EBADF: - raise - else: - for key in self._fd_to_key.values(): - if key.fileobj is fileobj: - self._fd_to_key.pop(key.fd) - break - else: - raise KeyError("{0!r} is not registered".format(fileobj)) - return key - - def modify(self, fileobj, events, data=None): - """ Change a registered file object monitored events and data. """ - # NOTE: Some subclasses optimize this operation even further. - try: - key = self._fd_to_key[self._fileobj_lookup(fileobj)] - except KeyError: - raise KeyError("{0!r} is not registered".format(fileobj)) - - if events != key.events: - self.unregister(fileobj) - key = self.register(fileobj, events, data) - - elif data != key.data: - # Use a shortcut to update the data. - key = key._replace(data=data) - self._fd_to_key[key.fd] = key - - return key - - def select(self, timeout=None): - """ Perform the actual selection until some monitored file objects - are ready or the timeout expires. """ - raise NotImplementedError() - - def close(self): - """ Close the selector. This must be called to ensure that all - underlying resources are freed. """ - self._fd_to_key.clear() - self._map = None - - def get_key(self, fileobj): - """ Return the key associated with a registered file object. """ - mapping = self.get_map() - if mapping is None: - raise RuntimeError("Selector is closed") - try: - return mapping[fileobj] - except KeyError: - raise KeyError("{0!r} is not registered".format(fileobj)) - - def get_map(self): - """ Return a mapping of file objects to selector keys """ - return self._map - - def _key_from_fd(self, fd): - """ Return the key associated to a given file descriptor - Return None if it is not found. """ - try: - return self._fd_to_key[fd] - except KeyError: - return None - - def __enter__(self): - return self - - def __exit__(self, *args): - self.close() - - -# Almost all platforms have select.select() -if hasattr(select, "select"): - class SelectSelector(BaseSelector): - """ Select-based selector. """ - def __init__(self): - super(SelectSelector, self).__init__() - self._readers = set() - self._writers = set() - - def register(self, fileobj, events, data=None): - key = super(SelectSelector, self).register(fileobj, events, data) - if events & EVENT_READ: - self._readers.add(key.fd) - if events & EVENT_WRITE: - self._writers.add(key.fd) - return key - - def unregister(self, fileobj): - key = super(SelectSelector, self).unregister(fileobj) - self._readers.discard(key.fd) - self._writers.discard(key.fd) - return key - - def _select(self, r, w, timeout=None): - """ Wrapper for select.select because timeout is a positional arg """ - return select.select(r, w, [], timeout) - - def select(self, timeout=None): - # Selecting on empty lists on Windows errors out. - if not len(self._readers) and not len(self._writers): - return [] - - timeout = None if timeout is None else max(timeout, 0.0) - ready = [] - r, w, dummy = _syscall_wrapper(self._select, True, self._readers, - self._writers, timeout=timeout) - r = set(r) - w = set(w) - for fd in r | w: - events = 0 - if fd in r: - events |= EVENT_READ - if fd in w: - events |= EVENT_WRITE - - key = self._key_from_fd(fd) - if key: - ready.append((key, events & key.events)) - return ready - - __all__.append('SelectSelector') - - -if hasattr(select, "poll"): - class PollSelector(BaseSelector): - """ Poll-based selector """ - def __init__(self): - super(PollSelector, self).__init__() - self._poll = select.poll() - - def register(self, fileobj, events, data=None): - key = super(PollSelector, self).register(fileobj, events, data) - event_mask = 0 - if events & EVENT_READ: - event_mask |= select.POLLIN - if events & EVENT_WRITE: - event_mask |= select.POLLOUT - self._poll.register(key.fd, event_mask) - return key - - def unregister(self, fileobj): - key = super(PollSelector, self).unregister(fileobj) - self._poll.unregister(key.fd) - return key - - def _wrap_poll(self, timeout=None): - """ Wrapper function for select.poll.poll() so that - _syscall_wrapper can work with only seconds. """ - if timeout is not None: - if timeout <= 0: - timeout = 0 - else: - # select.poll.poll() has a resolution of 1 millisecond, - # round away from zero to wait *at least* timeout seconds. - timeout = math.ceil(timeout * 1e3) - - result = self._poll.poll(timeout) - return result - - def select(self, timeout=None): - ready = [] - fd_events = _syscall_wrapper(self._wrap_poll, True, timeout=timeout) - for fd, event_mask in fd_events: - events = 0 - if event_mask & ~select.POLLIN: - events |= EVENT_WRITE - if event_mask & ~select.POLLOUT: - events |= EVENT_READ - - key = self._key_from_fd(fd) - if key: - ready.append((key, events & key.events)) - - return ready - - __all__.append('PollSelector') - -if hasattr(select, "epoll"): - class EpollSelector(BaseSelector): - """ Epoll-based selector """ - def __init__(self): - super(EpollSelector, self).__init__() - self._epoll = select.epoll() - - def fileno(self): - return self._epoll.fileno() - - def register(self, fileobj, events, data=None): - key = super(EpollSelector, self).register(fileobj, events, data) - events_mask = 0 - if events & EVENT_READ: - events_mask |= select.EPOLLIN - if events & EVENT_WRITE: - events_mask |= select.EPOLLOUT - _syscall_wrapper(self._epoll.register, False, key.fd, events_mask) - return key - - def unregister(self, fileobj): - key = super(EpollSelector, self).unregister(fileobj) - try: - _syscall_wrapper(self._epoll.unregister, False, key.fd) - except SelectorError: - # This can occur when the fd was closed since registry. - pass - return key - - def select(self, timeout=None): - if timeout is not None: - if timeout <= 0: - timeout = 0.0 - else: - # select.epoll.poll() has a resolution of 1 millisecond - # but luckily takes seconds so we don't need a wrapper - # like PollSelector. Just for better rounding. - timeout = math.ceil(timeout * 1e3) * 1e-3 - timeout = float(timeout) - else: - timeout = -1.0 # epoll.poll() must have a float. - - # We always want at least 1 to ensure that select can be called - # with no file descriptors registered. Otherwise will fail. - max_events = max(len(self._fd_to_key), 1) - - ready = [] - fd_events = _syscall_wrapper(self._epoll.poll, True, - timeout=timeout, - maxevents=max_events) - for fd, event_mask in fd_events: - events = 0 - if event_mask & ~select.EPOLLIN: - events |= EVENT_WRITE - if event_mask & ~select.EPOLLOUT: - events |= EVENT_READ - - key = self._key_from_fd(fd) - if key: - ready.append((key, events & key.events)) - return ready - - def close(self): - self._epoll.close() - super(EpollSelector, self).close() - - __all__.append('EpollSelector') - - -if hasattr(select, "devpoll"): - class DevpollSelector(BaseSelector): - """Solaris /dev/poll selector.""" - - def __init__(self): - super(DevpollSelector, self).__init__() - self._devpoll = select.devpoll() - - def fileno(self): - return self._devpoll.fileno() - - def register(self, fileobj, events, data=None): - key = super(DevpollSelector, self).register(fileobj, events, data) - poll_events = 0 - if events & EVENT_READ: - poll_events |= select.POLLIN - if events & EVENT_WRITE: - poll_events |= select.POLLOUT - self._devpoll.register(key.fd, poll_events) - return key - - def unregister(self, fileobj): - key = super(DevpollSelector, self).unregister(fileobj) - self._devpoll.unregister(key.fd) - return key - - def _wrap_poll(self, timeout=None): - """ Wrapper function for select.poll.poll() so that - _syscall_wrapper can work with only seconds. """ - if timeout is not None: - if timeout <= 0: - timeout = 0 - else: - # select.devpoll.poll() has a resolution of 1 millisecond, - # round away from zero to wait *at least* timeout seconds. - timeout = math.ceil(timeout * 1e3) - - result = self._devpoll.poll(timeout) - return result - - def select(self, timeout=None): - ready = [] - fd_events = _syscall_wrapper(self._wrap_poll, True, timeout=timeout) - for fd, event_mask in fd_events: - events = 0 - if event_mask & ~select.POLLIN: - events |= EVENT_WRITE - if event_mask & ~select.POLLOUT: - events |= EVENT_READ - - key = self._key_from_fd(fd) - if key: - ready.append((key, events & key.events)) - - return ready - - def close(self): - self._devpoll.close() - super(DevpollSelector, self).close() - - __all__.append('DevpollSelector') - - -if hasattr(select, "kqueue"): - class KqueueSelector(BaseSelector): - """ Kqueue / Kevent-based selector """ - def __init__(self): - super(KqueueSelector, self).__init__() - self._kqueue = select.kqueue() - - def fileno(self): - return self._kqueue.fileno() - - def register(self, fileobj, events, data=None): - key = super(KqueueSelector, self).register(fileobj, events, data) - if events & EVENT_READ: - kevent = select.kevent(key.fd, - select.KQ_FILTER_READ, - select.KQ_EV_ADD) - - _syscall_wrapper(self._wrap_control, False, [kevent], 0, 0) - - if events & EVENT_WRITE: - kevent = select.kevent(key.fd, - select.KQ_FILTER_WRITE, - select.KQ_EV_ADD) - - _syscall_wrapper(self._wrap_control, False, [kevent], 0, 0) - - return key - - def unregister(self, fileobj): - key = super(KqueueSelector, self).unregister(fileobj) - if key.events & EVENT_READ: - kevent = select.kevent(key.fd, - select.KQ_FILTER_READ, - select.KQ_EV_DELETE) - try: - _syscall_wrapper(self._wrap_control, False, [kevent], 0, 0) - except SelectorError: - pass - if key.events & EVENT_WRITE: - kevent = select.kevent(key.fd, - select.KQ_FILTER_WRITE, - select.KQ_EV_DELETE) - try: - _syscall_wrapper(self._wrap_control, False, [kevent], 0, 0) - except SelectorError: - pass - - return key - - def select(self, timeout=None): - if timeout is not None: - timeout = max(timeout, 0) - - max_events = len(self._fd_to_key) * 2 - ready_fds = {} - - kevent_list = _syscall_wrapper(self._wrap_control, True, - None, max_events, timeout=timeout) - - for kevent in kevent_list: - fd = kevent.ident - event_mask = kevent.filter - events = 0 - if event_mask == select.KQ_FILTER_READ: - events |= EVENT_READ - if event_mask == select.KQ_FILTER_WRITE: - events |= EVENT_WRITE - - key = self._key_from_fd(fd) - if key: - if key.fd not in ready_fds: - ready_fds[key.fd] = (key, events & key.events) - else: - old_events = ready_fds[key.fd][1] - ready_fds[key.fd] = (key, (events | old_events) & key.events) - - return list(ready_fds.values()) - - def close(self): - self._kqueue.close() - super(KqueueSelector, self).close() - - def _wrap_control(self, changelist, max_events, timeout): - return self._kqueue.control(changelist, max_events, timeout) - - __all__.append('KqueueSelector') - - -# Choose the best implementation, roughly: -# kqueue == epoll == devpoll > poll > select. -# select() also can't accept a FD > FD_SETSIZE (usually around 1024) -if 'KqueueSelector' in globals(): # Platform-specific: Mac OS and BSD - DefaultSelector = KqueueSelector -elif 'DevpollSelector' in globals(): - DefaultSelector = DevpollSelector -elif 'EpollSelector' in globals(): # Platform-specific: Linux - DefaultSelector = EpollSelector -elif 'PollSelector' in globals(): # Platform-specific: Linux - DefaultSelector = PollSelector -elif 'SelectSelector' in globals(): # Platform-specific: Windows - DefaultSelector = SelectSelector -else: # Platform-specific: AppEngine - def no_selector(dummy): - raise ValueError("Platform does not have a selector") - DefaultSelector = no_selector - HAS_SELECT = False diff --git a/lib/ansible/module_utils/compat/selectors.py b/lib/ansible/module_utils/compat/selectors.py index 1f30929fb1b..81082f3fe36 100644 --- a/lib/ansible/module_utils/compat/selectors.py +++ b/lib/ansible/module_utils/compat/selectors.py @@ -15,41 +15,18 @@ # You should have received a copy of the GNU General Public License # along with Ansible. If not, see . - -''' -Compat selectors library. Python-3.5 has this builtin. The selectors2 -package exists on pypi to backport the functionality as far as python-2.6. -''' from __future__ import annotations -# The following makes it easier for us to script updates of the bundled code -_BUNDLED_METADATA = {"pypi_name": "selectors2", "version": "1.1.1", "version_constraints": ">1.0,<2.0"} - -# Added these bugfix commits from 2.1.0: -# * https://github.com/SethMichaelLarson/selectors2/commit/3bd74f2033363b606e1e849528ccaa76f5067590 -# Wrap kqueue.control so that timeout is a keyword arg -# * https://github.com/SethMichaelLarson/selectors2/commit/6f6a26f42086d8aab273b30be492beecb373646b -# Fix formatting of the kqueue.control patch for pylint -# * https://github.com/SethMichaelLarson/selectors2/commit/f0c2c6c66cfa7662bc52beaf4e2d65adfa25e189 -# Fix use of OSError exception for py3 and use the wrapper of kqueue.control so retries of -# interrupted syscalls work with kqueue - +import selectors import sys -import types # pylint: disable=unused-import -try: - # Python 3.4+ - import selectors as _system_selectors -except ImportError: - try: - # backport package installed in the system - import selectors2 as _system_selectors # type: ignore[no-redef] - except ImportError: - _system_selectors = None # type: types.ModuleType | None # type: ignore[no-redef] +from ansible.module_utils.common.warnings import deprecate + -if _system_selectors: - selectors = _system_selectors -else: - # Our bundled copy - from ansible.module_utils.compat import _selectors2 as selectors # type: ignore[no-redef] sys.modules['ansible.module_utils.compat.selectors'] = selectors + + +deprecate( + msg='The `ansible.module_utils.compat.selectors` module is deprecated.', + version='2.19', +) diff --git a/lib/ansible/plugins/connection/local.py b/lib/ansible/plugins/connection/local.py index 44af5829b30..2ba3e692869 100644 --- a/lib/ansible/plugins/connection/local.py +++ b/lib/ansible/plugins/connection/local.py @@ -21,13 +21,13 @@ import fcntl import getpass import os import pty +import selectors import shutil import subprocess import typing as t import ansible.constants as C from ansible.errors import AnsibleError, AnsibleFileNotFound -from ansible.module_utils.compat import selectors from ansible.module_utils.six import text_type, binary_type from ansible.module_utils.common.text.converters import to_bytes, to_native, to_text from ansible.plugins.connection import ConnectionBase diff --git a/lib/ansible/plugins/connection/ssh.py b/lib/ansible/plugins/connection/ssh.py index 7d6513aac9b..dc8ffbff142 100644 --- a/lib/ansible/plugins/connection/ssh.py +++ b/lib/ansible/plugins/connection/ssh.py @@ -388,6 +388,7 @@ import io import os import pty import re +import selectors import shlex import subprocess import time @@ -401,7 +402,6 @@ from ansible.errors import ( AnsibleFileNotFound, ) from ansible.errors import AnsibleOptionsError -from ansible.module_utils.compat import selectors from ansible.module_utils.six import PY3, text_type, binary_type from ansible.module_utils.common.text.converters import to_bytes, to_native, to_text from ansible.module_utils.parsing.convert_bool import BOOLEANS, boolean diff --git a/test/lib/ansible_test/_internal/commands/sanity/mypy.py b/test/lib/ansible_test/_internal/commands/sanity/mypy.py index 0296177772c..4d580e933e3 100644 --- a/test/lib/ansible_test/_internal/commands/sanity/mypy.py +++ b/test/lib/ansible_test/_internal/commands/sanity/mypy.py @@ -64,7 +64,6 @@ class MypyTest(SanityMultipleVersion): vendored_paths = ( 'lib/ansible/module_utils/six/__init__.py', 'lib/ansible/module_utils/distro/_distro.py', - 'lib/ansible/module_utils/compat/_selectors2.py', ) def filter_targets(self, targets: list[TestTarget]) -> list[TestTarget]: diff --git a/test/lib/ansible_test/_util/controller/sanity/mypy/ansible-core.ini b/test/lib/ansible_test/_util/controller/sanity/mypy/ansible-core.ini index 41d824b26c0..0c10e68ae0b 100644 --- a/test/lib/ansible_test/_util/controller/sanity/mypy/ansible-core.ini +++ b/test/lib/ansible_test/_util/controller/sanity/mypy/ansible-core.ini @@ -85,9 +85,6 @@ ignore_missing_imports = True [mypy-distro.*] ignore_missing_imports = True -[mypy-selectors2.*] -ignore_missing_imports = True - [mypy-resolvelib.*] ignore_missing_imports = True diff --git a/test/lib/ansible_test/_util/controller/sanity/mypy/modules.ini b/test/lib/ansible_test/_util/controller/sanity/mypy/modules.ini index d6a608f6c7e..fb3da5c26d4 100644 --- a/test/lib/ansible_test/_util/controller/sanity/mypy/modules.ini +++ b/test/lib/ansible_test/_util/controller/sanity/mypy/modules.ini @@ -52,9 +52,6 @@ ignore_missing_imports = True [mypy-distro.*] ignore_missing_imports = True -[mypy-selectors2.*] -ignore_missing_imports = True - [mypy-selinux.*] ignore_missing_imports = True diff --git a/test/sanity/code-smell/update-bundled.py b/test/sanity/code-smell/update-bundled.py index 4bad77a6672..61c837c81ab 100644 --- a/test/sanity/code-smell/update-bundled.py +++ b/test/sanity/code-smell/update-bundled.py @@ -49,7 +49,6 @@ def get_bundled_libs(paths): for filename in fnmatch.filter(paths, 'lib/ansible/compat/*/__init__.py'): bundled_libs.add(filename) - bundled_libs.add('lib/ansible/module_utils/compat/selectors.py') bundled_libs.add('lib/ansible/module_utils/distro/__init__.py') bundled_libs.add('lib/ansible/module_utils/six/__init__.py') # backports.ssl_match_hostname should be moved to its own file in the future diff --git a/test/units/executor/module_common/test_recursive_finder.py b/test/units/executor/module_common/test_recursive_finder.py index 5058d6da2ff..92d7c206e0b 100644 --- a/test/units/executor/module_common/test_recursive_finder.py +++ b/test/units/executor/module_common/test_recursive_finder.py @@ -56,8 +56,6 @@ MODULE_UTILS_BASIC_FILES = frozenset(('ansible/__init__.py', 'ansible/module_utils/common/_utils.py', 'ansible/module_utils/common/arg_spec.py', 'ansible/module_utils/compat/__init__.py', - 'ansible/module_utils/compat/_selectors2.py', - 'ansible/module_utils/compat/selectors.py', 'ansible/module_utils/compat/selinux.py', 'ansible/module_utils/distro/__init__.py', 'ansible/module_utils/distro/_distro.py', diff --git a/test/units/module_utils/basic/test_run_command.py b/test/units/module_utils/basic/test_run_command.py index ecb68659520..707d5c95e22 100644 --- a/test/units/module_utils/basic/test_run_command.py +++ b/test/units/module_utils/basic/test_run_command.py @@ -5,6 +5,7 @@ from __future__ import annotations import errno +import selectors from itertools import product from io import BytesIO @@ -12,7 +13,6 @@ import pytest from ansible.module_utils.common.text.converters import to_native from ansible.module_utils.six import PY2 -from ansible.module_utils.compat import selectors class OpenBytesIO(BytesIO): diff --git a/test/units/plugins/connection/test_ssh.py b/test/units/plugins/connection/test_ssh.py index ff1f128bafe..62d72713e21 100644 --- a/test/units/plugins/connection/test_ssh.py +++ b/test/units/plugins/connection/test_ssh.py @@ -19,6 +19,7 @@ from __future__ import annotations from io import StringIO +from selectors import SelectorKey, EVENT_READ import pytest @@ -26,7 +27,6 @@ from ansible.errors import AnsibleAuthenticationFailure from units.compat import unittest from unittest.mock import patch, MagicMock, PropertyMock from ansible.errors import AnsibleError, AnsibleConnectionFailure, AnsibleFileNotFound -from ansible.module_utils.compat.selectors import SelectorKey, EVENT_READ from ansible.module_utils.six.moves import shlex_quote from ansible.module_utils.common.text.converters import to_bytes from ansible.playbook.play_context import PlayContext @@ -389,7 +389,7 @@ def mock_run_env(request, mocker): request.cls.mock_popen = mock_popen request.cls.mock_selector = MockSelector() - mocker.patch('ansible.module_utils.compat.selectors.DefaultSelector', lambda: request.cls.mock_selector) + mocker.patch('selectors.DefaultSelector', lambda: request.cls.mock_selector) request.cls.mock_openpty = mocker.patch('pty.openpty')