mirror of
https://github.com/ansible-collections/community.general.git
synced 2026-05-06 13:22:48 +00:00
Move type checking methods out of basic.py and add unit tests (#53687)
* Move check_type_str() out of basic.py * Move check_type_list() out of basic.py * Move safe_eval() out of basic.py * Move check_type_dict() out of basic.py * Move json importing code to common location * Move check_type_bool() out of basic.py * Move _check_type_int() out of basic.py * Move _check_type_float() out of basic.py * Move _check_type_path() out of basic.py * Move _check_type_raw() out of basic.py * Move _check_type_bytes() out of basic.py * Move _check_type_bits() out of basic.py * Create text.formatters.py Move human_to_bytes, bytes_to_human, and _lenient_lowercase out of basic.py into text.formatters.py Change references in modules to point to function at new location * Move _check_type_jsonarg() out of basic.py * Rename json related functions and put them in common.text.converters Move formatters.py to common.text.formatters.py and update references in modules. * Rework check_type_str() Add allow_conversion option to make the function more self-contained. Move the messaging back to basic.py since those error messages are more relevant to using this function in the context of AnsibleModule and not when using the function in isolation. * Add unit tests for type checking functions * Change _lenient_lowercase to lenient_lowercase per feedback
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2019 Ansible Project
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
import pytest
|
||||
|
||||
from ansible.module_utils._text import to_native
|
||||
from ansible.module_utils.common.validation import check_type_bits
|
||||
|
||||
|
||||
def test_check_type_bits():
|
||||
test_cases = (
|
||||
('1', 1),
|
||||
(99, 99),
|
||||
(1.5, 2),
|
||||
('1.5', 2),
|
||||
('2b', 2),
|
||||
('2k', 2048),
|
||||
('2K', 2048),
|
||||
('1m', 1048576),
|
||||
('1M', 1048576),
|
||||
('1g', 1073741824),
|
||||
('1G', 1073741824),
|
||||
(1073741824, 1073741824),
|
||||
)
|
||||
for case in test_cases:
|
||||
assert case[1] == check_type_bits(case[0])
|
||||
|
||||
|
||||
def test_check_type_bits_fail():
|
||||
test_cases = (
|
||||
'foo',
|
||||
'2KB',
|
||||
'1MB',
|
||||
'1GB',
|
||||
)
|
||||
for case in test_cases:
|
||||
with pytest.raises(TypeError) as e:
|
||||
check_type_bits(case)
|
||||
assert 'cannot be converted to a Bit value' in to_native(e.value)
|
||||
@@ -0,0 +1,49 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2019 Ansible Project
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
import pytest
|
||||
|
||||
from ansible.module_utils._text import to_native
|
||||
from ansible.module_utils.common.validation import check_type_bool
|
||||
|
||||
|
||||
def test_check_type_bool():
|
||||
test_cases = (
|
||||
(True, True),
|
||||
(False, False),
|
||||
('1', True),
|
||||
('on', True),
|
||||
(1, True),
|
||||
('0', False),
|
||||
(0, False),
|
||||
('n', False),
|
||||
('f', False),
|
||||
('false', False),
|
||||
('true', True),
|
||||
('y', True),
|
||||
('t', True),
|
||||
('yes', True),
|
||||
('no', False),
|
||||
('off', False),
|
||||
)
|
||||
for case in test_cases:
|
||||
assert case[1] == check_type_bool(case[0])
|
||||
|
||||
|
||||
def test_check_type_bool_fail():
|
||||
default_test_msg = 'cannot be converted to a bool'
|
||||
test_cases = (
|
||||
({'k1': 'v1'}, 'is not a valid bool'),
|
||||
(3.14159, default_test_msg),
|
||||
(-1, default_test_msg),
|
||||
(-90810398401982340981023948192349081, default_test_msg),
|
||||
(90810398401982340981023948192349081, default_test_msg),
|
||||
)
|
||||
for case in test_cases:
|
||||
with pytest.raises(TypeError) as e:
|
||||
check_type_bool(case)
|
||||
assert 'cannot be converted to a bool' in to_native(e.value)
|
||||
@@ -0,0 +1,50 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2019 Ansible Project
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
import pytest
|
||||
|
||||
from ansible.module_utils._text import to_native
|
||||
from ansible.module_utils.common.validation import check_type_bytes
|
||||
|
||||
|
||||
def test_check_type_bytes():
|
||||
test_cases = (
|
||||
('1', 1),
|
||||
(99, 99),
|
||||
(1.5, 2),
|
||||
('1.5', 2),
|
||||
('2b', 2),
|
||||
('2B', 2),
|
||||
('2k', 2048),
|
||||
('2K', 2048),
|
||||
('2KB', 2048),
|
||||
('1m', 1048576),
|
||||
('1M', 1048576),
|
||||
('1MB', 1048576),
|
||||
('1g', 1073741824),
|
||||
('1G', 1073741824),
|
||||
('1GB', 1073741824),
|
||||
(1073741824, 1073741824),
|
||||
)
|
||||
for case in test_cases:
|
||||
assert case[1] == check_type_bytes(case[0])
|
||||
|
||||
|
||||
def test_check_type_bytes_fail():
|
||||
test_cases = (
|
||||
'foo',
|
||||
'2kb',
|
||||
'2Kb',
|
||||
'1mb',
|
||||
'1Mb',
|
||||
'1gb',
|
||||
'1Gb',
|
||||
)
|
||||
for case in test_cases:
|
||||
with pytest.raises(TypeError) as e:
|
||||
check_type_bytes(case)
|
||||
assert 'cannot be converted to a Byte value' in to_native(e.value)
|
||||
@@ -0,0 +1,34 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2019 Ansible Project
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
import pytest
|
||||
|
||||
from ansible.module_utils.common.validation import check_type_dict
|
||||
|
||||
|
||||
def test_check_type_dict():
|
||||
test_cases = (
|
||||
({'k1': 'v1'}, {'k1': 'v1'}),
|
||||
('k1=v1,k2=v2', {'k1': 'v1', 'k2': 'v2'}),
|
||||
('k1=v1, k2=v2', {'k1': 'v1', 'k2': 'v2'}),
|
||||
('k1=v1, k2=v2, k3=v3', {'k1': 'v1', 'k2': 'v2', 'k3': 'v3'}),
|
||||
('{"key": "value", "list": ["one", "two"]}', {'key': 'value', 'list': ['one', 'two']})
|
||||
)
|
||||
for case in test_cases:
|
||||
assert case[1] == check_type_dict(case[0])
|
||||
|
||||
|
||||
def test_check_type_dict_fail():
|
||||
test_cases = (
|
||||
1,
|
||||
3.14159,
|
||||
[1, 2],
|
||||
'a',
|
||||
)
|
||||
for case in test_cases:
|
||||
with pytest.raises(TypeError):
|
||||
check_type_dict(case)
|
||||
@@ -0,0 +1,38 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2019 Ansible Project
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
import pytest
|
||||
|
||||
from ansible.module_utils._text import to_native
|
||||
from ansible.module_utils.common.validation import check_type_float
|
||||
|
||||
|
||||
def test_check_type_float():
|
||||
test_cases = (
|
||||
('1.5', 1.5),
|
||||
('''1.5''', 1.5),
|
||||
(u'1.5', 1.5),
|
||||
(1002, 1002.0),
|
||||
(1.0, 1.0),
|
||||
(3.141592653589793, 3.141592653589793),
|
||||
('3.141592653589793', 3.141592653589793),
|
||||
(b'3.141592653589793', 3.141592653589793),
|
||||
)
|
||||
for case in test_cases:
|
||||
assert case[1] == check_type_float(case[0])
|
||||
|
||||
|
||||
def test_check_type_float_fail():
|
||||
test_cases = (
|
||||
{'k1': 'v1'},
|
||||
['a', 'b'],
|
||||
'b',
|
||||
)
|
||||
for case in test_cases:
|
||||
with pytest.raises(TypeError) as e:
|
||||
check_type_float(case)
|
||||
assert 'cannot be converted to a float' in to_native(e.value)
|
||||
@@ -0,0 +1,34 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2019 Ansible Project
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
import pytest
|
||||
|
||||
from ansible.module_utils._text import to_native
|
||||
from ansible.module_utils.common.validation import check_type_int
|
||||
|
||||
|
||||
def test_check_type_int():
|
||||
test_cases = (
|
||||
('1', 1),
|
||||
(u'1', 1),
|
||||
(1002, 1002),
|
||||
)
|
||||
for case in test_cases:
|
||||
assert case[1] == check_type_int(case[0])
|
||||
|
||||
|
||||
def test_check_type_int_fail():
|
||||
test_cases = (
|
||||
{'k1': 'v1'},
|
||||
(b'1', 1),
|
||||
(3.14159, 3),
|
||||
'b',
|
||||
)
|
||||
for case in test_cases:
|
||||
with pytest.raises(TypeError) as e:
|
||||
check_type_int(case)
|
||||
assert 'cannot be converted to an int' in to_native(e)
|
||||
@@ -0,0 +1,36 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2019 Ansible Project
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
import pytest
|
||||
|
||||
from ansible.module_utils._text import to_native
|
||||
from ansible.module_utils.common.validation import check_type_jsonarg
|
||||
|
||||
|
||||
def test_check_type_jsonarg():
|
||||
test_cases = (
|
||||
('a', 'a'),
|
||||
('a ', 'a'),
|
||||
(b'99', b'99'),
|
||||
(b'99 ', b'99'),
|
||||
({'k1': 'v1'}, '{"k1": "v1"}'),
|
||||
([1, 'a'], '[1, "a"]'),
|
||||
((1, 2, 'three'), '[1, 2, "three"]'),
|
||||
)
|
||||
for case in test_cases:
|
||||
assert case[1] == check_type_jsonarg(case[0])
|
||||
|
||||
|
||||
def test_check_type_jsonarg_fail():
|
||||
test_cases = (
|
||||
1.5,
|
||||
910313498012384012341982374109384098,
|
||||
)
|
||||
for case in test_cases:
|
||||
with pytest.raises(TypeError) as e:
|
||||
check_type_jsonarg(case)
|
||||
assert 'cannot be converted to a json string' in to_native(e.value)
|
||||
@@ -0,0 +1,32 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2019 Ansible Project
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
import pytest
|
||||
|
||||
from ansible.module_utils.common.validation import check_type_list
|
||||
|
||||
|
||||
def test_check_type_list():
|
||||
test_cases = (
|
||||
([1, 2], [1, 2]),
|
||||
(1, ['1']),
|
||||
(['a', 'b'], ['a', 'b']),
|
||||
('a', ['a']),
|
||||
(3.14159, ['3.14159']),
|
||||
('a,b,1,2', ['a', 'b', '1', '2'])
|
||||
)
|
||||
for case in test_cases:
|
||||
assert case[1] == check_type_list(case[0])
|
||||
|
||||
|
||||
def test_check_type_list_failure():
|
||||
test_cases = (
|
||||
{'k1': 'v1'},
|
||||
)
|
||||
for case in test_cases:
|
||||
with pytest.raises(TypeError):
|
||||
check_type_list(case)
|
||||
@@ -0,0 +1,28 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2019 Ansible Project
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
import re
|
||||
|
||||
import os
|
||||
from ansible.module_utils.common.validation import check_type_path
|
||||
|
||||
|
||||
def mock_expand(value):
|
||||
return re.sub(r'~|\$HOME', '/home/testuser', value)
|
||||
|
||||
|
||||
def test_check_type_path(monkeypatch):
|
||||
monkeypatch.setattr(os.path, 'expandvars', mock_expand)
|
||||
monkeypatch.setattr(os.path, 'expanduser', mock_expand)
|
||||
test_cases = (
|
||||
('~/foo', '/home/testuser/foo'),
|
||||
('$HOME/foo', '/home/testuser/foo'),
|
||||
('/home/jane', '/home/jane'),
|
||||
(u'/home/jané', u'/home/jané'),
|
||||
)
|
||||
for case in test_cases:
|
||||
assert case[1] == check_type_path(case[0])
|
||||
@@ -0,0 +1,23 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2019 Ansible Project
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
from ansible.module_utils.common.validation import check_type_raw
|
||||
|
||||
|
||||
def test_check_type_raw():
|
||||
test_cases = (
|
||||
(1, 1),
|
||||
('1', '1'),
|
||||
('a', 'a'),
|
||||
({'k1': 'v1'}, {'k1': 'v1'}),
|
||||
([1, 2], [1, 2]),
|
||||
(b'42', b'42'),
|
||||
(u'42', u'42'),
|
||||
)
|
||||
for case in test_cases:
|
||||
assert case[1] == check_type_raw(case[0])
|
||||
@@ -0,0 +1,33 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2019 Ansible Project
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
import pytest
|
||||
|
||||
from ansible.module_utils._text import to_native
|
||||
from ansible.module_utils.common.validation import check_type_str
|
||||
|
||||
|
||||
TEST_CASES = (
|
||||
('string', 'string'),
|
||||
(100, '100'),
|
||||
(1.5, '1.5'),
|
||||
({'k1': 'v1'}, "{'k1': 'v1'}"),
|
||||
([1, 2, 'three'], "[1, 2, 'three']"),
|
||||
((1, 2,), '(1, 2)'),
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('value, expected', TEST_CASES)
|
||||
def test_check_type_str(value, expected):
|
||||
assert expected == check_type_str(value)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('value, expected', TEST_CASES[1:])
|
||||
def test_check_type_str_no_conversion(value, expected):
|
||||
with pytest.raises(TypeError) as e:
|
||||
check_type_str(value, allow_conversion=False)
|
||||
assert 'is not a string and conversion is not allowed' in to_native(e.value)
|
||||
Reference in New Issue
Block a user