mirror of https://github.com/ansible/ansible.git
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 feedbackpull/54816/head
parent
bb61d7527f
commit
ff88bd82b5
@ -0,0 +1,16 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (c) 2019 Ansible Project
|
||||||
|
# Simplified BSD License (see licenses/simplified_bsd.txt or https://opensource.org/licenses/BSD-2-Clause)
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
import types
|
||||||
|
import json
|
||||||
|
|
||||||
|
# Detect the python-json library which is incompatible
|
||||||
|
try:
|
||||||
|
if not isinstance(json.loads, types.FunctionType) or not isinstance(json.dumps, types.FunctionType):
|
||||||
|
raise ImportError('json.loads or json.dumps were not found in the imported json library.')
|
||||||
|
except AttributeError:
|
||||||
|
raise ImportError('python-json was detected, which is incompatible.')
|
||||||
@ -0,0 +1,83 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (c) 2019 Ansible Project
|
||||||
|
# Simplified BSD License (see licenses/simplified_bsd.txt or https://opensource.org/licenses/BSD-2-Clause)
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
import json
|
||||||
|
|
||||||
|
from itertools import repeat
|
||||||
|
|
||||||
|
from ansible.module_utils._text import to_bytes, to_native, to_text
|
||||||
|
from ansible.module_utils.common._collections_compat import Set
|
||||||
|
from ansible.module_utils.six import (
|
||||||
|
binary_type,
|
||||||
|
iteritems,
|
||||||
|
text_type,
|
||||||
|
)
|
||||||
|
from ansible.module_utils.six.moves import map
|
||||||
|
|
||||||
|
|
||||||
|
def _json_encode_fallback(obj):
|
||||||
|
if isinstance(obj, Set):
|
||||||
|
return list(obj)
|
||||||
|
elif isinstance(obj, datetime.datetime):
|
||||||
|
return obj.isoformat()
|
||||||
|
raise TypeError("Cannot json serialize %s" % to_native(obj))
|
||||||
|
|
||||||
|
|
||||||
|
def jsonify(data, **kwargs):
|
||||||
|
for encoding in ("utf-8", "latin-1"):
|
||||||
|
try:
|
||||||
|
return json.dumps(data, encoding=encoding, default=_json_encode_fallback, **kwargs)
|
||||||
|
# Old systems using old simplejson module does not support encoding keyword.
|
||||||
|
except TypeError:
|
||||||
|
try:
|
||||||
|
new_data = container_to_text(data, encoding=encoding)
|
||||||
|
except UnicodeDecodeError:
|
||||||
|
continue
|
||||||
|
return json.dumps(new_data, default=_json_encode_fallback, **kwargs)
|
||||||
|
except UnicodeDecodeError:
|
||||||
|
continue
|
||||||
|
raise UnicodeError('Invalid unicode encoding encountered')
|
||||||
|
|
||||||
|
|
||||||
|
def container_to_bytes(d, encoding='utf-8', errors='surrogate_or_strict'):
|
||||||
|
''' Recursively convert dict keys and values to byte str
|
||||||
|
|
||||||
|
Specialized for json return because this only handles, lists, tuples,
|
||||||
|
and dict container types (the containers that the json module returns)
|
||||||
|
'''
|
||||||
|
|
||||||
|
if isinstance(d, text_type):
|
||||||
|
return to_bytes(d, encoding=encoding, errors=errors)
|
||||||
|
elif isinstance(d, dict):
|
||||||
|
return dict(map(container_to_bytes, iteritems(d), repeat(encoding), repeat(errors)))
|
||||||
|
elif isinstance(d, list):
|
||||||
|
return list(map(container_to_bytes, d, repeat(encoding), repeat(errors)))
|
||||||
|
elif isinstance(d, tuple):
|
||||||
|
return tuple(map(container_to_bytes, d, repeat(encoding), repeat(errors)))
|
||||||
|
else:
|
||||||
|
return d
|
||||||
|
|
||||||
|
|
||||||
|
def container_to_text(d, encoding='utf-8', errors='surrogate_or_strict'):
|
||||||
|
"""Recursively convert dict keys and values to byte str
|
||||||
|
|
||||||
|
Specialized for json return because this only handles, lists, tuples,
|
||||||
|
and dict container types (the containers that the json module returns)
|
||||||
|
"""
|
||||||
|
|
||||||
|
if isinstance(d, binary_type):
|
||||||
|
# Warning, can traceback
|
||||||
|
return to_text(d, encoding=encoding, errors=errors)
|
||||||
|
elif isinstance(d, dict):
|
||||||
|
return dict(map(container_to_text, iteritems(d), repeat(encoding), repeat(errors)))
|
||||||
|
elif isinstance(d, list):
|
||||||
|
return list(map(container_to_text, d, repeat(encoding), repeat(errors)))
|
||||||
|
elif isinstance(d, tuple):
|
||||||
|
return tuple(map(container_to_text, d, repeat(encoding), repeat(errors)))
|
||||||
|
else:
|
||||||
|
return d
|
||||||
@ -0,0 +1,100 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (c) 2019 Ansible Project
|
||||||
|
# Simplified BSD License (see licenses/simplified_bsd.txt or https://opensource.org/licenses/BSD-2-Clause)
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
|
from ansible.module_utils.six import iteritems
|
||||||
|
|
||||||
|
SIZE_RANGES = {
|
||||||
|
'Y': 1 << 80,
|
||||||
|
'Z': 1 << 70,
|
||||||
|
'E': 1 << 60,
|
||||||
|
'P': 1 << 50,
|
||||||
|
'T': 1 << 40,
|
||||||
|
'G': 1 << 30,
|
||||||
|
'M': 1 << 20,
|
||||||
|
'K': 1 << 10,
|
||||||
|
'B': 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def lenient_lowercase(lst):
|
||||||
|
"""Lowercase elements of a list.
|
||||||
|
|
||||||
|
If an element is not a string, pass it through untouched.
|
||||||
|
"""
|
||||||
|
lowered = []
|
||||||
|
for value in lst:
|
||||||
|
try:
|
||||||
|
lowered.append(value.lower())
|
||||||
|
except AttributeError:
|
||||||
|
lowered.append(value)
|
||||||
|
return lowered
|
||||||
|
|
||||||
|
|
||||||
|
def human_to_bytes(number, default_unit=None, isbits=False):
|
||||||
|
"""Convert number in string format into bytes (ex: '2K' => 2048) or using unit argument.
|
||||||
|
example: human_to_bytes('10M') <=> human_to_bytes(10, 'M')
|
||||||
|
"""
|
||||||
|
m = re.search(r'^\s*(\d*\.?\d*)\s*([A-Za-z]+)?', str(number), flags=re.IGNORECASE)
|
||||||
|
if m is None:
|
||||||
|
raise ValueError("human_to_bytes() can't interpret following string: %s" % str(number))
|
||||||
|
try:
|
||||||
|
num = float(m.group(1))
|
||||||
|
except Exception:
|
||||||
|
raise ValueError("human_to_bytes() can't interpret following number: %s (original input string: %s)" % (m.group(1), number))
|
||||||
|
|
||||||
|
unit = m.group(2)
|
||||||
|
if unit is None:
|
||||||
|
unit = default_unit
|
||||||
|
|
||||||
|
if unit is None:
|
||||||
|
''' No unit given, returning raw number '''
|
||||||
|
return int(round(num))
|
||||||
|
range_key = unit[0].upper()
|
||||||
|
try:
|
||||||
|
limit = SIZE_RANGES[range_key]
|
||||||
|
except Exception:
|
||||||
|
raise ValueError("human_to_bytes() failed to convert %s (unit = %s). The suffix must be one of %s" % (number, unit, ", ".join(SIZE_RANGES.keys())))
|
||||||
|
|
||||||
|
# default value
|
||||||
|
unit_class = 'B'
|
||||||
|
unit_class_name = 'byte'
|
||||||
|
# handling bits case
|
||||||
|
if isbits:
|
||||||
|
unit_class = 'b'
|
||||||
|
unit_class_name = 'bit'
|
||||||
|
# check unit value if more than one character (KB, MB)
|
||||||
|
if len(unit) > 1:
|
||||||
|
expect_message = 'expect %s%s or %s' % (range_key, unit_class, range_key)
|
||||||
|
if range_key == 'B':
|
||||||
|
expect_message = 'expect %s or %s' % (unit_class, unit_class_name)
|
||||||
|
|
||||||
|
if unit_class_name in unit.lower():
|
||||||
|
pass
|
||||||
|
elif unit[1] != unit_class:
|
||||||
|
raise ValueError("human_to_bytes() failed to convert %s. Value is not a valid string (%s)" % (number, expect_message))
|
||||||
|
|
||||||
|
return int(round(num * limit))
|
||||||
|
|
||||||
|
|
||||||
|
def bytes_to_human(size, isbits=False, unit=None):
|
||||||
|
base = 'Bytes'
|
||||||
|
if isbits:
|
||||||
|
base = 'bits'
|
||||||
|
suffix = ''
|
||||||
|
|
||||||
|
for suffix, limit in sorted(iteritems(SIZE_RANGES), key=lambda item: -item[1]):
|
||||||
|
if (unit is None and size >= limit) or unit is not None and unit.upper() == suffix[0]:
|
||||||
|
break
|
||||||
|
|
||||||
|
if limit != 1:
|
||||||
|
suffix += base[0]
|
||||||
|
else:
|
||||||
|
suffix = base
|
||||||
|
|
||||||
|
return '%.2f %s' % (size / limit, suffix)
|
||||||
@ -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)
|
||||||
Loading…
Reference in New Issue