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