diff --git a/changelogs/fragments/75863-start-move-away-six.yml b/changelogs/fragments/75863-start-move-away-six.yml new file mode 100644 index 00000000000..d868aee8ef4 --- /dev/null +++ b/changelogs/fragments/75863-start-move-away-six.yml @@ -0,0 +1,2 @@ +minor_changes: + - "Start of moving away from using Six, Python 2 and 3 compatibility library (https://github.com/ansible/ansible/pull/75863)" diff --git a/lib/ansible/cli/__init__.py b/lib/ansible/cli/__init__.py index 4ab4b84c5ed..969edf93369 100644 --- a/lib/ansible/cli/__init__.py +++ b/lib/ansible/cli/__init__.py @@ -22,7 +22,7 @@ import getpass import os import subprocess import traceback -from abc import ABCMeta, abstractmethod +from abc import ABC, abstractmethod from pathlib import Path try: @@ -38,7 +38,7 @@ from ansible import context from ansible.cli.arguments import option_helpers as opt_help from ansible.errors import AnsibleError, AnsibleOptionsError, AnsibleParserError from ansible.inventory.manager import InventoryManager -from ansible.module_utils.six import with_metaclass, string_types, PY3 +from ansible.module_utils.six import string_types from ansible.module_utils._text import to_bytes, to_text from ansible.parsing.dataloader import DataLoader from ansible.parsing.vault import PromptVaultSecret, get_file_vault_secret @@ -57,7 +57,7 @@ except ImportError: HAS_ARGCOMPLETE = False -class CLI(with_metaclass(ABCMeta, object)): +class CLI(ABC): ''' code behind bin/ansible* programs ''' PAGER = 'less' @@ -509,11 +509,8 @@ class CLI(with_metaclass(ABCMeta, object)): b_pwd_file = to_bytes(pwd_file) secret = None if b_pwd_file == b'-': - if PY3: - # ensure its read as bytes - secret = sys.stdin.buffer.read() - else: - secret = sys.stdin.read() + # ensure its read as bytes + secret = sys.stdin.buffer.read() elif not os.path.exists(b_pwd_file): raise AnsibleError("The password file %s was not found" % pwd_file) diff --git a/lib/ansible/cli/config.py b/lib/ansible/cli/config.py index 59041ba3b30..b78a5afbb82 100755 --- a/lib/ansible/cli/config.py +++ b/lib/ansible/cli/config.py @@ -24,7 +24,6 @@ from ansible.errors import AnsibleError, AnsibleOptionsError from ansible.module_utils._text import to_native, to_text, to_bytes from ansible.module_utils.common._collections_compat import Mapping from ansible.module_utils.six import string_types -from ansible.module_utils.six.moves import shlex_quote from ansible.parsing.quoting import is_quoted from ansible.parsing.yaml.dumper import AnsibleDumper from ansible.utils.color import stringc @@ -263,7 +262,7 @@ class ConfigCLI(CLI): # list of other stuff default = '%s' % to_native(default) if isinstance(default, string_types) and not is_quoted(default): - default = shlex_quote(default) + default = shlex.quote(default) elif default is None: default = '' diff --git a/lib/ansible/cli/doc.py b/lib/ansible/cli/doc.py index 78db1e6f0cf..27dc9418fea 100755 --- a/lib/ansible/cli/doc.py +++ b/lib/ansible/cli/doc.py @@ -28,11 +28,11 @@ from ansible.cli.arguments import option_helpers as opt_help from ansible.collections.list import list_collection_dirs from ansible.errors import AnsibleError, AnsibleOptionsError, AnsibleParserError from ansible.module_utils._text import to_native, to_text -from ansible.module_utils.common._collections_compat import Container, Sequence +from ansible.module_utils.common._collections_compat import Sequence from ansible.module_utils.common.json import AnsibleJSONEncoder from ansible.module_utils.common.yaml import yaml_dump from ansible.module_utils.compat import importlib -from ansible.module_utils.six import iteritems, string_types +from ansible.module_utils.six import string_types from ansible.parsing.plugin_docs import read_docstub from ansible.parsing.utils.yaml import from_yaml from ansible.parsing.yaml.dumper import AnsibleDumper @@ -499,7 +499,7 @@ class DocCLI(CLI, RoleMixin): text = [] for role in sorted(roles): - for entry_point, desc in iteritems(list_json[role]['entry_points']): + for entry_point, desc in list_json[role]['entry_points'].items(): if len(desc) > linelimit: desc = desc[:linelimit] + '...' text.append("%-*s %-*s %s" % (max_role_len, role, diff --git a/lib/ansible/cli/pull.py b/lib/ansible/cli/pull.py index bff636363a0..bcbe64a23d2 100755 --- a/lib/ansible/cli/pull.py +++ b/lib/ansible/cli/pull.py @@ -14,6 +14,7 @@ import datetime import os import platform import random +import shlex import shutil import socket import sys @@ -24,7 +25,6 @@ from ansible import context from ansible.cli.arguments import option_helpers as opt_help from ansible.errors import AnsibleOptionsError from ansible.module_utils._text import to_native, to_text -from ansible.module_utils.six.moves import shlex_quote from ansible.plugins.loader import module_loader from ansible.utils.cmd_functions import run_cmd from ansible.utils.display import Display @@ -179,7 +179,7 @@ class PullCLI(CLI): if not inv_opts: inv_opts = " -i localhost, " # avoid interpreter discovery since we already know which interpreter to use on localhost - inv_opts += '-e %s ' % shlex_quote('ansible_python_interpreter=%s' % sys.executable) + inv_opts += '-e %s ' % shlex.quote('ansible_python_interpreter=%s' % sys.executable) # SCM specific options if context.CLIARGS['module_name'] == 'git': @@ -234,7 +234,7 @@ class PullCLI(CLI): context.CLIARGS['module_name'], repo_opts, limit_opts) for ev in context.CLIARGS['extra_vars']: - cmd += ' -e %s' % shlex_quote(ev) + cmd += ' -e %s' % shlex.quote(ev) # Nap? if context.CLIARGS['sleep']: @@ -269,7 +269,7 @@ class PullCLI(CLI): cmd += " --vault-id=%s" % vault_id for ev in context.CLIARGS['extra_vars']: - cmd += ' -e %s' % shlex_quote(ev) + cmd += ' -e %s' % shlex.quote(ev) if context.CLIARGS['become_ask_pass']: cmd += ' --ask-become-pass' if context.CLIARGS['skip_tags']: diff --git a/lib/ansible/cli/scripts/ansible_connection_cli_stub.py b/lib/ansible/cli/scripts/ansible_connection_cli_stub.py index f3cd5816dd5..f56e17cfb11 100755 --- a/lib/ansible/cli/scripts/ansible_connection_cli_stub.py +++ b/lib/ansible/cli/scripts/ansible_connection_cli_stub.py @@ -9,7 +9,9 @@ __metaclass__ = type import argparse import fcntl import hashlib +import io import os +import pickle import signal import socket import sys @@ -23,8 +25,6 @@ from contextlib import contextmanager from ansible import constants as C from ansible.cli.arguments.option_helpers import AnsibleVersion from ansible.module_utils._text import to_bytes, to_text -from ansible.module_utils.six import PY3 -from ansible.module_utils.six.moves import cPickle, StringIO from ansible.module_utils.connection import Connection, ConnectionError, send_data, recv_data from ansible.module_utils.service import fork_process from ansible.parsing.ajson import AnsibleJSONEncoder, AnsibleJSONDecoder @@ -236,26 +236,19 @@ def main(args=None): socket_path = None # Need stdin as a byte stream - if PY3: - stdin = sys.stdin.buffer - else: - stdin = sys.stdin + stdin = sys.stdin.buffer # Note: update the below log capture code after Display.display() is refactored. saved_stdout = sys.stdout - sys.stdout = StringIO() + sys.stdout = io.StringIO() try: # read the play context data via stdin, which means depickling it vars_data = read_stream(stdin) init_data = read_stream(stdin) - if PY3: - pc_data = cPickle.loads(init_data, encoding='bytes') - variables = cPickle.loads(vars_data, encoding='bytes') - else: - pc_data = cPickle.loads(init_data) - variables = cPickle.loads(vars_data) + pc_data = pickle.loads(init_data, encoding='bytes') + variables = pickle.loads(vars_data, encoding='bytes') play_context = PlayContext() play_context.deserialize(pc_data) diff --git a/lib/ansible/config/manager.py b/lib/ansible/config/manager.py index ee9979b0b58..2f09cfa3a9b 100644 --- a/lib/ansible/config/manager.py +++ b/lib/ansible/config/manager.py @@ -5,7 +5,7 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type import atexit -import io +import configparser import os import os.path import sys @@ -20,7 +20,6 @@ from ansible.module_utils._text import to_text, to_bytes, to_native from ansible.module_utils.common._collections_compat import Mapping, Sequence from ansible.module_utils.common.yaml import yaml_load from ansible.module_utils.six import string_types -from ansible.module_utils.six.moves import configparser from ansible.module_utils.parsing.convert_bool import boolean from ansible.parsing.quoting import unquote from ansible.parsing.yaml.objects import AnsibleVaultEncryptedUnicode diff --git a/lib/ansible/executor/play_iterator.py b/lib/ansible/executor/play_iterator.py index 96f87c2cc95..555be1f5f94 100644 --- a/lib/ansible/executor/play_iterator.py +++ b/lib/ansible/executor/play_iterator.py @@ -22,7 +22,6 @@ __metaclass__ = type import fnmatch from ansible import constants as C -from ansible.module_utils.six import iteritems from ansible.module_utils.parsing.convert_bool import boolean from ansible.playbook.block import Block from ansible.playbook.task import Task @@ -468,7 +467,7 @@ class PlayIterator: self._play._removed_hosts.append(host.name) def get_failed_hosts(self): - return dict((host, True) for (host, state) in iteritems(self._host_states) if self._check_failed_state(state)) + return dict((host, True) for (host, state) in self._host_states.items() if self._check_failed_state(state)) def _check_failed_state(self, state): if state is None: diff --git a/lib/ansible/executor/task_executor.py b/lib/ansible/executor/task_executor.py index 7de63543fe6..803ab6fe356 100644 --- a/lib/ansible/executor/task_executor.py +++ b/lib/ansible/executor/task_executor.py @@ -19,8 +19,7 @@ from ansible.errors import AnsibleError, AnsibleParserError, AnsibleUndefinedVar from ansible.executor.task_result import TaskResult from ansible.executor.module_common import get_action_args_with_defaults from ansible.module_utils.parsing.convert_bool import boolean -from ansible.module_utils.six import iteritems, binary_type -from ansible.module_utils.six.moves import xrange +from ansible.module_utils.six import binary_type from ansible.module_utils._text import to_text, to_native from ansible.module_utils.connection import write_to_file_descriptor from ansible.playbook.conditional import Conditional @@ -60,7 +59,7 @@ def remove_omit(task_args, omit_token): return task_args new_args = {} - for i in iteritems(task_args): + for i in task_args.items(): if i[1] == omit_token: continue elif isinstance(i[1], dict): @@ -408,7 +407,7 @@ class TaskExecutor: if self._connection.become: clear_plugins['become'] = self._connection.become._load_name - for plugin_type, plugin_name in iteritems(clear_plugins): + for plugin_type, plugin_name in clear_plugins.items(): for var in C.config.get_plugin_vars(plugin_type, plugin_name): if var in task_vars and var not in self._job_vars: del task_vars[var] @@ -580,7 +579,7 @@ class TaskExecutor: display.debug("starting attempt loop") result = None - for attempt in xrange(1, retries + 1): + for attempt in range(1, retries + 1): display.debug("running the handler") try: if self._task.timeout: diff --git a/lib/ansible/galaxy/api.py b/lib/ansible/galaxy/api.py index 5bd37149093..3178d47b0d1 100644 --- a/lib/ansible/galaxy/api.py +++ b/lib/ansible/galaxy/api.py @@ -16,14 +16,15 @@ import tarfile import time import threading +from urllib.error import HTTPError +from urllib.parse import quote as urlquote, urlencode, urlparse, parse_qs, urljoin + from ansible import constants as C from ansible.errors import AnsibleError from ansible.galaxy.user_agent import user_agent from ansible.module_utils.api import retry_with_delays_and_condition from ansible.module_utils.api import generate_jittered_backoff from ansible.module_utils.six import string_types -from ansible.module_utils.six.moves.urllib.error import HTTPError -from ansible.module_utils.six.moves.urllib.parse import quote as urlquote, urlencode, urlparse, parse_qs, urljoin from ansible.module_utils._text import to_bytes, to_native, to_text from ansible.module_utils.urls import open_url, prepare_multipart from ansible.utils.display import Display diff --git a/lib/ansible/galaxy/collection/concrete_artifact_manager.py b/lib/ansible/galaxy/collection/concrete_artifact_manager.py index 7406b85b9fb..f64458e5414 100644 --- a/lib/ansible/galaxy/collection/concrete_artifact_manager.py +++ b/lib/ansible/galaxy/collection/concrete_artifact_manager.py @@ -12,6 +12,8 @@ import tarfile import subprocess from contextlib import contextmanager from hashlib import sha256 +from urllib.error import URLError +from urllib.parse import urldefrag from shutil import rmtree from tempfile import mkdtemp @@ -39,8 +41,6 @@ from ansible.galaxy.dependency_resolution.dataclasses import _GALAXY_YAML from ansible.galaxy.user_agent import user_agent from ansible.module_utils._text import to_bytes, to_native, to_text from ansible.module_utils.common.yaml import yaml_load -from ansible.module_utils.six.moves.urllib.error import URLError -from ansible.module_utils.six.moves.urllib.parse import urldefrag from ansible.module_utils.six import raise_from from ansible.module_utils.urls import open_url from ansible.utils.display import Display diff --git a/lib/ansible/galaxy/dependency_resolution/dataclasses.py b/lib/ansible/galaxy/dependency_resolution/dataclasses.py index 49de8c5fc3f..ab46fbce028 100644 --- a/lib/ansible/galaxy/dependency_resolution/dataclasses.py +++ b/lib/ansible/galaxy/dependency_resolution/dataclasses.py @@ -11,6 +11,7 @@ import json import os from collections import namedtuple from glob import iglob +from urllib.parse import urlparse try: from typing import TYPE_CHECKING @@ -33,7 +34,6 @@ import yaml from ansible.errors import AnsibleError from ansible.galaxy.api import GalaxyAPI from ansible.module_utils._text import to_bytes, to_native, to_text -from ansible.module_utils.six.moves.urllib.parse import urlparse from ansible.module_utils.six import raise_from from ansible.utils.collection_loader import AnsibleCollectionRef from ansible.utils.display import Display diff --git a/lib/ansible/inventory/data.py b/lib/ansible/inventory/data.py index cf6fbb66acd..15a64202d90 100644 --- a/lib/ansible/inventory/data.py +++ b/lib/ansible/inventory/data.py @@ -25,7 +25,7 @@ from ansible import constants as C from ansible.errors import AnsibleError from ansible.inventory.group import Group from ansible.inventory.host import Host -from ansible.module_utils.six import iteritems, string_types +from ansible.module_utils.six import string_types from ansible.utils.display import Display from ansible.utils.vars import combine_vars from ansible.utils.path import basedir @@ -277,7 +277,7 @@ class InventoryData(object): We merge a 'magic' var 'groups' with group name keys and hostname list values into every host variable set. Cache for speed. """ if not self._groups_dict_cache: - for (group_name, group) in iteritems(self.groups): + for (group_name, group) in self.groups.items(): self._groups_dict_cache[group_name] = [h.name for h in group.get_hosts()] return self._groups_dict_cache diff --git a/lib/ansible/parsing/mod_args.py b/lib/ansible/parsing/mod_args.py index b3962ade135..f40631e8dda 100644 --- a/lib/ansible/parsing/mod_args.py +++ b/lib/ansible/parsing/mod_args.py @@ -21,12 +21,11 @@ __metaclass__ = type import ansible.constants as C from ansible.errors import AnsibleParserError, AnsibleError, AnsibleAssertionError -from ansible.module_utils.six import iteritems, string_types +from ansible.module_utils.six import string_types from ansible.module_utils._text import to_text from ansible.parsing.splitter import parse_kv, split_args from ansible.plugins.loader import module_loader, action_loader from ansible.template import Templar -from ansible.utils.collection_loader import AnsibleCollectionRef from ansible.utils.fqcn import add_internal_fqcns from ansible.utils.sentinel import Sentinel @@ -294,10 +293,10 @@ class ModuleArgsParser: # module: is the more new-style invocation # filter out task attributes so we're only querying unrecognized keys as actions/modules - non_task_ds = dict((k, v) for k, v in iteritems(self._task_ds) if (k not in self._task_attrs) and (not k.startswith('with_'))) + non_task_ds = dict((k, v) for k, v in self._task_ds.items() if (k not in self._task_attrs) and (not k.startswith('with_'))) # walk the filtered input dictionary to see if we recognize a module name - for item, value in iteritems(non_task_ds): + for item, value in non_task_ds.items(): context = None is_action_candidate = False if item in BUILTIN_TASKS: diff --git a/lib/ansible/parsing/vault/__init__.py b/lib/ansible/parsing/vault/__init__.py index 1b4d8113ba7..e10b9766096 100644 --- a/lib/ansible/parsing/vault/__init__.py +++ b/lib/ansible/parsing/vault/__init__.py @@ -55,8 +55,6 @@ except ImportError: from ansible.errors import AnsibleError, AnsibleAssertionError from ansible import constants as C from ansible.module_utils.six import binary_type -# Note: on py2, this zip is izip not the list based zip() builtin -from ansible.module_utils.six.moves import zip from ansible.module_utils._text import to_bytes, to_text, to_native from ansible.utils.display import Display from ansible.utils.path import makedirs_safe diff --git a/lib/ansible/playbook/base.py b/lib/ansible/playbook/base.py index 564ce0cd3a5..55a1330674c 100644 --- a/lib/ansible/playbook/base.py +++ b/lib/ansible/playbook/base.py @@ -17,7 +17,7 @@ from jinja2.exceptions import UndefinedError from ansible import constants as C from ansible import context from ansible.errors import AnsibleError -from ansible.module_utils.six import iteritems, string_types, with_metaclass +from ansible.module_utils.six import string_types from ansible.module_utils.parsing.convert_bool import boolean from ansible.errors import AnsibleParserError, AnsibleUndefinedVariable, AnsibleAssertionError from ansible.module_utils._text import to_text, to_native @@ -192,7 +192,7 @@ class BaseMeta(type): return super(BaseMeta, cls).__new__(cls, name, parents, dct) -class FieldAttributeBase(with_metaclass(BaseMeta, object)): +class FieldAttributeBase(metaclass=BaseMeta): def __init__(self): @@ -271,7 +271,7 @@ class FieldAttributeBase(with_metaclass(BaseMeta, object)): # Walk all attributes in the class. We sort them based on their priority # so that certain fields can be loaded before others, if they are dependent. - for name, attr in sorted(iteritems(self._valid_attrs), key=operator.itemgetter(1)): + for name, attr in sorted(self._valid_attrs.items(), key=operator.itemgetter(1)): # copy the value over unless a _load_field method is defined target_name = name if name in self._alias_attrs: @@ -325,7 +325,7 @@ class FieldAttributeBase(with_metaclass(BaseMeta, object)): if not self._validated: # walk all fields in the object - for (name, attribute) in iteritems(self._valid_attrs): + for (name, attribute) in self._valid_attrs.items(): if name in self._alias_attrs: name = self._alias_attrs[name] @@ -615,7 +615,7 @@ class FieldAttributeBase(with_metaclass(BaseMeta, object)): # save the omit value for later checking omit_value = templar.available_variables.get('omit') - for (name, attribute) in iteritems(self._valid_attrs): + for (name, attribute) in self._valid_attrs.items(): if attribute.static: value = getattr(self, name) @@ -742,7 +742,7 @@ class FieldAttributeBase(with_metaclass(BaseMeta, object)): Dumps all attributes to a dictionary ''' attrs = {} - for (name, attribute) in iteritems(self._valid_attrs): + for (name, attribute) in self._valid_attrs.items(): attr = getattr(self, name) if attribute.isa == 'class' and hasattr(attr, 'serialize'): attrs[name] = attr.serialize() @@ -754,7 +754,7 @@ class FieldAttributeBase(with_metaclass(BaseMeta, object)): ''' Loads attributes from a dictionary ''' - for (attr, value) in iteritems(attrs): + for (attr, value) in attrs.items(): if attr in self._valid_attrs: attribute = self._valid_attrs[attr] if attribute.isa == 'class' and isinstance(value, dict): @@ -800,7 +800,7 @@ class FieldAttributeBase(with_metaclass(BaseMeta, object)): if not isinstance(data, dict): raise AnsibleAssertionError('data (%s) should be a dict but is a %s' % (data, type(data))) - for (name, attribute) in iteritems(self._valid_attrs): + for (name, attribute) in self._valid_attrs.items(): if name in data: setattr(self, name, data[name]) else: diff --git a/lib/ansible/playbook/play_context.py b/lib/ansible/playbook/play_context.py index a3b70f5a5f0..21bd84c0256 100644 --- a/lib/ansible/playbook/play_context.py +++ b/lib/ansible/playbook/play_context.py @@ -21,19 +21,13 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type -import os -import sys - from ansible import constants as C from ansible import context -from ansible.errors import AnsibleError from ansible.module_utils.compat.paramiko import paramiko -from ansible.module_utils.six import iteritems from ansible.playbook.attribute import FieldAttribute from ansible.playbook.base import Base from ansible.plugins import get_plugin_class from ansible.utils.display import Display -from ansible.plugins.loader import get_shell_plugin from ansible.utils.ssh_functions import check_for_controlpersist @@ -257,7 +251,7 @@ class PlayContext(Base): setattr(new_info, 'executable', variables.get(exe_var)) attrs_considered = [] - for (attr, variable_names) in iteritems(C.MAGIC_VARIABLE_MAPPING): + for (attr, variable_names) in C.MAGIC_VARIABLE_MAPPING.items(): for variable_name in variable_names: if attr in attrs_considered: continue diff --git a/lib/ansible/playbook/playbook_include.py b/lib/ansible/playbook/playbook_include.py index d65f7966f36..91bcf5163a7 100644 --- a/lib/ansible/playbook/playbook_include.py +++ b/lib/ansible/playbook/playbook_include.py @@ -24,7 +24,7 @@ import os import ansible.constants as C from ansible.errors import AnsibleParserError, AnsibleAssertionError from ansible.module_utils._text import to_bytes -from ansible.module_utils.six import iteritems, string_types +from ansible.module_utils.six import string_types from ansible.parsing.splitter import split_args, parse_kv from ansible.parsing.yaml.objects import AnsibleBaseYAMLObject, AnsibleMapping from ansible.playbook.attribute import FieldAttribute @@ -139,7 +139,7 @@ class PlaybookInclude(Base, Conditional, Taggable): if isinstance(ds, AnsibleBaseYAMLObject): new_ds.ansible_pos = ds.ansible_pos - for (k, v) in iteritems(ds): + for (k, v) in ds.items(): if k in C._ACTION_IMPORT_PLAYBOOK: self._preprocess_import(ds, new_ds, k, v) else: diff --git a/lib/ansible/playbook/role/__init__.py b/lib/ansible/playbook/role/__init__.py index 43d4b271522..7bb6972826d 100644 --- a/lib/ansible/playbook/role/__init__.py +++ b/lib/ansible/playbook/role/__init__.py @@ -24,7 +24,7 @@ import os from ansible import constants as C from ansible.errors import AnsibleError, AnsibleParserError, AnsibleAssertionError from ansible.module_utils._text import to_text -from ansible.module_utils.six import iteritems, binary_type, text_type +from ansible.module_utils.six import binary_type, text_type from ansible.module_utils.common._collections_compat import Container, Mapping, Set, Sequence from ansible.playbook.attribute import FieldAttribute from ansible.playbook.base import Base @@ -161,7 +161,7 @@ class Role(Base, Conditional, Taggable, CollectionSearch): hashed_params = hash_params(params) if role_include.get_name() in play.ROLE_CACHE: - for (entry, role_obj) in iteritems(play.ROLE_CACHE[role_include.get_name()]): + for (entry, role_obj) in play.ROLE_CACHE[role_include.get_name()].items(): if hashed_params == entry: if parent_role: role_obj.add_parent(parent_role) @@ -198,7 +198,7 @@ class Role(Base, Conditional, Taggable, CollectionSearch): # copy over all field attributes from the RoleInclude # update self._attributes directly, to avoid squashing - for (attr_name, dump) in iteritems(self._valid_attrs): + for (attr_name, dump) in self._valid_attrs.items(): if attr_name in ('when', 'tags'): self._attributes[attr_name] = self._extend_value( self._attributes[attr_name], diff --git a/lib/ansible/playbook/role/definition.py b/lib/ansible/playbook/role/definition.py index 20d69ebd6b3..c1c1364eb67 100644 --- a/lib/ansible/playbook/role/definition.py +++ b/lib/ansible/playbook/role/definition.py @@ -23,9 +23,9 @@ import os from ansible import constants as C from ansible.errors import AnsibleError, AnsibleAssertionError -from ansible.module_utils.six import iteritems, string_types +from ansible.module_utils.six import string_types from ansible.parsing.yaml.objects import AnsibleBaseYAMLObject, AnsibleMapping -from ansible.playbook.attribute import Attribute, FieldAttribute +from ansible.playbook.attribute import FieldAttribute from ansible.playbook.base import Base from ansible.playbook.collectionsearch import CollectionSearch from ansible.playbook.conditional import Conditional @@ -211,7 +211,7 @@ class RoleDefinition(Base, Conditional, Taggable, CollectionSearch): role_def = dict() role_params = dict() base_attribute_names = frozenset(self._valid_attrs.keys()) - for (key, value) in iteritems(ds): + for (key, value) in ds.items(): # use the list of FieldAttribute values to determine what is and is not # an extra parameter for this role (or sub-class of this role) # FIXME: hard-coded list of exception key names here corresponds to the diff --git a/lib/ansible/playbook/role/include.py b/lib/ansible/playbook/role/include.py index 1e5d901d96e..6274fc631f7 100644 --- a/lib/ansible/playbook/role/include.py +++ b/lib/ansible/playbook/role/include.py @@ -19,14 +19,11 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type -import os - from ansible.errors import AnsibleError, AnsibleParserError -from ansible.module_utils.six import iteritems, string_types +from ansible.module_utils.six import string_types from ansible.parsing.yaml.objects import AnsibleBaseYAMLObject -from ansible.playbook.attribute import Attribute, FieldAttribute +from ansible.playbook.attribute import FieldAttribute from ansible.playbook.role.definition import RoleDefinition -from ansible.playbook.role.requirement import RoleRequirement from ansible.module_utils._text import to_native diff --git a/lib/ansible/playbook/task.py b/lib/ansible/playbook/task.py index 63969e4abf5..2f1f92cb6cc 100644 --- a/lib/ansible/playbook/task.py +++ b/lib/ansible/playbook/task.py @@ -19,12 +19,10 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type -import os - from ansible import constants as C from ansible.errors import AnsibleError, AnsibleParserError, AnsibleUndefinedVariable, AnsibleAssertionError from ansible.module_utils._text import to_native -from ansible.module_utils.six import iteritems, string_types +from ansible.module_utils.six import string_types from ansible.parsing.mod_args import ModuleArgsParser from ansible.parsing.yaml.objects import AnsibleBaseYAMLObject, AnsibleMapping from ansible.plugins.loader import lookup_loader @@ -126,7 +124,7 @@ class Task(Base, Conditional, Taggable, CollectionSearch): return ds elif isinstance(ds, dict): buf = "" - for (k, v) in iteritems(ds): + for (k, v) in ds.items(): if k.startswith('_'): continue buf = buf + "%s=%s " % (k, v) @@ -239,7 +237,7 @@ class Task(Base, Conditional, Taggable, CollectionSearch): else: new_ds['vars'] = dict() - for (k, v) in iteritems(ds): + for (k, v) in ds.items(): if k in ('action', 'local_action', 'args', 'delegate_to') or k == action or k == 'shell': # we don't want to re-assign these values, which were determined by the ModuleArgsParser() above continue diff --git a/lib/ansible/plugins/__init__.py b/lib/ansible/plugins/__init__.py index 2bb1a4c9a27..b08e322d898 100644 --- a/lib/ansible/plugins/__init__.py +++ b/lib/ansible/plugins/__init__.py @@ -21,12 +21,12 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type -from abc import ABCMeta +from abc import ABC from ansible import constants as C from ansible.errors import AnsibleError from ansible.module_utils._text import to_native -from ansible.module_utils.six import with_metaclass, string_types +from ansible.module_utils.six import string_types from ansible.utils.display import Display display = Display() @@ -44,7 +44,7 @@ def get_plugin_class(obj): return obj.__class__.__name__.lower().replace('module', '') -class AnsiblePlugin(with_metaclass(ABCMeta, object)): +class AnsiblePlugin(ABC): # allow extra passthrough parameters allow_extras = False diff --git a/lib/ansible/plugins/action/__init__.py b/lib/ansible/plugins/action/__init__.py index 4f01af48e73..ac5ecf3aa0b 100644 --- a/lib/ansible/plugins/action/__init__.py +++ b/lib/ansible/plugins/action/__init__.py @@ -12,9 +12,10 @@ import json import os import random import re +import shlex import stat import tempfile -from abc import ABCMeta, abstractmethod +from abc import ABC, abstractmethod from ansible import constants as C from ansible.errors import AnsibleError, AnsibleConnectionFailure, AnsibleActionSkip, AnsibleActionFail, AnsibleAuthenticationFailure @@ -22,8 +23,7 @@ from ansible.executor.module_common import modify_module from ansible.executor.interpreter_discovery import discover_interpreter, InterpreterDiscoveryRequiredError from ansible.module_utils.common._collections_compat import Sequence from ansible.module_utils.json_utils import _filter_non_json_lines -from ansible.module_utils.six import binary_type, string_types, text_type, iteritems, with_metaclass -from ansible.module_utils.six.moves import shlex_quote +from ansible.module_utils.six import binary_type, string_types, text_type from ansible.module_utils._text import to_bytes, to_native, to_text from ansible.parsing.utils.jsonify import jsonify from ansible.release import __version__ @@ -36,7 +36,7 @@ from ansible.utils.plugin_docs import get_versioned_doclink display = Display() -class ActionBase(with_metaclass(ABCMeta, object)): +class ActionBase(ABC): ''' This class is the base class for all action plugins, and defines @@ -1023,8 +1023,8 @@ class ActionBase(with_metaclass(ABCMeta, object)): # we need to dump the module args to a k=v string in a file on # the remote system, which can be read and parsed by the module args_data = "" - for k, v in iteritems(module_args): - args_data += '%s=%s ' % (k, shlex_quote(text_type(v))) + for k, v in module_args.items(): + args_data += '%s=%s ' % (k, shlex.quote(text_type(v))) self._transfer_data(args_file_path, args_data) elif module_style in ('non_native_want_json', 'binary'): self._transfer_data(args_file_path, json.dumps(module_args)) @@ -1242,7 +1242,7 @@ class ActionBase(with_metaclass(ABCMeta, object)): # only applied for the default executable to avoid interfering with the raw action cmd = self._connection._shell.append_command(cmd, 'sleep 0') if executable: - cmd = executable + ' -c ' + shlex_quote(cmd) + cmd = executable + ' -c ' + shlex.quote(cmd) display.debug("_low_level_execute_command(): executing: %s" % (cmd,)) diff --git a/lib/ansible/plugins/action/pause.py b/lib/ansible/plugins/action/pause.py index 2bc7d6f6f31..6130d860d2d 100644 --- a/lib/ansible/plugins/action/pause.py +++ b/lib/ansible/plugins/action/pause.py @@ -32,7 +32,6 @@ from os import ( from ansible.errors import AnsibleError from ansible.module_utils._text import to_text, to_native from ansible.module_utils.parsing.convert_bool import boolean -from ansible.module_utils.six import PY3 from ansible.plugins.action import ActionBase from ansible.utils.display import Display @@ -185,12 +184,8 @@ class ActionModule(ActionBase): stdin_fd = None stdout_fd = None try: - if PY3: - stdin = self._connection._new_stdin.buffer - stdout = sys.stdout.buffer - else: - stdin = self._connection._new_stdin - stdout = sys.stdout + stdin = self._connection._new_stdin.buffer + stdout = sys.stdout.buffer stdin_fd = stdin.fileno() stdout_fd = stdout.fileno() except (ValueError, AttributeError): diff --git a/lib/ansible/plugins/action/set_fact.py b/lib/ansible/plugins/action/set_fact.py index df1c0a43da9..ae92de8088b 100644 --- a/lib/ansible/plugins/action/set_fact.py +++ b/lib/ansible/plugins/action/set_fact.py @@ -19,7 +19,7 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type from ansible.errors import AnsibleActionFail -from ansible.module_utils.six import iteritems, string_types +from ansible.module_utils.six import string_types from ansible.module_utils.parsing.convert_bool import boolean from ansible.plugins.action import ActionBase from ansible.utils.vars import isidentifier @@ -42,7 +42,7 @@ class ActionModule(ActionBase): cacheable = boolean(self._task.args.pop('cacheable', False)) if self._task.args: - for (k, v) in iteritems(self._task.args): + for (k, v) in self._task.args.items(): k = self._templar.template(k) if not isidentifier(k): diff --git a/lib/ansible/plugins/action/set_stats.py b/lib/ansible/plugins/action/set_stats.py index f9fe8b30148..9d429ced8dd 100644 --- a/lib/ansible/plugins/action/set_stats.py +++ b/lib/ansible/plugins/action/set_stats.py @@ -18,7 +18,7 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type -from ansible.module_utils.six import iteritems, string_types +from ansible.module_utils.six import string_types from ansible.module_utils.parsing.convert_bool import boolean from ansible.plugins.action import ActionBase from ansible.utils.vars import isidentifier @@ -59,7 +59,7 @@ class ActionModule(ActionBase): else: stats[opt] = val - for (k, v) in iteritems(data): + for (k, v) in data.items(): k = self._templar.template(k) diff --git a/lib/ansible/plugins/action/validate_argument_spec.py b/lib/ansible/plugins/action/validate_argument_spec.py index e73729e0508..8c4432d111a 100644 --- a/lib/ansible/plugins/action/validate_argument_spec.py +++ b/lib/ansible/plugins/action/validate_argument_spec.py @@ -6,7 +6,7 @@ __metaclass__ = type from ansible.errors import AnsibleError from ansible.plugins.action import ActionBase -from ansible.module_utils.six import iteritems, string_types +from ansible.module_utils.six import string_types from ansible.module_utils.common.arg_spec import ArgumentSpecValidator from ansible.module_utils.errors import AnsibleValidationErrorMultiple from ansible.utils.vars import combine_vars @@ -30,7 +30,7 @@ class ActionModule(ActionBase): ''' args = {} - for argument_name, argument_attrs in iteritems(argument_spec): + for argument_name, argument_attrs in argument_spec.items(): if argument_name in task_vars: args[argument_name] = task_vars[argument_name] args = self._templar.template(args) diff --git a/lib/ansible/plugins/become/__init__.py b/lib/ansible/plugins/become/__init__.py index f20326c633e..c373c1d4ad4 100644 --- a/lib/ansible/plugins/become/__init__.py +++ b/lib/ansible/plugins/become/__init__.py @@ -4,13 +4,14 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type +import shlex + from abc import abstractmethod from random import choice from string import ascii_lowercase from gettext import dgettext from ansible.errors import AnsibleError -from ansible.module_utils.six.moves import shlex_quote from ansible.module_utils._text import to_bytes from ansible.plugins import AnsiblePlugin @@ -64,7 +65,7 @@ class BecomeBase(AnsiblePlugin): return cmd try: - cmd = shlex_quote('%s %s %s %s' % (shell.ECHO, self.success, shell.COMMAND_SEP, cmd)) + cmd = shlex.quote('%s %s %s %s' % (shell.ECHO, self.success, shell.COMMAND_SEP, cmd)) except AttributeError: # TODO: This should probably become some more robust functionlity used to detect incompat raise AnsibleError('The %s shell family is incompatible with the %s become plugin' % (shell.SHELL_FAMILY, self.name)) diff --git a/lib/ansible/plugins/become/su.py b/lib/ansible/plugins/become/su.py index 6b09d89056c..90ef6eaee44 100644 --- a/lib/ansible/plugins/become/su.py +++ b/lib/ansible/plugins/become/su.py @@ -85,9 +85,9 @@ DOCUMENTATION = """ """ import re +import shlex from ansible.module_utils._text import to_bytes -from ansible.module_utils.six.moves import shlex_quote from ansible.plugins.become import BecomeBase @@ -158,4 +158,4 @@ class BecomeModule(BecomeBase): user = self.get_option('become_user') or '' success_cmd = self._build_success_command(cmd, shell) - return "%s %s %s -c %s" % (exe, flags, user, shlex_quote(success_cmd)) + return "%s %s %s -c %s" % (exe, flags, user, shlex.quote(success_cmd)) diff --git a/lib/ansible/plugins/cache/__init__.py b/lib/ansible/plugins/cache/__init__.py index bd023a5c348..49f137cf4c2 100644 --- a/lib/ansible/plugins/cache/__init__.py +++ b/lib/ansible/plugins/cache/__init__.py @@ -22,11 +22,10 @@ import copy import os import time import errno -from abc import ABCMeta, abstractmethod +from abc import abstractmethod from ansible import constants as C from ansible.errors import AnsibleError -from ansible.module_utils.six import with_metaclass from ansible.module_utils._text import to_bytes, to_text from ansible.module_utils.common._collections_compat import MutableMapping from ansible.plugins import AnsiblePlugin diff --git a/lib/ansible/plugins/connection/paramiko_ssh.py b/lib/ansible/plugins/connection/paramiko_ssh.py index 24362135941..4692d099864 100644 --- a/lib/ansible/plugins/connection/paramiko_ssh.py +++ b/lib/ansible/plugins/connection/paramiko_ssh.py @@ -148,8 +148,6 @@ from ansible.errors import ( AnsibleFileNotFound, ) from ansible.module_utils.compat.paramiko import PARAMIKO_IMPORT_ERR, paramiko -from ansible.module_utils.six import iteritems -from ansible.module_utils.six.moves import input from ansible.plugins.connection import ConnectionBase from ansible.utils.display import Display from ansible.utils.path import makedirs_safe @@ -500,8 +498,8 @@ class Connection(ConnectionBase): def _any_keys_added(self): - for hostname, keys in iteritems(self.ssh._host_keys): - for keytype, key in iteritems(keys): + for hostname, keys in self.ssh._host_keys.items(): + for keytype, key in keys.items(): added_this_time = getattr(key, '_added_by_ansible_this_time', False) if added_this_time: return True @@ -521,18 +519,18 @@ class Connection(ConnectionBase): with open(filename, 'w') as f: - for hostname, keys in iteritems(self.ssh._host_keys): + for hostname, keys in self.ssh._host_keys.items(): - for keytype, key in iteritems(keys): + for keytype, key in keys.items(): # was f.write added_this_time = getattr(key, '_added_by_ansible_this_time', False) if not added_this_time: f.write("%s %s %s\n" % (hostname, keytype, key.get_base64())) - for hostname, keys in iteritems(self.ssh._host_keys): + for hostname, keys in self.ssh._host_keys.items(): - for keytype, key in iteritems(keys): + for keytype, key in keys.items(): added_this_time = getattr(key, '_added_by_ansible_this_time', False) if added_this_time: f.write("%s %s %s\n" % (hostname, keytype, key.get_base64())) diff --git a/lib/ansible/plugins/connection/ssh.py b/lib/ansible/plugins/connection/ssh.py index 08e90ce0814..fe47ae05d95 100644 --- a/lib/ansible/plugins/connection/ssh.py +++ b/lib/ansible/plugins/connection/ssh.py @@ -352,6 +352,7 @@ import hashlib import os import pty import re +import shlex import subprocess import time @@ -366,7 +367,6 @@ from ansible.errors import ( 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.six.moves import shlex_quote from ansible.module_utils._text import to_bytes, to_native, to_text from ansible.module_utils.parsing.convert_bool import BOOLEANS, boolean from ansible.plugins.connection import ConnectionBase, BUFSIZE @@ -868,7 +868,7 @@ class Connection(ConnectionBase): ''' # We don't use _shell.quote as this is run on the controller and independent from the shell plugin chosen - display_cmd = u' '.join(shlex_quote(to_text(c)) for c in cmd) + display_cmd = u' '.join(shlex.quote(to_text(c)) for c in cmd) display.vvv(u'SSH: EXEC {0}'.format(display_cmd), host=self.host) # Start the given command. If we don't need to pipeline data, we can try @@ -1208,7 +1208,7 @@ class Connection(ConnectionBase): returncode = stdout = stderr = None if method == 'sftp': cmd = self._build_command(self.get_option('sftp_executable'), 'sftp', to_bytes(host)) - in_data = u"{0} {1} {2}\n".format(sftp_action, shlex_quote(in_path), shlex_quote(out_path)) + in_data = u"{0} {1} {2}\n".format(sftp_action, shlex.quote(in_path), shlex.quote(out_path)) in_data = to_bytes(in_data, nonstring='passthru') (returncode, stdout, stderr) = self._bare_run(cmd, in_data, checkrc=False) elif method == 'scp': diff --git a/lib/ansible/plugins/connection/winrm.py b/lib/ansible/plugins/connection/winrm.py index dd52288ee65..ddcbe2c6029 100644 --- a/lib/ansible/plugins/connection/winrm.py +++ b/lib/ansible/plugins/connection/winrm.py @@ -144,6 +144,9 @@ import tempfile import shlex import subprocess +from inspect import getfullargspec +from urllib.parse import urlunsplit + HAVE_KERBEROS = False try: import kerberos @@ -156,20 +159,13 @@ from ansible.errors import AnsibleError, AnsibleConnectionFailure from ansible.errors import AnsibleFileNotFound from ansible.module_utils.json_utils import _filter_non_json_lines from ansible.module_utils.parsing.convert_bool import boolean -from ansible.module_utils.six.moves.urllib.parse import urlunsplit from ansible.module_utils._text import to_bytes, to_native, to_text -from ansible.module_utils.six import binary_type, PY3 +from ansible.module_utils.six import binary_type from ansible.plugins.connection import ConnectionBase from ansible.plugins.shell.powershell import _parse_clixml from ansible.utils.hashing import secure_hash from ansible.utils.display import Display -# getargspec is deprecated in favour of getfullargspec in Python 3 but -# getfullargspec is not available in Python 2 -if PY3: - from inspect import getfullargspec as getargspec -else: - from inspect import getargspec try: import winrm @@ -195,7 +191,7 @@ try: # we can only use pexpect for kerb auth if echo is a valid kwarg # https://github.com/ansible/ansible/issues/43462 if hasattr(pexpect, 'spawn'): - argspec = getargspec(pexpect.spawn.__init__) + argspec = getfullargspec(pexpect.spawn.__init__) if 'echo' in argspec.args: HAS_PEXPECT = True except ImportError as e: @@ -295,7 +291,7 @@ class Connection(ConnectionBase): internal_kwarg_mask = {'self', 'endpoint', 'transport', 'username', 'password', 'scheme', 'path', 'kinit_mode', 'kinit_cmd'} self._winrm_kwargs = dict(username=self._winrm_user, password=self._winrm_pass) - argspec = getargspec(Protocol.__init__) + argspec = getfullargspec(Protocol.__init__) supported_winrm_args = set(argspec.args) supported_winrm_args.update(internal_kwarg_mask) passed_winrm_args = {v.replace('ansible_winrm_', '') for v in self.get_option('_extras')} diff --git a/lib/ansible/plugins/filter/core.py b/lib/ansible/plugins/filter/core.py index b382945168b..703575c0fc3 100644 --- a/lib/ansible/plugins/filter/core.py +++ b/lib/ansible/plugins/filter/core.py @@ -12,6 +12,7 @@ import json import ntpath import os.path import re +import shlex import sys import time import uuid @@ -25,7 +26,6 @@ from jinja2.filters import pass_environment from ansible.errors import AnsibleError, AnsibleFilterError, AnsibleFilterTypeError from ansible.module_utils.six import string_types, integer_types, reraise, text_type -from ansible.module_utils.six.moves import shlex_quote from ansible.module_utils._text import to_bytes, to_native, to_text from ansible.module_utils.common.collections import is_sequence from ansible.module_utils.common._collections_compat import Mapping @@ -102,7 +102,7 @@ def quote(a): ''' return its argument quoted for shell usage ''' if a is None: a = u'' - return shlex_quote(to_text(a)) + return shlex.quote(to_text(a)) def fileglob(pathname): diff --git a/lib/ansible/plugins/filter/mathstuff.py b/lib/ansible/plugins/filter/mathstuff.py index 6c0469e30a9..8c4f5270e2c 100644 --- a/lib/ansible/plugins/filter/mathstuff.py +++ b/lib/ansible/plugins/filter/mathstuff.py @@ -31,7 +31,6 @@ from jinja2.filters import pass_environment from ansible.errors import AnsibleFilterError, AnsibleFilterTypeError from ansible.module_utils.common.text import formatters from ansible.module_utils.six import binary_type, text_type -from ansible.module_utils.six.moves import zip, zip_longest from ansible.module_utils.common._collections_compat import Hashable, Mapping, Iterable from ansible.module_utils._text import to_native, to_text from ansible.utils.display import Display @@ -246,7 +245,7 @@ class FilterModule(object): # zip 'zip': zip, - 'zip_longest': zip_longest, + 'zip_longest': itertools.zip_longest, } diff --git a/lib/ansible/plugins/filter/urlsplit.py b/lib/ansible/plugins/filter/urlsplit.py index 84e460aad15..500782757ac 100644 --- a/lib/ansible/plugins/filter/urlsplit.py +++ b/lib/ansible/plugins/filter/urlsplit.py @@ -6,8 +6,9 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type +from urllib.parse import urlsplit + from ansible.errors import AnsibleFilterError -from ansible.module_utils.six.moves.urllib.parse import urlsplit from ansible.utils import helpers diff --git a/lib/ansible/plugins/inventory/script.py b/lib/ansible/plugins/inventory/script.py index 0c028c70063..e992629d29c 100644 --- a/lib/ansible/plugins/inventory/script.py +++ b/lib/ansible/plugins/inventory/script.py @@ -35,7 +35,6 @@ import subprocess from ansible.errors import AnsibleError, AnsibleParserError from ansible.module_utils.basic import json_dict_bytes_to_unicode -from ansible.module_utils.six import iteritems from ansible.module_utils._text import to_native, to_text from ansible.module_utils.common._collections_compat import Mapping from ansible.plugins.inventory import BaseInventoryPlugin @@ -171,7 +170,7 @@ class InventoryModule(BaseInventoryPlugin): if not isinstance(data['vars'], dict): raise AnsibleError("You defined a group '%s' with bad data for variables:\n %s" % (group, data)) - for k, v in iteritems(data['vars']): + for k, v in data['vars'].items(): self.inventory.set_variable(group, k, v) if group != '_meta' and isinstance(data, dict) and 'children' in data: diff --git a/lib/ansible/plugins/lookup/ini.py b/lib/ansible/plugins/lookup/ini.py index 460bf9c6328..6efdaf0a290 100644 --- a/lib/ansible/plugins/lookup/ini.py +++ b/lib/ansible/plugins/lookup/ini.py @@ -76,6 +76,7 @@ _raw: elements: str """ +import configparser import os import re @@ -83,7 +84,6 @@ from io import StringIO from collections import defaultdict from ansible.errors import AnsibleLookupError, AnsibleOptionsError -from ansible.module_utils.six.moves import configparser from ansible.module_utils._text import to_text, to_native from ansible.module_utils.common._collections_compat import MutableSequence from ansible.plugins.lookup import LookupBase diff --git a/lib/ansible/plugins/lookup/sequence.py b/lib/ansible/plugins/lookup/sequence.py index 7dac37bd528..26ab7a9df0a 100644 --- a/lib/ansible/plugins/lookup/sequence.py +++ b/lib/ansible/plugins/lookup/sequence.py @@ -81,7 +81,6 @@ RETURN = """ from re import compile as re_compile, IGNORECASE from ansible.errors import AnsibleError -from ansible.module_utils.six.moves import xrange from ansible.parsing.splitter import parse_kv from ansible.plugins.lookup import LookupBase @@ -231,7 +230,7 @@ class LookupModule(LookupBase): adjust = 1 else: adjust = -1 - numbers = xrange(self.start, self.end + adjust, self.stride) + numbers = range(self.start, self.end + adjust, self.stride) for i in numbers: try: diff --git a/lib/ansible/plugins/lookup/together.py b/lib/ansible/plugins/lookup/together.py index 8ba62f148cd..ecc167d2b94 100644 --- a/lib/ansible/plugins/lookup/together.py +++ b/lib/ansible/plugins/lookup/together.py @@ -35,8 +35,9 @@ RETURN = """ type: list elements: list """ +import itertools + from ansible.errors import AnsibleError -from ansible.module_utils.six.moves import zip_longest from ansible.plugins.lookup import LookupBase from ansible.utils.listify import listify_lookup_plugin_terms @@ -64,4 +65,4 @@ class LookupModule(LookupBase): if len(my_list) == 0: raise AnsibleError("with_together requires at least one element in each list") - return [self._flatten(x) for x in zip_longest(*my_list, fillvalue=None)] + return [self._flatten(x) for x in itertools.zip_longest(*my_list, fillvalue=None)] diff --git a/lib/ansible/plugins/lookup/url.py b/lib/ansible/plugins/lookup/url.py index 026590f3274..17eeb8e547a 100644 --- a/lib/ansible/plugins/lookup/url.py +++ b/lib/ansible/plugins/lookup/url.py @@ -173,8 +173,9 @@ RETURN = """ elements: str """ +from urllib.error import HTTPError, URLError + from ansible.errors import AnsibleError -from ansible.module_utils.six.moves.urllib.error import HTTPError, URLError from ansible.module_utils._text import to_text, to_native from ansible.module_utils.urls import open_url, ConnectionError, SSLValidationError from ansible.plugins.lookup import LookupBase diff --git a/lib/ansible/plugins/shell/__init__.py b/lib/ansible/plugins/shell/__init__.py index 8aeab292abc..513ddb6fe8d 100644 --- a/lib/ansible/plugins/shell/__init__.py +++ b/lib/ansible/plugins/shell/__init__.py @@ -21,11 +21,11 @@ import os import os.path import random import re +import shlex import time from ansible.errors import AnsibleError from ansible.module_utils.six import text_type -from ansible.module_utils.six.moves import shlex_quote from ansible.module_utils._text import to_native from ansible.plugins import AnsiblePlugin @@ -80,7 +80,7 @@ class ShellBase(AnsiblePlugin): return 'ansible-tmp-%s-%s-%s' % (time.time(), os.getpid(), random.randint(0, 2**48)) def env_prefix(self, **kwargs): - return ' '.join(['%s=%s' % (k, shlex_quote(text_type(v))) for k, v in kwargs.items()]) + return ' '.join(['%s=%s' % (k, shlex.quote(text_type(v))) for k, v in kwargs.items()]) def join_path(self, *args): return os.path.join(*args) @@ -96,21 +96,21 @@ class ShellBase(AnsiblePlugin): def chmod(self, paths, mode): cmd = ['chmod', mode] cmd.extend(paths) - cmd = [shlex_quote(c) for c in cmd] + cmd = [shlex.quote(c) for c in cmd] return ' '.join(cmd) def chown(self, paths, user): cmd = ['chown', user] cmd.extend(paths) - cmd = [shlex_quote(c) for c in cmd] + cmd = [shlex.quote(c) for c in cmd] return ' '.join(cmd) def chgrp(self, paths, group): cmd = ['chgrp', group] cmd.extend(paths) - cmd = [shlex_quote(c) for c in cmd] + cmd = [shlex.quote(c) for c in cmd] return ' '.join(cmd) @@ -118,19 +118,19 @@ class ShellBase(AnsiblePlugin): """Only sets acls for users as that's really all we need""" cmd = ['setfacl', '-m', 'u:%s:%s' % (user, mode)] cmd.extend(paths) - cmd = [shlex_quote(c) for c in cmd] + cmd = [shlex.quote(c) for c in cmd] return ' '.join(cmd) def remove(self, path, recurse=False): - path = shlex_quote(path) + path = shlex.quote(path) cmd = 'rm -f ' if recurse: cmd += '-r ' return cmd + "%s %s" % (path, self._SHELL_REDIRECT_ALLNULL) def exists(self, path): - cmd = ['test', '-e', shlex_quote(path)] + cmd = ['test', '-e', shlex.quote(path)] return ' '.join(cmd) def mkdtemp(self, basefile=None, system=False, mode=0o700, tmpdir=None): @@ -189,8 +189,8 @@ class ShellBase(AnsiblePlugin): # Check that the user_path to expand is safe if user_home_path != '~': if not _USER_HOME_PATH_RE.match(user_home_path): - # shlex_quote will make the shell return the string verbatim - user_home_path = shlex_quote(user_home_path) + # shlex.quote will make the shell return the string verbatim + user_home_path = shlex.quote(user_home_path) elif username: # if present the user name is appended to resolve "that user's home" user_home_path += username @@ -204,7 +204,7 @@ class ShellBase(AnsiblePlugin): def build_module_command(self, env_string, shebang, cmd, arg_path=None): # don't quote the cmd if it's an empty string, because this will break pipelining mode if cmd.strip() != '': - cmd = shlex_quote(cmd) + cmd = shlex.quote(cmd) cmd_parts = [] if shebang: @@ -231,4 +231,4 @@ class ShellBase(AnsiblePlugin): def quote(self, cmd): """Returns a shell-escaped string that can be safely used as one token in a shell command line""" - return shlex_quote(cmd) + return shlex.quote(cmd) diff --git a/lib/ansible/plugins/shell/sh.py b/lib/ansible/plugins/shell/sh.py index 5b13a015a23..146c46671b7 100644 --- a/lib/ansible/plugins/shell/sh.py +++ b/lib/ansible/plugins/shell/sh.py @@ -14,7 +14,8 @@ extends_documentation_fragment: - shell_common ''' -from ansible.module_utils.six.moves import shlex_quote +import shlex + from ansible.plugins.shell import ShellBase @@ -66,7 +67,7 @@ class ShellModule(ShellBase): # Quoting gets complex here. We're writing a python string that's # used by a variety of shells on the remote host to invoke a python # "one-liner". - shell_escaped_path = shlex_quote(path) + shell_escaped_path = shlex.quote(path) test = "rc=flag; [ -r %(p)s ] %(shell_or)s rc=2; [ -f %(p)s ] %(shell_or)s rc=1; [ -d %(p)s ] %(shell_and)s rc=3; %(i)s -V 2>/dev/null %(shell_or)s rc=4; [ x\"$rc\" != \"xflag\" ] %(shell_and)s echo \"${rc} \"%(p)s %(shell_and)s exit 0" % dict(p=shell_escaped_path, i=python_interp, shell_and=self._SHELL_AND, shell_or=self._SHELL_OR) # NOQA csums = [ u"({0} -c 'import hashlib; BLOCKSIZE = 65536; hasher = hashlib.sha1();{2}afile = open(\"'{1}'\", \"rb\"){2}buf = afile.read(BLOCKSIZE){2}while len(buf) > 0:{2}\thasher.update(buf){2}\tbuf = afile.read(BLOCKSIZE){2}afile.close(){2}print(hasher.hexdigest())' 2>/dev/null)".format(python_interp, shell_escaped_path, self._SHELL_EMBEDDED_PY_EOL), # NOQA Python > 2.4 (including python3) diff --git a/lib/ansible/plugins/strategy/__init__.py b/lib/ansible/plugins/strategy/__init__.py index f415709a543..e30f8318180 100644 --- a/lib/ansible/plugins/strategy/__init__.py +++ b/lib/ansible/plugins/strategy/__init__.py @@ -29,17 +29,18 @@ import time from collections import deque from multiprocessing import Lock +from queue import Queue + from jinja2.exceptions import UndefinedError from ansible import constants as C from ansible import context -from ansible.errors import AnsibleError, AnsibleFileNotFound, AnsibleParserError, AnsibleUndefinedVariable +from ansible.errors import AnsibleError, AnsibleFileNotFound, AnsibleUndefinedVariable from ansible.executor import action_write_locks from ansible.executor.process.worker import WorkerProcess from ansible.executor.task_result import TaskResult from ansible.executor.task_queue_manager import CallbackSend -from ansible.module_utils.six.moves import queue as Queue -from ansible.module_utils.six import iteritems, itervalues, string_types +from ansible.module_utils.six import string_types from ansible.module_utils._text import to_text from ansible.module_utils.connection import Connection, ConnectionError from ansible.playbook.conditional import Conditional @@ -260,7 +261,7 @@ class StrategyBase: def cleanup(self): # close active persistent connections - for sock in itervalues(self._active_connections): + for sock in self._active_connections.values(): try: conn = Connection(sock) conn.reset() @@ -679,7 +680,7 @@ class StrategyBase: host_list = self.get_task_hosts(iterator, original_host, original_task) if original_task.action in C._ACTION_INCLUDE_VARS: - for (var_name, var_value) in iteritems(result_item['ansible_facts']): + for (var_name, var_value) in result_item['ansible_facts'].items(): # find the host we're actually referring too here, which may # be a host that is not really in inventory at all for target_host in host_list: @@ -749,7 +750,7 @@ class StrategyBase: if original_task._role is not None and role_ran: # TODO: and original_task.action not in C._ACTION_INCLUDE_ROLE:? # lookup the role in the ROLE_CACHE to make sure we're dealing # with the correct object and mark it as executed - for (entry, role_obj) in iteritems(iterator._play.ROLE_CACHE[original_task._role.get_name()]): + for (entry, role_obj) in iterator._play.ROLE_CACHE[original_task._role.get_name()].items(): if role_obj._uuid == original_task._role._uuid: role_obj._had_task_run[original_host.name] = True diff --git a/lib/ansible/plugins/strategy/linear.py b/lib/ansible/plugins/strategy/linear.py index 8b434983437..5b1a5f07521 100644 --- a/lib/ansible/plugins/strategy/linear.py +++ b/lib/ansible/plugins/strategy/linear.py @@ -34,7 +34,6 @@ DOCUMENTATION = ''' from ansible import constants as C from ansible.errors import AnsibleError, AnsibleAssertionError from ansible.executor.play_iterator import PlayIterator -from ansible.module_utils.six import iteritems from ansible.module_utils._text import to_text from ansible.playbook.block import Block from ansible.playbook.included_file import IncludedFile @@ -106,7 +105,7 @@ class StrategyModule(StrategyBase): display.debug("counting tasks in each state of execution") host_tasks_to_run = [(host, state_task) - for host, state_task in iteritems(host_tasks) + for host, state_task in host_tasks.items() if state_task and state_task[1]] if host_tasks_to_run: diff --git a/lib/ansible/plugins/terminal/__init__.py b/lib/ansible/plugins/terminal/__init__.py index bb3ad1812f6..537d3ec9677 100644 --- a/lib/ansible/plugins/terminal/__init__.py +++ b/lib/ansible/plugins/terminal/__init__.py @@ -21,13 +21,12 @@ __metaclass__ = type import re -from abc import ABCMeta, abstractmethod +from abc import ABC, abstractmethod from ansible.errors import AnsibleConnectionFailure -from ansible.module_utils.six import with_metaclass -class TerminalBase(with_metaclass(ABCMeta, object)): +class TerminalBase(ABC): ''' A base class for implementing cli connections diff --git a/lib/ansible/template/__init__.py b/lib/ansible/template/__init__.py index 027e636d52d..f8b46cb6fef 100644 --- a/lib/ansible/template/__init__.py +++ b/lib/ansible/template/__init__.py @@ -50,8 +50,7 @@ from ansible.errors import ( AnsiblePluginRemovedError, AnsibleUndefinedVariable, ) -from ansible.module_utils.six import iteritems, string_types, text_type -from ansible.module_utils.six.moves import range +from ansible.module_utils.six import string_types, text_type from ansible.module_utils._text import to_native, to_text, to_bytes from ansible.module_utils.common._collections_compat import Iterator, Sequence, Mapping, MappingView, MutableMapping from ansible.module_utils.common.collections import is_sequence @@ -562,7 +561,7 @@ class JinjaPluginIntercept(MutableMapping): method_map = getattr(plugin_impl, self._method_map_name) try: - func_items = iteritems(method_map()) + func_items = method_map().items() except Exception as e: display.warning( "Skipping %s plugin %s as it seems to be invalid: %r" % (self._dirname, to_text(plugin_impl._original_path), e), diff --git a/lib/ansible/template/safe_eval.py b/lib/ansible/template/safe_eval.py index b7389dcecf8..5510505b9ab 100644 --- a/lib/ansible/template/safe_eval.py +++ b/lib/ansible/template/safe_eval.py @@ -19,12 +19,10 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type import ast -import sys +import builtins -from ansible import constants as C -from ansible.module_utils.common.text.converters import container_to_text, to_native +from ansible.module_utils.common.text.converters import to_native from ansible.module_utils.six import string_types -from ansible.module_utils.six.moves import builtins def safe_eval(expr, locals=None, include_exceptions=False): diff --git a/lib/ansible/template/vars.py b/lib/ansible/template/vars.py index e9491b4d65b..9b3ed19ffe0 100644 --- a/lib/ansible/template/vars.py +++ b/lib/ansible/template/vars.py @@ -22,7 +22,6 @@ __metaclass__ = type from jinja2.utils import missing from ansible.errors import AnsibleError, AnsibleUndefinedVariable -from ansible.module_utils.six import iteritems from ansible.module_utils._text import to_native from ansible.module_utils.common._collections_compat import Mapping @@ -51,7 +50,7 @@ class AnsibleJ2Vars(Mapping): self._globals = globals self._locals = dict() if isinstance(locals, dict): - for key, val in iteritems(locals): + for key, val in locals.items(): if val is not missing: if key[:2] == 'l_': self._locals[key[2:]] = val diff --git a/lib/ansible/utils/cmd_functions.py b/lib/ansible/utils/cmd_functions.py index 7a0fb23e964..c35e2b35b0e 100644 --- a/lib/ansible/utils/cmd_functions.py +++ b/lib/ansible/utils/cmd_functions.py @@ -24,17 +24,10 @@ import shlex import subprocess import sys -from ansible.module_utils.six import PY2, PY3 from ansible.module_utils._text import to_bytes def run_cmd(cmd, live=False, readsize=10): - - # readsize = 10 - - # On python2, shlex needs byte strings - if PY2: - cmd = to_bytes(cmd, errors='surrogate_or_strict') cmdargs = shlex.split(cmd) # subprocess should be passed byte strings. (on python2.6 it must be @@ -52,11 +45,7 @@ def run_cmd(cmd, live=False, readsize=10): if p.stdout in rfd: dat = os.read(p.stdout.fileno(), readsize) if live: - # On python3, stdout has a codec to go from text type to bytes - if PY3: - sys.stdout.buffer.write(dat) - else: - sys.stdout.write(dat) + sys.stdout.buffer.write(dat) stdout += dat if dat == b'': rpipes.remove(p.stdout) @@ -64,11 +53,7 @@ def run_cmd(cmd, live=False, readsize=10): dat = os.read(p.stderr.fileno(), readsize) stderr += dat if live: - # On python3, stdout has a codec to go from text type to bytes - if PY3: - sys.stdout.buffer.write(dat) - else: - sys.stdout.write(dat) + sys.stdout.buffer.write(dat) if dat == b'': rpipes.remove(p.stderr) # only break out if we've emptied the pipes, or there is nothing to diff --git a/lib/ansible/utils/collection_loader/_collection_config.py b/lib/ansible/utils/collection_loader/_collection_config.py index a20319319ce..49de68b135e 100644 --- a/lib/ansible/utils/collection_loader/_collection_config.py +++ b/lib/ansible/utils/collection_loader/_collection_config.py @@ -13,7 +13,6 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type from ansible.module_utils.common.text.converters import to_text -from ansible.module_utils.six import with_metaclass class _EventSource: @@ -103,5 +102,5 @@ class _AnsibleCollectionConfig(type): # concrete class of our metaclass type that defines the class properties we want -class AnsibleCollectionConfig(with_metaclass(_AnsibleCollectionConfig)): +class AnsibleCollectionConfig(metaclass=_AnsibleCollectionConfig): pass diff --git a/lib/ansible/utils/display.py b/lib/ansible/utils/display.py index f670cc8b453..86237ef85a6 100644 --- a/lib/ansible/utils/display.py +++ b/lib/ansible/utils/display.py @@ -36,18 +36,12 @@ from termios import TIOCGWINSZ from ansible import constants as C from ansible.errors import AnsibleError, AnsibleAssertionError -from ansible.module_utils._text import to_bytes, to_text, to_native -from ansible.module_utils.six import with_metaclass, text_type +from ansible.module_utils._text import to_bytes, to_text +from ansible.module_utils.six import text_type from ansible.utils.color import stringc from ansible.utils.singleton import Singleton from ansible.utils.unsafe_proxy import wrap_var -try: - # Python 2 - input = raw_input -except NameError: - # Python 3, we already have raw_input - pass _LIBC = ctypes.cdll.LoadLibrary(ctypes.util.find_library('c')) # Set argtypes, to avoid segfault if the wrong type is provided, @@ -204,7 +198,7 @@ b_COW_PATHS = ( ) -class Display(with_metaclass(Singleton, object)): +class Display(metaclass=Singleton): def __init__(self, verbosity=0): diff --git a/lib/ansible/utils/jsonrpc.py b/lib/ansible/utils/jsonrpc.py index e48c979d4c5..4855324619d 100644 --- a/lib/ansible/utils/jsonrpc.py +++ b/lib/ansible/utils/jsonrpc.py @@ -5,12 +5,12 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type import json +import pickle import traceback from ansible.module_utils._text import to_text from ansible.module_utils.connection import ConnectionError from ansible.module_utils.six import binary_type, text_type -from ansible.module_utils.six.moves import cPickle from ansible.utils.display import Display display = Display() @@ -84,7 +84,7 @@ class JsonRpcServer(object): result = to_text(result) if not isinstance(result, text_type): response["result_type"] = "pickle" - result = to_text(cPickle.dumps(result, protocol=0)) + result = to_text(pickle.dumps(result, protocol=0)) response['result'] = result return response diff --git a/lib/ansible/utils/vars.py b/lib/ansible/utils/vars.py index 7545f1d4358..540dd3e9ec9 100644 --- a/lib/ansible/utils/vars.py +++ b/lib/ansible/utils/vars.py @@ -29,7 +29,7 @@ from json import dumps from ansible import constants as C from ansible import context from ansible.errors import AnsibleError, AnsibleOptionsError -from ansible.module_utils.six import iteritems, string_types, PY3 +from ansible.module_utils.six import string_types, PY3 from ansible.module_utils._text import to_native, to_text from ansible.module_utils.common._collections_compat import MutableMapping, MutableSequence from ansible.parsing.splitter import parse_kv @@ -129,7 +129,7 @@ def merge_hash(x, y, recursive=True, list_merge='replace'): # there is a high probability x will be the "default" dict the user # want to "patch" with y # therefore x will have much more elements than y - for key, y_value in iteritems(y): + for key, y_value in y.items(): # if `key` isn't in x # update x and move on to the next element of y if key not in x: diff --git a/lib/ansible/vars/manager.py b/lib/ansible/vars/manager.py index 5301c7f4969..376d216a635 100644 --- a/lib/ansible/vars/manager.py +++ b/lib/ansible/vars/manager.py @@ -37,7 +37,7 @@ from ansible.inventory.host import Host from ansible.inventory.helpers import sort_groups, get_group_vars from ansible.module_utils._text import to_text from ansible.module_utils.common._collections_compat import Mapping, MutableMapping, Sequence -from ansible.module_utils.six import iteritems, text_type, string_types +from ansible.module_utils.six import text_type, string_types from ansible.plugins.loader import lookup_loader from ansible.vars.fact_cache import FactCache from ansible.template import Templar @@ -513,7 +513,7 @@ class VariableManager: # the 'omit' value allows params to be left out if the variable they are based on is undefined variables['omit'] = self._omit_token # Set options vars - for option, option_value in iteritems(self._options_vars): + for option, option_value in self._options_vars.items(): variables[option] = option_value if self._hostvars is not None and include_hostvars: