diff --git a/.azure-pipelines/azure-pipelines.yml b/.azure-pipelines/azure-pipelines.yml index dfc32f80e01..e7ad248f571 100644 --- a/.azure-pipelines/azure-pipelines.yml +++ b/.azure-pipelines/azure-pipelines.yml @@ -56,7 +56,6 @@ stages: testFormat: units/{0} targets: - test: 2.7 - - test: 3.5 - test: 3.6 - test: 3.7 - test: 3.8 diff --git a/changelogs/fragments/remove-python3.5.yml b/changelogs/fragments/remove-python3.5.yml new file mode 100644 index 00000000000..3367f4c1c1d --- /dev/null +++ b/changelogs/fragments/remove-python3.5.yml @@ -0,0 +1,2 @@ +removed_features: + - module_utils/basic.py - Removed Python 3.5 as a supported remote version. Python 2.7 or Python 3.6+ is now required. diff --git a/lib/ansible/config/base.yml b/lib/ansible/config/base.yml index 206deb76d2e..3aba53936e2 100644 --- a/lib/ansible/config/base.yml +++ b/lib/ansible/config/base.yml @@ -1563,7 +1563,6 @@ INTERPRETER_PYTHON_FALLBACK: - python3.8 - python3.7 - python3.6 - - python3.5 - /usr/bin/python3 - /usr/libexec/platform-python - python2.7 diff --git a/lib/ansible/executor/task_executor.py b/lib/ansible/executor/task_executor.py index f893eed7d56..bc08c6791ae 100644 --- a/lib/ansible/executor/task_executor.py +++ b/lib/ansible/executor/task_executor.py @@ -1249,8 +1249,7 @@ def start_connection(play_context, options, task_uuid): else: try: result = json.loads(to_text(stderr, errors='surrogate_then_replace')) - except getattr(json.decoder, 'JSONDecodeError', ValueError): - # JSONDecodeError only available on Python 3.5+ + except json.decoder.JSONDecodeError: result = {'error': to_text(stderr, errors='surrogate_then_replace')} if 'messages' in result: diff --git a/lib/ansible/module_utils/basic.py b/lib/ansible/module_utils/basic.py index 7cb22c66563..190e84099c1 100644 --- a/lib/ansible/module_utils/basic.py +++ b/lib/ansible/module_utils/basic.py @@ -9,14 +9,14 @@ import sys # Used for determining if the system is running a new enough python version # and should only restrict on our documented minimum versions -_PY3_MIN = sys.version_info >= (3, 5) +_PY3_MIN = sys.version_info >= (3, 6) _PY2_MIN = (2, 7) <= sys.version_info < (3,) _PY_MIN = _PY3_MIN or _PY2_MIN if not _PY_MIN: print( '\n{"failed": true, ' - '"msg": "ansible-core requires a minimum of Python2 version 2.7 or Python3 version 3.5. Current version: %s"}' % ''.join(sys.version.splitlines()) + '"msg": "ansible-core requires a minimum of Python2 version 2.7 or Python3 version 3.6. Current version: %s"}' % ''.join(sys.version.splitlines()) ) sys.exit(1) @@ -1715,14 +1715,6 @@ class AnsibleModule(object): tmp_dest_fd, tmp_dest_name = tempfile.mkstemp(prefix=b'.ansible_tmp', dir=b_dest_dir, suffix=b_suffix) except (OSError, IOError) as e: error_msg = 'The destination directory (%s) is not writable by the current user. Error was: %s' % (os.path.dirname(dest), to_native(e)) - except TypeError: - # We expect that this is happening because python3.4.x and - # below can't handle byte strings in mkstemp(). - # Traceback would end in something like: - # file = _os.path.join(dir, pre + name + suf) - # TypeError: can't concat bytes to str - error_msg = ('Failed creating tmp file for atomic move. This usually happens when using Python3 less than Python3.5. ' - 'Please use Python2.x or Python3.5 or greater.') finally: if error_msg: if unsafe_writes: diff --git a/lib/ansible/modules/pip.py b/lib/ansible/modules/pip.py index b1ad0ec4afe..eebda238ec6 100644 --- a/lib/ansible/modules/pip.py +++ b/lib/ansible/modules/pip.py @@ -61,7 +61,7 @@ options: virtualenv_python: description: - The Python executable used for creating the virtual environment. - For example C(python3.5), C(python2.7). When not specified, the + For example C(python3.12), C(python2.7). When not specified, the Python version used to run the ansible module is used. This parameter should not be used when C(virtualenv_command) is using C(pyvenv) or the C(-m venv) module. diff --git a/test/lib/ansible_test/_data/completion/docker.txt b/test/lib/ansible_test/_data/completion/docker.txt index 223d45bc30b..96ceb9049ff 100644 --- a/test/lib/ansible_test/_data/completion/docker.txt +++ b/test/lib/ansible_test/_data/completion/docker.txt @@ -1,6 +1,6 @@ -base image=quay.io/ansible/base-test-container:4.1.0 python=3.11,2.7,3.5,3.6,3.7,3.8,3.9,3.10 -default image=quay.io/ansible/default-test-container:8.2.0 python=3.11,2.7,3.5,3.6,3.7,3.8,3.9,3.10 context=collection -default image=quay.io/ansible/ansible-core-test-container:8.2.0 python=3.11,2.7,3.5,3.6,3.7,3.8,3.9,3.10 context=ansible-core +base image=quay.io/ansible/base-test-container:4.1.0 python=3.11,2.7,3.6,3.7,3.8,3.9,3.10 +default image=quay.io/ansible/default-test-container:8.2.0 python=3.11,2.7,3.6,3.7,3.8,3.9,3.10 context=collection +default image=quay.io/ansible/ansible-core-test-container:8.2.0 python=3.11,2.7,3.6,3.7,3.8,3.9,3.10 context=ansible-core alpine3 image=quay.io/ansible/alpine3-test-container:5.0.0 python=3.10 cgroup=none audit=none centos7 image=quay.io/ansible/centos7-test-container:5.0.0 python=2.7 cgroup=v1-only fedora37 image=quay.io/ansible/fedora37-test-container:5.0.0 python=3.11 diff --git a/test/lib/ansible_test/_internal/python_requirements.py b/test/lib/ansible_test/_internal/python_requirements.py index b44bae8b2de..44765f43868 100644 --- a/test/lib/ansible_test/_internal/python_requirements.py +++ b/test/lib/ansible_test/_internal/python_requirements.py @@ -445,11 +445,6 @@ def get_venv_packages(python: PythonConfig) -> dict[str, str]: setuptools='44.1.1', # 45.0.0 requires Python 3.5+ wheel=None, ), - '3.5': dict( - pip='20.3.4', # 21.0 requires Python 3.6+ - setuptools='50.3.2', # 51.0.0 requires Python 3.6+ - wheel=None, - ), '3.6': dict( pip='21.3.1', # 22.0 requires Python 3.7+ setuptools='59.6.0', # 59.7.0 requires Python 3.7+ diff --git a/test/lib/ansible_test/_util/target/common/constants.py b/test/lib/ansible_test/_util/target/common/constants.py index 9bddfaf4395..812b919c6bc 100644 --- a/test/lib/ansible_test/_util/target/common/constants.py +++ b/test/lib/ansible_test/_util/target/common/constants.py @@ -7,7 +7,6 @@ __metaclass__ = type REMOTE_ONLY_PYTHON_VERSIONS = ( '2.7', - '3.5', '3.6', '3.7', '3.8', diff --git a/test/lib/ansible_test/_util/target/sanity/import/importer.py b/test/lib/ansible_test/_util/target/sanity/import/importer.py index 44a5ddc9ec5..7919fa0d7d1 100644 --- a/test/lib/ansible_test/_util/target/sanity/import/importer.py +++ b/test/lib/ansible_test/_util/target/sanity/import/importer.py @@ -552,14 +552,6 @@ def main(): "Python 2 is no longer supported by the Python core team. Support for it is now deprecated in cryptography," " and will be removed in the next release.") - if sys.version_info[:2] == (3, 5): - warnings.filterwarnings( - "ignore", - "Python 3.5 support will be dropped in the next release ofcryptography. Please upgrade your Python.") - warnings.filterwarnings( - "ignore", - "Python 3.5 support will be dropped in the next release of cryptography. Please upgrade your Python.") - try: yield finally: diff --git a/test/lib/ansible_test/_util/target/setup/quiet_pip.py b/test/lib/ansible_test/_util/target/setup/quiet_pip.py index 54f0f860906..171ff8f3e24 100644 --- a/test/lib/ansible_test/_util/target/setup/quiet_pip.py +++ b/test/lib/ansible_test/_util/target/setup/quiet_pip.py @@ -27,10 +27,6 @@ WARNING_MESSAGE_FILTERS = ( # pip 21.0 will drop support for Python 2.7 in January 2021. # More details about Python 2 support in pip, can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support 'DEPRECATION: Python 2.7 reached the end of its life ', - - # DEPRECATION: Python 3.5 reached the end of its life on September 13th, 2020. Please upgrade your Python as Python 3.5 is no longer maintained. - # pip 21.0 will drop support for Python 3.5 in January 2021. pip 21.0 will remove support for this functionality. - 'DEPRECATION: Python 3.5 reached the end of its life ', ) diff --git a/test/sanity/ignore.txt b/test/sanity/ignore.txt index dc646dd4a53..923e45723ce 100644 --- a/test/sanity/ignore.txt +++ b/test/sanity/ignore.txt @@ -58,7 +58,6 @@ lib/ansible/module_utils/basic.py pylint:unused-import # deferring resolution t lib/ansible/module_utils/compat/_selectors2.py future-import-boilerplate # ignore bundled lib/ansible/module_utils/compat/_selectors2.py metaclass-boilerplate # ignore bundled lib/ansible/module_utils/compat/selinux.py import-2.7!skip # pass/fail depends on presence of libselinux.so -lib/ansible/module_utils/compat/selinux.py import-3.5!skip # pass/fail depends on presence of libselinux.so lib/ansible/module_utils/compat/selinux.py import-3.6!skip # pass/fail depends on presence of libselinux.so lib/ansible/module_utils/compat/selinux.py import-3.7!skip # pass/fail depends on presence of libselinux.so lib/ansible/module_utils/compat/selinux.py import-3.8!skip # pass/fail depends on presence of libselinux.so diff --git a/test/units/executor/test_interpreter_discovery.py b/test/units/executor/test_interpreter_discovery.py index d98e729bf85..10fc64be752 100644 --- a/test/units/executor/test_interpreter_discovery.py +++ b/test/units/executor/test_interpreter_discovery.py @@ -20,7 +20,7 @@ mock_ubuntu_platform_res = to_text( def test_discovery_interpreter_linux_auto_legacy(): - res1 = u'PLATFORM\nLinux\nFOUND\n/usr/bin/python\n/usr/bin/python3.5\n/usr/bin/python3\nENDFOUND' + res1 = u'PLATFORM\nLinux\nFOUND\n/usr/bin/python\n/usr/bin/python3\nENDFOUND' mock_action = MagicMock() mock_action._low_level_execute_command.side_effect = [{'stdout': res1}, {'stdout': mock_ubuntu_platform_res}] @@ -35,7 +35,7 @@ def test_discovery_interpreter_linux_auto_legacy(): def test_discovery_interpreter_linux_auto_legacy_silent(): - res1 = u'PLATFORM\nLinux\nFOUND\n/usr/bin/python\n/usr/bin/python3.5\n/usr/bin/python3\nENDFOUND' + res1 = u'PLATFORM\nLinux\nFOUND\n/usr/bin/python\n/usr/bin/python3\nENDFOUND' mock_action = MagicMock() mock_action._low_level_execute_command.side_effect = [{'stdout': res1}, {'stdout': mock_ubuntu_platform_res}] @@ -47,7 +47,7 @@ def test_discovery_interpreter_linux_auto_legacy_silent(): def test_discovery_interpreter_linux_auto(): - res1 = u'PLATFORM\nLinux\nFOUND\n/usr/bin/python\n/usr/bin/python3.5\n/usr/bin/python3\nENDFOUND' + res1 = u'PLATFORM\nLinux\nFOUND\n/usr/bin/python\n/usr/bin/python3\nENDFOUND' mock_action = MagicMock() mock_action._low_level_execute_command.side_effect = [{'stdout': res1}, {'stdout': mock_ubuntu_platform_res}]