Deprecate Py2.6 support for target nodes (#74165)
This commit is contained in:
parent
07939b04f3
commit
17237c1d88
9 changed files with 58 additions and 20 deletions
4
changelogs/fragments/212-py26-deprecation.yml
Normal file
4
changelogs/fragments/212-py26-deprecation.yml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
minor_changes:
|
||||||
|
- Python 2.6 Target Support - Deprecate Python 2.6 for targets, requiring Python 2.7 or newer.
|
||||||
|
``ansible-core==2.13`` will drop support for Python 2.6.
|
||||||
|
(https://github.com/ansible/ansible/pull/74165)
|
|
@ -31,6 +31,7 @@ No notable changes
|
||||||
Deprecated
|
Deprecated
|
||||||
==========
|
==========
|
||||||
|
|
||||||
|
* Python 2.6 on the target node is deprecated in this release. ``ansible-core`` 2.13 will remove support for Python 2.6.
|
||||||
* Bare variables in conditionals: ``when`` conditionals no longer automatically parse string booleans such as ``"true"`` and ``"false"`` into actual booleans. Any variable containing a non-empty string is considered true. This was previously configurable with the ``CONDITIONAL_BARE_VARS`` configuration option (and the ``ANSIBLE_CONDITIONAL_BARE_VARS`` environment variable). This setting no longer has any effect. Users can work around the issue by using the ``|bool`` filter:
|
* Bare variables in conditionals: ``when`` conditionals no longer automatically parse string booleans such as ``"true"`` and ``"false"`` into actual booleans. Any variable containing a non-empty string is considered true. This was previously configurable with the ``CONDITIONAL_BARE_VARS`` configuration option (and the ``ANSIBLE_CONDITIONAL_BARE_VARS`` environment variable). This setting no longer has any effect. Users can work around the issue by using the ``|bool`` filter:
|
||||||
|
|
||||||
.. code-block:: yaml
|
.. code-block:: yaml
|
||||||
|
|
|
@ -249,14 +249,22 @@ PERMS_RE = re.compile(r'[^rwxXstugo]')
|
||||||
# and should only restrict on our documented minimum versions
|
# and should only restrict on our documented minimum versions
|
||||||
_PY3_MIN = sys.version_info[:2] >= (3, 5)
|
_PY3_MIN = sys.version_info[:2] >= (3, 5)
|
||||||
_PY2_MIN = (2, 6) <= sys.version_info[:2] < (3,)
|
_PY2_MIN = (2, 6) <= sys.version_info[:2] < (3,)
|
||||||
|
_PY26 = (2, 6) == sys.version_info[:2]
|
||||||
_PY_MIN = _PY3_MIN or _PY2_MIN
|
_PY_MIN = _PY3_MIN or _PY2_MIN
|
||||||
if not _PY_MIN:
|
if not _PY_MIN:
|
||||||
print(
|
print(
|
||||||
'\n{"failed": true, '
|
'\n{"failed": true, '
|
||||||
'"msg": "Ansible requires a minimum of Python2 version 2.6 or Python3 version 3.5. Current version: %s"}' % ''.join(sys.version.splitlines())
|
'"msg": "ansible-core requires a minimum of Python2 version 2.6 or Python3 version 3.5. Current version: %s"}' % ''.join(sys.version.splitlines())
|
||||||
)
|
)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
if _PY26:
|
||||||
|
deprecate(
|
||||||
|
'ansible-core 2.13 will require Python 2.7 or newer on the target. '
|
||||||
|
'Current version: %s' % ''.join(sys.version.splitlines()),
|
||||||
|
version='2.13',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Deprecated functions
|
# Deprecated functions
|
||||||
|
|
|
@ -57,8 +57,8 @@
|
||||||
- name: Assert that the deprecation message is given correctly
|
- name: Assert that the deprecation message is given correctly
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- result.deprecations[0].msg == "Alias 'baz' is deprecated. See the module docs for more information"
|
- result.deprecations[-1].msg == "Alias 'baz' is deprecated. See the module docs for more information"
|
||||||
- result.deprecations[0].version == '9.99'
|
- result.deprecations[-1].version == '9.99'
|
||||||
|
|
||||||
- block:
|
- block:
|
||||||
- name: Get a string with a \0 in it
|
- name: Get a string with a \0 in it
|
||||||
|
|
|
@ -15,6 +15,7 @@ import pytest
|
||||||
from units.compat.mock import MagicMock
|
from units.compat.mock import MagicMock
|
||||||
from ansible.module_utils import basic
|
from ansible.module_utils import basic
|
||||||
from ansible.module_utils.api import basic_auth_argument_spec, rate_limit_argument_spec, retry_argument_spec
|
from ansible.module_utils.api import basic_auth_argument_spec, rate_limit_argument_spec, retry_argument_spec
|
||||||
|
from ansible.module_utils.common import warnings
|
||||||
from ansible.module_utils.common.warnings import get_deprecation_messages, get_warning_messages
|
from ansible.module_utils.common.warnings import get_deprecation_messages, get_warning_messages
|
||||||
from ansible.module_utils.six import integer_types, string_types
|
from ansible.module_utils.six import integer_types, string_types
|
||||||
from ansible.module_utils.six.moves import builtins
|
from ansible.module_utils.six.moves import builtins
|
||||||
|
@ -400,8 +401,10 @@ class TestComplexArgSpecs:
|
||||||
assert am.params['bar3'][1] == 'test/'
|
assert am.params['bar3'][1] == 'test/'
|
||||||
|
|
||||||
@pytest.mark.parametrize('stdin', [{'foo': 'hello', 'zodraz': 'one'}], indirect=['stdin'])
|
@pytest.mark.parametrize('stdin', [{'foo': 'hello', 'zodraz': 'one'}], indirect=['stdin'])
|
||||||
def test_deprecated_alias(self, capfd, mocker, stdin, complex_argspec):
|
def test_deprecated_alias(self, capfd, mocker, stdin, complex_argspec, monkeypatch):
|
||||||
"""Test a deprecated alias"""
|
"""Test a deprecated alias"""
|
||||||
|
monkeypatch.setattr(warnings, '_global_deprecations', [])
|
||||||
|
|
||||||
am = basic.AnsibleModule(**complex_argspec)
|
am = basic.AnsibleModule(**complex_argspec)
|
||||||
|
|
||||||
assert "Alias 'zodraz' is deprecated." in get_deprecation_messages()[0]['msg']
|
assert "Alias 'zodraz' is deprecated." in get_deprecation_messages()[0]['msg']
|
||||||
|
|
|
@ -10,6 +10,8 @@ import json
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
from ansible.module_utils.common import warnings
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('stdin', [{}], indirect=['stdin'])
|
@pytest.mark.parametrize('stdin', [{}], indirect=['stdin'])
|
||||||
def test_warn(am, capfd):
|
def test_warn(am, capfd):
|
||||||
|
@ -23,7 +25,9 @@ def test_warn(am, capfd):
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('stdin', [{}], indirect=['stdin'])
|
@pytest.mark.parametrize('stdin', [{}], indirect=['stdin'])
|
||||||
def test_deprecate(am, capfd):
|
def test_deprecate(am, capfd, monkeypatch):
|
||||||
|
monkeypatch.setattr(warnings, '_global_deprecations', [])
|
||||||
|
|
||||||
am.deprecate('deprecation1')
|
am.deprecate('deprecation1')
|
||||||
am.deprecate('deprecation2', '2.3') # pylint: disable=ansible-deprecated-no-collection-name
|
am.deprecate('deprecation2', '2.3') # pylint: disable=ansible-deprecated-no-collection-name
|
||||||
am.deprecate('deprecation3', version='2.4') # pylint: disable=ansible-deprecated-no-collection-name
|
am.deprecate('deprecation3', version='2.4') # pylint: disable=ansible-deprecated-no-collection-name
|
||||||
|
|
|
@ -12,6 +12,7 @@ import datetime
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
from ansible.module_utils.common import warnings
|
||||||
|
|
||||||
EMPTY_INVOCATION = {u'module_args': {}}
|
EMPTY_INVOCATION = {u'module_args': {}}
|
||||||
DATETIME = datetime.datetime.strptime('2020-07-13 12:50:00', '%Y-%m-%d %H:%M:%S')
|
DATETIME = datetime.datetime.strptime('2020-07-13 12:50:00', '%Y-%m-%d %H:%M:%S')
|
||||||
|
@ -37,7 +38,9 @@ class TestAnsibleModuleExitJson:
|
||||||
# pylint bug: https://github.com/PyCQA/pylint/issues/511
|
# pylint bug: https://github.com/PyCQA/pylint/issues/511
|
||||||
# pylint: disable=undefined-variable
|
# pylint: disable=undefined-variable
|
||||||
@pytest.mark.parametrize('args, expected, stdin', ((a, e, {}) for a, e in DATA), indirect=['stdin'])
|
@pytest.mark.parametrize('args, expected, stdin', ((a, e, {}) for a, e in DATA), indirect=['stdin'])
|
||||||
def test_exit_json_exits(self, am, capfd, args, expected):
|
def test_exit_json_exits(self, am, capfd, args, expected, monkeypatch):
|
||||||
|
monkeypatch.setattr(warnings, '_global_deprecations', [])
|
||||||
|
|
||||||
with pytest.raises(SystemExit) as ctx:
|
with pytest.raises(SystemExit) as ctx:
|
||||||
am.exit_json(**args)
|
am.exit_json(**args)
|
||||||
assert ctx.value.code == 0
|
assert ctx.value.code == 0
|
||||||
|
@ -51,7 +54,9 @@ class TestAnsibleModuleExitJson:
|
||||||
@pytest.mark.parametrize('args, expected, stdin',
|
@pytest.mark.parametrize('args, expected, stdin',
|
||||||
((a, e, {}) for a, e in DATA if 'msg' in a), # pylint: disable=undefined-variable
|
((a, e, {}) for a, e in DATA if 'msg' in a), # pylint: disable=undefined-variable
|
||||||
indirect=['stdin'])
|
indirect=['stdin'])
|
||||||
def test_fail_json_exits(self, am, capfd, args, expected):
|
def test_fail_json_exits(self, am, capfd, args, expected, monkeypatch):
|
||||||
|
monkeypatch.setattr(warnings, '_global_deprecations', [])
|
||||||
|
|
||||||
with pytest.raises(SystemExit) as ctx:
|
with pytest.raises(SystemExit) as ctx:
|
||||||
am.fail_json(**args)
|
am.fail_json(**args)
|
||||||
assert ctx.value.code == 1
|
assert ctx.value.code == 1
|
||||||
|
@ -63,7 +68,9 @@ class TestAnsibleModuleExitJson:
|
||||||
assert return_val == expected
|
assert return_val == expected
|
||||||
|
|
||||||
@pytest.mark.parametrize('stdin', [{}], indirect=['stdin'])
|
@pytest.mark.parametrize('stdin', [{}], indirect=['stdin'])
|
||||||
def test_fail_json_msg_positional(self, am, capfd):
|
def test_fail_json_msg_positional(self, am, capfd, monkeypatch):
|
||||||
|
monkeypatch.setattr(warnings, '_global_deprecations', [])
|
||||||
|
|
||||||
with pytest.raises(SystemExit) as ctx:
|
with pytest.raises(SystemExit) as ctx:
|
||||||
am.fail_json('This is the msg')
|
am.fail_json('This is the msg')
|
||||||
assert ctx.value.code == 1
|
assert ctx.value.code == 1
|
||||||
|
@ -75,8 +82,10 @@ class TestAnsibleModuleExitJson:
|
||||||
'invocation': EMPTY_INVOCATION}
|
'invocation': EMPTY_INVOCATION}
|
||||||
|
|
||||||
@pytest.mark.parametrize('stdin', [{}], indirect=['stdin'])
|
@pytest.mark.parametrize('stdin', [{}], indirect=['stdin'])
|
||||||
def test_fail_json_msg_as_kwarg_after(self, am, capfd):
|
def test_fail_json_msg_as_kwarg_after(self, am, capfd, monkeypatch):
|
||||||
"""Test that msg as a kwarg after other kwargs works"""
|
"""Test that msg as a kwarg after other kwargs works"""
|
||||||
|
monkeypatch.setattr(warnings, '_global_deprecations', [])
|
||||||
|
|
||||||
with pytest.raises(SystemExit) as ctx:
|
with pytest.raises(SystemExit) as ctx:
|
||||||
am.fail_json(arbitrary=42, msg='This is the msg')
|
am.fail_json(arbitrary=42, msg='This is the msg')
|
||||||
assert ctx.value.code == 1
|
assert ctx.value.code == 1
|
||||||
|
@ -139,7 +148,8 @@ class TestAnsibleModuleExitValuesRemoved:
|
||||||
(({'username': {}, 'password': {'no_log': True}, 'token': {'no_log': True}}, s, r, e)
|
(({'username': {}, 'password': {'no_log': True}, 'token': {'no_log': True}}, s, r, e)
|
||||||
for s, r, e in DATA), # pylint: disable=undefined-variable
|
for s, r, e in DATA), # pylint: disable=undefined-variable
|
||||||
indirect=['am', 'stdin'])
|
indirect=['am', 'stdin'])
|
||||||
def test_exit_json_removes_values(self, am, capfd, return_val, expected):
|
def test_exit_json_removes_values(self, am, capfd, return_val, expected, monkeypatch):
|
||||||
|
monkeypatch.setattr(warnings, '_global_deprecations', [])
|
||||||
with pytest.raises(SystemExit):
|
with pytest.raises(SystemExit):
|
||||||
am.exit_json(**return_val)
|
am.exit_json(**return_val)
|
||||||
out, err = capfd.readouterr()
|
out, err = capfd.readouterr()
|
||||||
|
@ -151,7 +161,8 @@ class TestAnsibleModuleExitValuesRemoved:
|
||||||
(({'username': {}, 'password': {'no_log': True}, 'token': {'no_log': True}}, s, r, e)
|
(({'username': {}, 'password': {'no_log': True}, 'token': {'no_log': True}}, s, r, e)
|
||||||
for s, r, e in DATA), # pylint: disable=undefined-variable
|
for s, r, e in DATA), # pylint: disable=undefined-variable
|
||||||
indirect=['am', 'stdin'])
|
indirect=['am', 'stdin'])
|
||||||
def test_fail_json_removes_values(self, am, capfd, return_val, expected):
|
def test_fail_json_removes_values(self, am, capfd, return_val, expected, monkeypatch):
|
||||||
|
monkeypatch.setattr(warnings, '_global_deprecations', [])
|
||||||
expected['failed'] = True
|
expected['failed'] = True
|
||||||
with pytest.raises(SystemExit):
|
with pytest.raises(SystemExit):
|
||||||
am.fail_json(**return_val) == expected
|
am.fail_json(**return_val) == expected
|
||||||
|
|
|
@ -25,7 +25,9 @@ def test_module_validate():
|
||||||
assert result.validated_parameters == expected
|
assert result.validated_parameters == expected
|
||||||
|
|
||||||
|
|
||||||
def test_module_alias_deprecations_warnings():
|
def test_module_alias_deprecations_warnings(monkeypatch):
|
||||||
|
monkeypatch.setattr(warnings, '_global_deprecations', [])
|
||||||
|
|
||||||
arg_spec = {
|
arg_spec = {
|
||||||
'path': {
|
'path': {
|
||||||
'aliases': ['source', 'src', 'flamethrower'],
|
'aliases': ['source', 'src', 'flamethrower'],
|
||||||
|
|
|
@ -26,50 +26,55 @@ def deprecation_messages():
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def test_deprecate_message_only():
|
@pytest.fixture
|
||||||
|
def reset(monkeypatch):
|
||||||
|
monkeypatch.setattr(warnings, '_global_deprecations', [])
|
||||||
|
|
||||||
|
|
||||||
|
def test_deprecate_message_only(reset):
|
||||||
deprecate('Deprecation message')
|
deprecate('Deprecation message')
|
||||||
assert warnings._global_deprecations == [
|
assert warnings._global_deprecations == [
|
||||||
{'msg': 'Deprecation message', 'version': None, 'collection_name': None}]
|
{'msg': 'Deprecation message', 'version': None, 'collection_name': None}]
|
||||||
|
|
||||||
|
|
||||||
def test_deprecate_with_collection():
|
def test_deprecate_with_collection(reset):
|
||||||
deprecate(msg='Deprecation message', collection_name='ansible.builtin')
|
deprecate(msg='Deprecation message', collection_name='ansible.builtin')
|
||||||
assert warnings._global_deprecations == [
|
assert warnings._global_deprecations == [
|
||||||
{'msg': 'Deprecation message', 'version': None, 'collection_name': 'ansible.builtin'}]
|
{'msg': 'Deprecation message', 'version': None, 'collection_name': 'ansible.builtin'}]
|
||||||
|
|
||||||
|
|
||||||
def test_deprecate_with_version():
|
def test_deprecate_with_version(reset):
|
||||||
deprecate(msg='Deprecation message', version='2.14')
|
deprecate(msg='Deprecation message', version='2.14')
|
||||||
assert warnings._global_deprecations == [
|
assert warnings._global_deprecations == [
|
||||||
{'msg': 'Deprecation message', 'version': '2.14', 'collection_name': None}]
|
{'msg': 'Deprecation message', 'version': '2.14', 'collection_name': None}]
|
||||||
|
|
||||||
|
|
||||||
def test_deprecate_with_version_and_collection():
|
def test_deprecate_with_version_and_collection(reset):
|
||||||
deprecate(msg='Deprecation message', version='2.14', collection_name='ansible.builtin')
|
deprecate(msg='Deprecation message', version='2.14', collection_name='ansible.builtin')
|
||||||
assert warnings._global_deprecations == [
|
assert warnings._global_deprecations == [
|
||||||
{'msg': 'Deprecation message', 'version': '2.14', 'collection_name': 'ansible.builtin'}]
|
{'msg': 'Deprecation message', 'version': '2.14', 'collection_name': 'ansible.builtin'}]
|
||||||
|
|
||||||
|
|
||||||
def test_deprecate_with_date():
|
def test_deprecate_with_date(reset):
|
||||||
deprecate(msg='Deprecation message', date='2199-12-31')
|
deprecate(msg='Deprecation message', date='2199-12-31')
|
||||||
assert warnings._global_deprecations == [
|
assert warnings._global_deprecations == [
|
||||||
{'msg': 'Deprecation message', 'date': '2199-12-31', 'collection_name': None}]
|
{'msg': 'Deprecation message', 'date': '2199-12-31', 'collection_name': None}]
|
||||||
|
|
||||||
|
|
||||||
def test_deprecate_with_date_and_collection():
|
def test_deprecate_with_date_and_collection(reset):
|
||||||
deprecate(msg='Deprecation message', date='2199-12-31', collection_name='ansible.builtin')
|
deprecate(msg='Deprecation message', date='2199-12-31', collection_name='ansible.builtin')
|
||||||
assert warnings._global_deprecations == [
|
assert warnings._global_deprecations == [
|
||||||
{'msg': 'Deprecation message', 'date': '2199-12-31', 'collection_name': 'ansible.builtin'}]
|
{'msg': 'Deprecation message', 'date': '2199-12-31', 'collection_name': 'ansible.builtin'}]
|
||||||
|
|
||||||
|
|
||||||
def test_multiple_deprecations(deprecation_messages):
|
def test_multiple_deprecations(deprecation_messages, reset):
|
||||||
for d in deprecation_messages:
|
for d in deprecation_messages:
|
||||||
deprecate(**d)
|
deprecate(**d)
|
||||||
|
|
||||||
assert deprecation_messages == warnings._global_deprecations
|
assert deprecation_messages == warnings._global_deprecations
|
||||||
|
|
||||||
|
|
||||||
def test_get_deprecation_messages(deprecation_messages):
|
def test_get_deprecation_messages(deprecation_messages, reset):
|
||||||
for d in deprecation_messages:
|
for d in deprecation_messages:
|
||||||
deprecate(**d)
|
deprecate(**d)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue