Merge "Switch to collections.abc.*"

This commit is contained in:
Zuul 2021-03-12 08:07:07 +00:00 committed by Gerrit Code Review
commit 98dc789fbc
28 changed files with 123 additions and 116 deletions

View File

@ -248,7 +248,7 @@ the end user.
*AllowedValues(allowed, description)*: *AllowedValues(allowed, description)*:
Lists the allowed values. ``allowed`` must be a Lists the allowed values. ``allowed`` must be a
``collections.Sequence`` or ``basestring``. Applicable to all types ``collections.abc.Sequence`` or ``basestring``. Applicable to all types
of value except MAP. of value except MAP.
*Length(min, max, description)*: *Length(min, max, description)*:
@ -480,16 +480,16 @@ that updates require the engine to delete and re-create the resource
Update the physical resources using updated information. Update the physical resources using updated information.
:param json_snippet: the resource definition from the updated template :param json_snippet: the resource definition from the updated template
:type json_snippet: collections.Mapping :type json_snippet: collections.abc.Mapping
:param tmpl_diff: values in the updated definition that have changed :param tmpl_diff: values in the updated definition that have changed
with respect to the original template definition. with respect to the original template definition.
:type tmpl_diff: collections.Mapping :type tmpl_diff: collections.abc.Mapping
:param prop_diff: property values that are different between the original :param prop_diff: property values that are different between the original
definition and the updated definition; keys are definition and the updated definition; keys are
property names and values are the new values. Deleted or property names and values are the new values. Deleted or
properties that were originally present but now absent properties that were originally present but now absent
have values of ``None`` have values of ``None``
:type prop_diff: collections.Mapping :type prop_diff: collections.abc.Mapping
*Note* Before calling ``handle_update`` we check whether need to replace *Note* Before calling ``handle_update`` we check whether need to replace
the resource, especially for resource in ``*_FAILED`` state, there is a the resource, especially for resource in ``*_FAILED`` state, there is a

View File

@ -57,10 +57,10 @@ def merge_map(old, new, deep_merge=False):
if v is not None: if v is not None:
if not deep_merge: if not deep_merge:
old[k] = v old[k] = v
elif isinstance(v, collections.Mapping): elif isinstance(v, collections.abc.Mapping):
old_v = old.get(k) old_v = old.get(k)
old[k] = merge_map(old_v, v, deep_merge) if old_v else v old[k] = merge_map(old_v, v, deep_merge) if old_v else v
elif (isinstance(v, collections.Sequence) and elif (isinstance(v, collections.abc.Sequence) and
not isinstance(v, str)): not isinstance(v, str)):
old_v = old.get(k) old_v = old.get(k)
old[k] = merge_list(old_v, v) if old_v else v old[k] = merge_list(old_v, v) if old_v else v
@ -79,7 +79,7 @@ def parse_param(p_val, p_schema):
p_val = jsonutils.dumps(p_val) p_val = jsonutils.dumps(p_val)
if p_val: if p_val:
return jsonutils.loads(p_val) return jsonutils.loads(p_val)
elif not isinstance(p_val, collections.Sequence): elif not isinstance(p_val, collections.abc.Sequence):
raise ValueError() raise ValueError()
except (ValueError, TypeError) as err: except (ValueError, TypeError) as err:
msg = _("Invalid parameter in environment %s.") % str(err) msg = _("Invalid parameter in environment %s.") % str(err)

View File

@ -20,7 +20,7 @@ from urllib import parse as urlparse
from heat.common.i18n import _ from heat.common.i18n import _
class HeatIdentifier(collections.Mapping): class HeatIdentifier(collections.abc.Mapping):
FIELDS = ( FIELDS = (
TENANT, STACK_NAME, STACK_ID, PATH TENANT, STACK_NAME, STACK_ID, PATH

View File

@ -292,7 +292,7 @@ def format_resource_attributes(resource, with_attr=None):
if 'show' in resolver: if 'show' in resolver:
show_attr = resolve('show', resolver) show_attr = resolve('show', resolver)
# check if 'show' resolved to dictionary. so it's not None # check if 'show' resolved to dictionary. so it's not None
if isinstance(show_attr, collections.Mapping): if isinstance(show_attr, collections.abc.Mapping):
for a in with_attr: for a in with_attr:
if a not in show_attr: if a not in show_attr:
show_attr[a] = resolve(a, resolver) show_attr[a] = resolve(a, resolver)

View File

@ -138,7 +138,7 @@ BASE_ATTRIBUTES = (SHOW_ATTR, ) = ('show', )
ALL_ATTRIBUTES = '*' ALL_ATTRIBUTES = '*'
class Attributes(collections.Mapping): class Attributes(collections.abc.Mapping):
"""Models a collection of Resource Attributes.""" """Models a collection of Resource Attributes."""
def __init__(self, res_name, schema, resolver): def __init__(self, res_name, schema, resolver):
@ -212,14 +212,14 @@ class Attributes(collections.Mapping):
{'name': attrib.name, {'name': attrib.name,
'att_type': attrib.schema.STRING}) 'att_type': attrib.schema.STRING})
elif attrib.schema.type == attrib.schema.LIST: elif attrib.schema.type == attrib.schema.LIST:
if (not isinstance(value, collections.Sequence) if (not isinstance(value, collections.abc.Sequence)
or isinstance(value, str)): or isinstance(value, str)):
LOG.warning("Attribute %(name)s is not of type " LOG.warning("Attribute %(name)s is not of type "
"%(att_type)s", "%(att_type)s",
{'name': attrib.name, {'name': attrib.name,
'att_type': attrib.schema.LIST}) 'att_type': attrib.schema.LIST})
elif attrib.schema.type == attrib.schema.MAP: elif attrib.schema.type == attrib.schema.MAP:
if not isinstance(value, collections.Mapping): if not isinstance(value, collections.abc.Mapping):
LOG.warning("Attribute %(name)s is not of type " LOG.warning("Attribute %(name)s is not of type "
"%(att_type)s", "%(att_type)s",
{'name': attrib.name, {'name': attrib.name,
@ -307,8 +307,8 @@ def select_from_attribute(attribute_value, path):
:returns: the selected attribute component value. :returns: the selected attribute component value.
""" """
def get_path_component(collection, key): def get_path_component(collection, key):
if not isinstance(collection, (collections.Mapping, if not isinstance(collection, (collections.abc.Mapping,
collections.Sequence)): collections.abc.Sequence)):
raise TypeError(_("Can't traverse attribute path")) raise TypeError(_("Can't traverse attribute path"))
if not isinstance(key, (str, int)): if not isinstance(key, (str, int)):

View File

@ -168,7 +168,7 @@ class Select(function.Function):
'err': json_ex} 'err': json_ex}
raise ValueError(_('"%(fn_name)s": %(err)s') % fmt_data) raise ValueError(_('"%(fn_name)s": %(err)s') % fmt_data)
if isinstance(strings, collections.Mapping): if isinstance(strings, collections.abc.Mapping):
if not isinstance(index, str): if not isinstance(index, str):
raise TypeError(_('Index to "%s" must be a string') % raise TypeError(_('Index to "%s" must be a string') %
self.fn_name) self.fn_name)
@ -179,7 +179,7 @@ class Select(function.Function):
except (ValueError, TypeError): except (ValueError, TypeError):
pass pass
if (isinstance(strings, collections.Sequence) and if (isinstance(strings, collections.abc.Sequence) and
not isinstance(strings, str)): not isinstance(strings, str)):
if not isinstance(index, int): if not isinstance(index, int):
raise TypeError(_('Index to "%s" must be an integer') % raise TypeError(_('Index to "%s" must be an integer') %
@ -229,7 +229,7 @@ class Split(function.Function):
fmt_data = {'fn_name': self.fn_name, fmt_data = {'fn_name': self.fn_name,
'example': example} 'example': example}
if isinstance(self.args, (str, collections.Mapping)): if isinstance(self.args, (str, collections.abc.Mapping)):
raise TypeError(_('Incorrect arguments to "%(fn_name)s" ' raise TypeError(_('Incorrect arguments to "%(fn_name)s" '
'should be: %(example)s') % fmt_data) 'should be: %(example)s') % fmt_data)
@ -278,7 +278,7 @@ class Replace(hot_funcs.Replace):
fmt_data = {'fn_name': self.fn_name, fmt_data = {'fn_name': self.fn_name,
'example': example} 'example': example}
if isinstance(self.args, (str, collections.Mapping)): if isinstance(self.args, (str, collections.abc.Mapping)):
raise TypeError(_('Incorrect arguments to "%(fn_name)s" ' raise TypeError(_('Incorrect arguments to "%(fn_name)s" '
'should be: %(example)s') % fmt_data) 'should be: %(example)s') % fmt_data)
@ -350,7 +350,7 @@ class MemberListToMap(function.Function):
def result(self): def result(self):
member_list = function.resolve(self._list) member_list = function.resolve(self._list)
if not isinstance(member_list, collections.Iterable): if not isinstance(member_list, collections.abc.Iterable):
raise TypeError(_('Member list must be a list')) raise TypeError(_('Member list must be a list'))
def item(s): def item(s):
@ -428,7 +428,7 @@ class Not(hot_funcs.Not):
msg = _('Arguments to "%s" must be of the form: ' msg = _('Arguments to "%s" must be of the form: '
'[condition]') % self.fn_name '[condition]') % self.fn_name
if (not self.args or if (not self.args or
not isinstance(self.args, collections.Sequence) or not isinstance(self.args, collections.abc.Sequence) or
isinstance(self.args, str)): isinstance(self.args, str)):
raise ValueError(msg) raise ValueError(msg)
if len(self.args) != 1: if len(self.args) != 1:

View File

@ -596,7 +596,7 @@ echo -e '%s\tALL=(ALL)\tNOPASSWD: ALL' >> /etc/sudoers
def meta_serialize(self, metadata): def meta_serialize(self, metadata):
"""Serialize non-string metadata values before sending them to Nova.""" """Serialize non-string metadata values before sending them to Nova."""
if not isinstance(metadata, collections.Mapping): if not isinstance(metadata, collections.abc.Mapping):
raise exception.StackValidationFailed(message=_( raise exception.StackValidationFailed(message=_(
"nova server metadata needs to be a Map.")) "nova server metadata needs to be a Map."))
@ -647,7 +647,7 @@ echo -e '%s\tALL=(ALL)\tNOPASSWD: ALL' >> /etc/sudoers
""" """
nc = self.client nc = self.client
class ConsoleUrls(collections.Mapping): class ConsoleUrls(collections.abc.Mapping):
def __init__(self, server): def __init__(self, server):
self.console_method = server.get_console_url self.console_method = server.get_console_url
self.support_console_types = ['novnc', 'xvpvnc', self.support_console_types = ['novnc', 'xvpvnc',

View File

@ -24,7 +24,7 @@ _in_progress = object()
class Conditions(object): class Conditions(object):
def __init__(self, conditions_dict): def __init__(self, conditions_dict):
assert isinstance(conditions_dict, collections.Mapping) assert isinstance(conditions_dict, collections.abc.Mapping)
self._conditions = conditions_dict self._conditions = conditions_dict
self._resolved = {} self._resolved = {}

View File

@ -36,7 +36,7 @@ MEMOIZE = core.get_memoization_decorator(conf=cfg.CONF,
LOG = log.getLogger(__name__) LOG = log.getLogger(__name__)
class Schema(collections.Mapping): class Schema(collections.abc.Mapping):
"""Schema base class for validating properties or parameters. """Schema base class for validating properties or parameters.
Schema objects are serializable to dictionaries following a superset of Schema objects are serializable to dictionaries following a superset of
@ -251,7 +251,7 @@ class Schema(collections.Mapping):
return self._len return self._len
class AnyIndexDict(collections.Mapping): class AnyIndexDict(collections.abc.Mapping):
"""A Mapping that returns the same value for any integer index. """A Mapping that returns the same value for any integer index.
Used for storing the schema for a list. When converted to a dictionary, Used for storing the schema for a list. When converted to a dictionary,
@ -276,7 +276,7 @@ class AnyIndexDict(collections.Mapping):
return 1 return 1
class Constraint(collections.Mapping): class Constraint(collections.abc.Mapping):
"""Parent class for constraints on allowable values for a Property. """Parent class for constraints on allowable values for a Property.
Constraints are serializable to dictionaries following the HOT input Constraints are serializable to dictionaries following the HOT input
@ -540,7 +540,7 @@ class AllowedValues(Constraint):
def __init__(self, allowed, description=None): def __init__(self, allowed, description=None):
super(AllowedValues, self).__init__(description) super(AllowedValues, self).__init__(description)
if (not isinstance(allowed, collections.Sequence) or if (not isinstance(allowed, collections.abc.Sequence) or
isinstance(allowed, str)): isinstance(allowed, str)):
raise exception.InvalidSchemaError( raise exception.InvalidSchemaError(
message=_('AllowedValues must be a list')) message=_('AllowedValues must be a list'))

View File

@ -55,7 +55,7 @@ def is_hook_definition(key, value):
if key == 'hooks': if key == 'hooks':
if isinstance(value, str): if isinstance(value, str):
is_valid_hook = valid_hook_type(value) is_valid_hook = valid_hook_type(value)
elif isinstance(value, collections.Sequence): elif isinstance(value, collections.abc.Sequence):
is_valid_hook = all(valid_hook_type(hook) for hook in value) is_valid_hook = all(valid_hook_type(hook) for hook in value)
if not is_valid_hook: if not is_valid_hook:
@ -72,7 +72,7 @@ def is_valid_restricted_action(key, value):
if key == 'restricted_actions': if key == 'restricted_actions':
if isinstance(value, str): if isinstance(value, str):
valid_action = valid_restricted_actions(value) valid_action = valid_restricted_actions(value)
elif isinstance(value, collections.Sequence): elif isinstance(value, collections.abc.Sequence):
valid_action = all(valid_restricted_actions( valid_action = all(valid_restricted_actions(
action) for action in value) action) for action in value)
@ -397,7 +397,7 @@ class ResourceRegistry(object):
actions = resource['restricted_actions'] actions = resource['restricted_actions']
if isinstance(actions, str): if isinstance(actions, str):
restricted_actions.add(actions) restricted_actions.add(actions)
elif isinstance(actions, collections.Sequence): elif isinstance(actions, collections.abc.Sequence):
restricted_actions |= set(actions) restricted_actions |= set(actions)
return restricted_actions return restricted_actions
@ -433,7 +433,7 @@ class ResourceRegistry(object):
if isinstance(hooks, str): if isinstance(hooks, str):
if hook == hooks: if hook == hooks:
return True return True
elif isinstance(hooks, collections.Sequence): elif isinstance(hooks, collections.abc.Sequence):
if hook in hooks: if hook in hooks:
return True return True
return False return False

View File

@ -266,12 +266,12 @@ def resolve(snippet, nullable=False):
result = None result = None
return result return result
if isinstance(snippet, collections.Mapping): if isinstance(snippet, collections.abc.Mapping):
return dict(filter(_non_null_item, return dict(filter(_non_null_item,
((k, resolve(v, nullable=True)) ((k, resolve(v, nullable=True))
for k, v in snippet.items()))) for k, v in snippet.items())))
elif (not isinstance(snippet, str) and elif (not isinstance(snippet, str) and
isinstance(snippet, collections.Iterable)): isinstance(snippet, collections.abc.Iterable)):
return list(filter(_non_null_value, return list(filter(_non_null_value,
(resolve(v, nullable=True) for v in snippet))) (resolve(v, nullable=True) for v in snippet)))
@ -293,11 +293,11 @@ def validate(snippet, path=None):
raise exception.StackValidationFailed( raise exception.StackValidationFailed(
path=path + [snippet.fn_name], path=path + [snippet.fn_name],
message=str(e)) message=str(e))
elif isinstance(snippet, collections.Mapping): elif isinstance(snippet, collections.abc.Mapping):
for k, v in snippet.items(): for k, v in snippet.items():
validate(v, path + [k]) validate(v, path + [k])
elif (not isinstance(snippet, str) and elif (not isinstance(snippet, str) and
isinstance(snippet, collections.Iterable)): isinstance(snippet, collections.abc.Iterable)):
basepath = list(path) basepath = list(path)
parent = basepath.pop() if basepath else '' parent = basepath.pop() if basepath else ''
for i, v in enumerate(snippet): for i, v in enumerate(snippet):
@ -314,7 +314,7 @@ def dependencies(snippet, path=''):
if isinstance(snippet, Function): if isinstance(snippet, Function):
return snippet.dependencies(path) return snippet.dependencies(path)
elif isinstance(snippet, collections.Mapping): elif isinstance(snippet, collections.abc.Mapping):
def mkpath(key): def mkpath(key):
return '.'.join([path, str(key)]) return '.'.join([path, str(key)])
@ -323,7 +323,7 @@ def dependencies(snippet, path=''):
return itertools.chain.from_iterable(deps) return itertools.chain.from_iterable(deps)
elif (not isinstance(snippet, str) and elif (not isinstance(snippet, str) and
isinstance(snippet, collections.Iterable)): isinstance(snippet, collections.abc.Iterable)):
def mkpath(idx): def mkpath(idx):
return ''.join([path, '[%d]' % idx]) return ''.join([path, '[%d]' % idx])
@ -348,11 +348,11 @@ def dep_attrs(snippet, resource_name):
if isinstance(snippet, Function): if isinstance(snippet, Function):
return snippet.dep_attrs(resource_name) return snippet.dep_attrs(resource_name)
elif isinstance(snippet, collections.Mapping): elif isinstance(snippet, collections.abc.Mapping):
attrs = (dep_attrs(val, resource_name) for val in snippet.values()) attrs = (dep_attrs(val, resource_name) for val in snippet.values())
return itertools.chain.from_iterable(attrs) return itertools.chain.from_iterable(attrs)
elif (not isinstance(snippet, str) and elif (not isinstance(snippet, str) and
isinstance(snippet, collections.Iterable)): isinstance(snippet, collections.abc.Iterable)):
attrs = (dep_attrs(value, resource_name) for value in snippet) attrs = (dep_attrs(value, resource_name) for value in snippet)
return itertools.chain.from_iterable(attrs) return itertools.chain.from_iterable(attrs)
return [] return []
@ -371,11 +371,11 @@ def all_dep_attrs(snippet):
if isinstance(snippet, Function): if isinstance(snippet, Function):
return snippet.all_dep_attrs() return snippet.all_dep_attrs()
elif isinstance(snippet, collections.Mapping): elif isinstance(snippet, collections.abc.Mapping):
res_attrs = (all_dep_attrs(value) for value in snippet.values()) res_attrs = (all_dep_attrs(value) for value in snippet.values())
return itertools.chain.from_iterable(res_attrs) return itertools.chain.from_iterable(res_attrs)
elif (not isinstance(snippet, str) and elif (not isinstance(snippet, str) and
isinstance(snippet, collections.Iterable)): isinstance(snippet, collections.abc.Iterable)):
res_attrs = (all_dep_attrs(value) for value in snippet) res_attrs = (all_dep_attrs(value) for value in snippet)
return itertools.chain.from_iterable(res_attrs) return itertools.chain.from_iterable(res_attrs)
return [] return []

View File

@ -79,7 +79,7 @@ class GetParam(function.Function):
if isinstance(args, str): if isinstance(args, str):
param_name = args param_name = args
path_components = [] path_components = []
elif isinstance(args, collections.Sequence): elif isinstance(args, collections.abc.Sequence):
param_name = args[0] param_name = args[0]
path_components = args[1:] path_components = args[1:]
else: else:
@ -96,15 +96,15 @@ class GetParam(function.Function):
raise exception.UserParameterMissing(key=param_name) raise exception.UserParameterMissing(key=param_name)
def get_path_component(collection, key): def get_path_component(collection, key):
if not isinstance(collection, (collections.Mapping, if not isinstance(collection, (collections.abc.Mapping,
collections.Sequence)): collections.abc.Sequence)):
raise TypeError(_('"%s" can\'t traverse path') % self.fn_name) raise TypeError(_('"%s" can\'t traverse path') % self.fn_name)
if not isinstance(key, (str, int)): if not isinstance(key, (str, int)):
raise TypeError(_('Path components in "%s" ' raise TypeError(_('Path components in "%s" '
'must be strings') % self.fn_name) 'must be strings') % self.fn_name)
if isinstance(collection, collections.Sequence if isinstance(collection, collections.abc.Sequence
) and isinstance(key, str): ) and isinstance(key, str):
try: try:
key = int(key) key = int(key)
@ -167,7 +167,7 @@ class GetAttThenSelect(function.Function):
self._path_components) = self._parse_args() self._path_components) = self._parse_args()
def _parse_args(self): def _parse_args(self):
if (not isinstance(self.args, collections.Sequence) or if (not isinstance(self.args, collections.abc.Sequence) or
isinstance(self.args, str)): isinstance(self.args, str)):
raise TypeError(_('Argument to "%s" must be a list') % raise TypeError(_('Argument to "%s" must be a list') %
self.fn_name) self.fn_name)
@ -314,7 +314,7 @@ class GetAttAllAttributes(GetAtt):
'forms: [resource_name] or ' 'forms: [resource_name] or '
'[resource_name, attribute, (path), ...]' '[resource_name, attribute, (path), ...]'
) % self.fn_name) ) % self.fn_name)
elif isinstance(self.args, collections.Sequence): elif isinstance(self.args, collections.abc.Sequence):
if len(self.args) > 1: if len(self.args) > 1:
return super(GetAttAllAttributes, self)._parse_args() return super(GetAttAllAttributes, self)._parse_args()
else: else:
@ -372,12 +372,12 @@ class Replace(function.Function):
self._mapping, self._string = self._parse_args() self._mapping, self._string = self._parse_args()
if not isinstance(self._mapping, if not isinstance(self._mapping,
(collections.Mapping, function.Function)): (collections.abc.Mapping, function.Function)):
raise TypeError(_('"%s" parameters must be a mapping') % raise TypeError(_('"%s" parameters must be a mapping') %
self.fn_name) self.fn_name)
def _parse_args(self): def _parse_args(self):
if not isinstance(self.args, collections.Mapping): if not isinstance(self.args, collections.abc.Mapping):
raise TypeError(_('Arguments to "%s" must be a map') % raise TypeError(_('Arguments to "%s" must be a map') %
self.fn_name) self.fn_name)
@ -418,7 +418,7 @@ class Replace(function.Function):
if not isinstance(template, str): if not isinstance(template, str):
raise TypeError(_('"%s" template must be a string') % self.fn_name) raise TypeError(_('"%s" template must be a string') % self.fn_name)
if not isinstance(mapping, collections.Mapping): if not isinstance(mapping, collections.abc.Mapping):
raise TypeError(_('"%s" params must be a map') % self.fn_name) raise TypeError(_('"%s" params must be a map') % self.fn_name)
def replace(strings, keys): def replace(strings, keys):
@ -490,9 +490,10 @@ class ReplaceJson(Replace):
else: else:
_raise_empty_param_value_error() _raise_empty_param_value_error()
if not isinstance(value, (str, int, if not isinstance(value, (str, int, float, bool)):
float, bool)): if isinstance(
if isinstance(value, (collections.Mapping, collections.Sequence)): value, (collections.abc.Mapping, collections.abc.Sequence)
):
if not self._allow_empty_value and len(value) == 0: if not self._allow_empty_value and len(value) == 0:
_raise_empty_param_value_error() _raise_empty_param_value_error()
try: try:
@ -604,7 +605,7 @@ class Join(function.Function):
if strings is None: if strings is None:
strings = [] strings = []
if (isinstance(strings, str) or if (isinstance(strings, str) or
not isinstance(strings, collections.Sequence)): not isinstance(strings, collections.abc.Sequence)):
raise TypeError(_('"%s" must operate on a list') % self.fn_name) raise TypeError(_('"%s" must operate on a list') % self.fn_name)
delim = function.resolve(self._delim) delim = function.resolve(self._delim)
@ -669,7 +670,7 @@ class JoinMultiple(function.Function):
for jl in r_joinlists: for jl in r_joinlists:
if jl: if jl:
if (isinstance(jl, str) or if (isinstance(jl, str) or
not isinstance(jl, collections.Sequence)): not isinstance(jl, collections.abc.Sequence)):
raise TypeError(_('"%s" must operate on ' raise TypeError(_('"%s" must operate on '
'a list') % self.fn_name) 'a list') % self.fn_name)
@ -687,7 +688,9 @@ class JoinMultiple(function.Function):
return '' return ''
elif isinstance(s, str): elif isinstance(s, str):
return s return s
elif isinstance(s, (collections.Mapping, collections.Sequence)): elif isinstance(
s, (collections.abc.Mapping, collections.abc.Sequence)
):
try: try:
return jsonutils.dumps(s, default=None, sort_keys=True) return jsonutils.dumps(s, default=None, sort_keys=True)
except TypeError: except TypeError:
@ -725,14 +728,14 @@ class MapMerge(function.Function):
def result(self): def result(self):
args = function.resolve(self.args) args = function.resolve(self.args)
if not isinstance(args, collections.Sequence): if not isinstance(args, collections.abc.Sequence):
raise TypeError(_('Incorrect arguments to "%(fn_name)s" ' raise TypeError(_('Incorrect arguments to "%(fn_name)s" '
'should be: %(example)s') % self.fmt_data) 'should be: %(example)s') % self.fmt_data)
def ensure_map(m): def ensure_map(m):
if m is None: if m is None:
return {} return {}
elif isinstance(m, collections.Mapping): elif isinstance(m, collections.abc.Mapping):
return m return m
else: else:
msg = _('Incorrect arguments: Items to merge must be maps.') msg = _('Incorrect arguments: Items to merge must be maps.')
@ -776,7 +779,7 @@ class MapReplace(function.Function):
def ensure_map(m): def ensure_map(m):
if m is None: if m is None:
return {} return {}
elif isinstance(m, collections.Mapping): elif isinstance(m, collections.abc.Mapping):
return m return m
else: else:
msg = (_('Incorrect arguments: to "%(fn_name)s", arguments ' msg = (_('Incorrect arguments: to "%(fn_name)s", arguments '
@ -901,7 +904,7 @@ class Repeat(function.Function):
self._parse_args() self._parse_args()
def _parse_args(self): def _parse_args(self):
if not isinstance(self.args, collections.Mapping): if not isinstance(self.args, collections.abc.Mapping):
raise TypeError(_('Arguments to "%s" must be a map') % raise TypeError(_('Arguments to "%s" must be a map') %
self.fn_name) self.fn_name)
@ -923,12 +926,12 @@ class Repeat(function.Function):
super(Repeat, self).validate() super(Repeat, self).validate()
if not isinstance(self._for_each, function.Function): if not isinstance(self._for_each, function.Function):
if not isinstance(self._for_each, collections.Mapping): if not isinstance(self._for_each, collections.abc.Mapping):
raise TypeError(_('The "for_each" argument to "%s" must ' raise TypeError(_('The "for_each" argument to "%s" must '
'contain a map') % self.fn_name) 'contain a map') % self.fn_name)
def _valid_arg(self, arg): def _valid_arg(self, arg):
if not (isinstance(arg, (collections.Sequence, if not (isinstance(arg, (collections.abc.Sequence,
function.Function)) and function.Function)) and
not isinstance(arg, str)): not isinstance(arg, str)):
raise TypeError(_('The values of the "for_each" argument to ' raise TypeError(_('The values of the "for_each" argument to '
@ -939,10 +942,10 @@ class Repeat(function.Function):
for (key, value) in zip(keys, values): for (key, value) in zip(keys, values):
template = template.replace(key, value) template = template.replace(key, value)
return template return template
elif isinstance(template, collections.Sequence): elif isinstance(template, collections.abc.Sequence):
return [self._do_replacement(keys, values, elem) return [self._do_replacement(keys, values, elem)
for elem in template] for elem in template]
elif isinstance(template, collections.Mapping): elif isinstance(template, collections.abc.Mapping):
return dict((self._do_replacement(keys, values, k), return dict((self._do_replacement(keys, values, k),
self._do_replacement(keys, values, v)) self._do_replacement(keys, values, v))
for (k, v) in template.items()) for (k, v) in template.items())
@ -993,8 +996,8 @@ class RepeatWithMap(Repeat):
""" """
def _valid_arg(self, arg): def _valid_arg(self, arg):
if not (isinstance(arg, (collections.Sequence, if not (isinstance(arg, (collections.abc.Sequence,
collections.Mapping, collections.abc.Mapping,
function.Function)) and function.Function)) and
not isinstance(arg, str)): not isinstance(arg, str)):
raise TypeError(_('The values of the "for_each" argument to ' raise TypeError(_('The values of the "for_each" argument to '
@ -1118,7 +1121,7 @@ class StrSplit(function.Function):
'example': example} 'example': example}
self.fn_name = fn_name self.fn_name = fn_name
if isinstance(args, (str, collections.Mapping)): if isinstance(args, (str, collections.abc.Mapping)):
raise TypeError(_('Incorrect arguments to "%(fn_name)s" ' raise TypeError(_('Incorrect arguments to "%(fn_name)s" '
'should be: %(example)s') % self.fmt_data) 'should be: %(example)s') % self.fmt_data)
@ -1188,7 +1191,7 @@ class Yaql(function.Function):
def __init__(self, stack, fn_name, args): def __init__(self, stack, fn_name, args):
super(Yaql, self).__init__(stack, fn_name, args) super(Yaql, self).__init__(stack, fn_name, args)
if not isinstance(self.args, collections.Mapping): if not isinstance(self.args, collections.abc.Mapping):
raise TypeError(_('Arguments to "%s" must be a map.') % raise TypeError(_('Arguments to "%s" must be a map.') %
self.fn_name) self.fn_name)
@ -1281,7 +1284,7 @@ class If(function.Macro):
def parse_args(self, parse_func): def parse_args(self, parse_func):
try: try:
if (not self.args or if (not self.args or
not isinstance(self.args, collections.Sequence) or not isinstance(self.args, collections.abc.Sequence) or
isinstance(self.args, str)): isinstance(self.args, str)):
raise ValueError() raise ValueError()
condition, value_if_true, value_if_false = self._read_args() condition, value_if_true, value_if_false = self._read_args()
@ -1344,7 +1347,7 @@ class ConditionBoolean(function.Function):
self._check_args() self._check_args()
def _check_args(self): def _check_args(self):
if not (isinstance(self.args, collections.Sequence) and if not (isinstance(self.args, collections.abc.Sequence) and
not isinstance(self.args, str)): not isinstance(self.args, str)):
msg = _('Arguments to "%s" must be a list of conditions') msg = _('Arguments to "%s" must be a list of conditions')
raise ValueError(msg % self.fn_name) raise ValueError(msg % self.fn_name)
@ -1439,7 +1442,7 @@ class Filter(function.Function):
self._values, self._sequence = self._parse_args() self._values, self._sequence = self._parse_args()
def _parse_args(self): def _parse_args(self):
if (not isinstance(self.args, collections.Sequence) or if (not isinstance(self.args, collections.abc.Sequence) or
isinstance(self.args, str)): isinstance(self.args, str)):
raise TypeError(_('Argument to "%s" must be a list') % raise TypeError(_('Argument to "%s" must be a list') %
self.fn_name) self.fn_name)
@ -1501,7 +1504,7 @@ class MakeURL(function.Function):
if arg in args: if arg in args:
if arg == self.QUERY: if arg == self.QUERY:
if not isinstance(args[arg], (function.Function, if not isinstance(args[arg], (function.Function,
collections.Mapping)): collections.abc.Mapping)):
raise TypeError(_('The "%(arg)s" argument to ' raise TypeError(_('The "%(arg)s" argument to '
'"%(fn_name)s" must be a map') % '"%(fn_name)s" must be a map') %
{'arg': arg, {'arg': arg,
@ -1536,7 +1539,7 @@ class MakeURL(function.Function):
def validate(self): def validate(self):
super(MakeURL, self).validate() super(MakeURL, self).validate()
if not isinstance(self.args, collections.Mapping): if not isinstance(self.args, collections.abc.Mapping):
raise TypeError(_('The arguments to "%s" must ' raise TypeError(_('The arguments to "%s" must '
'be a map') % self.fn_name) 'be a map') % self.fn_name)
@ -1619,14 +1622,14 @@ class ListConcat(function.Function):
args = function.resolve(self.args) args = function.resolve(self.args)
if (isinstance(args, str) or if (isinstance(args, str) or
not isinstance(args, collections.Sequence)): not isinstance(args, collections.abc.Sequence)):
raise TypeError(_('Incorrect arguments to "%(fn_name)s" ' raise TypeError(_('Incorrect arguments to "%(fn_name)s" '
'should be: %(example)s') % self.fmt_data) 'should be: %(example)s') % self.fmt_data)
def ensure_list(m): def ensure_list(m):
if m is None: if m is None:
return [] return []
elif (isinstance(m, collections.Sequence) and elif (isinstance(m, collections.abc.Sequence) and
not isinstance(m, str)): not isinstance(m, str)):
return m return m
else: else:
@ -1691,7 +1694,7 @@ class Contains(function.Function):
resolved_value = function.resolve(self.value) resolved_value = function.resolve(self.value)
resolved_sequence = function.resolve(self.sequence) resolved_sequence = function.resolve(self.sequence)
if not isinstance(resolved_sequence, collections.Sequence): if not isinstance(resolved_sequence, collections.abc.Sequence):
raise TypeError(_('Second argument to "%s" should be ' raise TypeError(_('Second argument to "%s" should be '
'a sequence.') % self.fn_name) 'a sequence.') % self.fn_name)

View File

@ -388,7 +388,7 @@ class ParsedParameter(Parameter):
return self._parsed return self._parsed
class CommaDelimitedListParam(ParsedParameter, collections.Sequence): class CommaDelimitedListParam(ParsedParameter, collections.abc.Sequence):
"""A template parameter of type "CommaDelimitedList".""" """A template parameter of type "CommaDelimitedList"."""
__slots__ = tuple() __slots__ = tuple()
@ -481,7 +481,7 @@ class JsonParam(ParsedParameter):
self.schema.validate_value(parsed, context) self.schema.validate_value(parsed, context)
class Parameters(collections.Mapping, metaclass=abc.ABCMeta): class Parameters(collections.abc.Mapping, metaclass=abc.ABCMeta):
"""Parameters of a stack. """Parameters of a stack.
The parameters of a stack, with type checking, defaults, etc. specified by The parameters of a stack, with type checking, defaults, etc. specified by

View File

@ -93,7 +93,7 @@ class PluginMapping(object):
'from %(module)s', fmt_data) 'from %(module)s', fmt_data)
raise raise
else: else:
if isinstance(mapping_dict, collections.Mapping): if isinstance(mapping_dict, collections.abc.Mapping):
return mapping_dict return mapping_dict
elif mapping_dict is not None: elif mapping_dict is not None:
LOG.error('Invalid type for %(mapping_name)s ' LOG.error('Invalid type for %(mapping_name)s '

View File

@ -300,14 +300,14 @@ class Property(object):
def _get_map(self, value, validate=False, translation=None): def _get_map(self, value, validate=False, translation=None):
if value is None: if value is None:
value = self.default() if self.has_default() else {} value = self.default() if self.has_default() else {}
if not isinstance(value, collections.Mapping): if not isinstance(value, collections.abc.Mapping):
# This is to handle passing Lists via Json parameters exposed # This is to handle passing Lists via Json parameters exposed
# via a provider resource, in particular lists-of-dicts which # via a provider resource, in particular lists-of-dicts which
# cannot be handled correctly via comma_delimited_list # cannot be handled correctly via comma_delimited_list
if self.schema.allow_conversion: if self.schema.allow_conversion:
if isinstance(value, str): if isinstance(value, str):
return value return value
elif isinstance(value, collections.Sequence): elif isinstance(value, collections.abc.Sequence):
return jsonutils.dumps(value) return jsonutils.dumps(value)
raise TypeError(_('"%s" is not a map') % value) raise TypeError(_('"%s" is not a map') % value)
@ -320,7 +320,7 @@ class Property(object):
value = self.has_default() and self.default() or [] value = self.has_default() and self.default() or []
if self.schema.allow_conversion and isinstance(value, str): if self.schema.allow_conversion and isinstance(value, str):
value = param_utils.delim_string_to_list(value) value = param_utils.delim_string_to_list(value)
if (not isinstance(value, collections.Sequence) or if (not isinstance(value, collections.abc.Sequence) or
isinstance(value, str)): isinstance(value, str)):
raise TypeError(_('"%s" is not a list') % repr(value)) raise TypeError(_('"%s" is not a list') % repr(value))
@ -376,7 +376,7 @@ def _default_resolver(d, nullable=False):
return d return d
class Properties(collections.Mapping): class Properties(collections.abc.Mapping):
def __init__(self, schema, data, resolver=_default_resolver, def __init__(self, schema, data, resolver=_default_resolver,
parent_name=None, parent_name=None,

View File

@ -1066,7 +1066,7 @@ class Resource(status.ResourceStatus):
refd_attrs |= get_dep_attrs(stk_defn.resource_definition(r_name) refd_attrs |= get_dep_attrs(stk_defn.resource_definition(r_name)
for r_name in enabled_resources) for r_name in enabled_resources)
subset_outputs = isinstance(in_outputs, collections.Iterable) subset_outputs = isinstance(in_outputs, collections.abc.Iterable)
if subset_outputs or in_outputs: if subset_outputs or in_outputs:
if not subset_outputs: if not subset_outputs:
in_outputs = stk_defn.enabled_output_names() in_outputs = stk_defn.enabled_output_names()

View File

@ -610,12 +610,12 @@ class ResourceGroup(stack_resource.StackResource):
result = None result = None
return result return result
if isinstance(snippet, collections.Mapping): if isinstance(snippet, collections.abc.Mapping):
return dict(filter(function._non_null_item, return dict(filter(function._non_null_item,
((k, ignore_param_resolve(v, nullable=True)) ((k, ignore_param_resolve(v, nullable=True))
for k, v in snippet.items()))) for k, v in snippet.items())))
elif (not isinstance(snippet, str) and elif (not isinstance(snippet, str) and
isinstance(snippet, collections.Iterable)): isinstance(snippet, collections.abc.Iterable)):
return list(filter(function._non_null_value, return list(filter(function._non_null_value,
(ignore_param_resolve(v, nullable=True) (ignore_param_resolve(v, nullable=True)
for v in snippet))) for v in snippet)))
@ -646,9 +646,9 @@ class ResourceGroup(stack_resource.StackResource):
if isinstance(val, str): if isinstance(val, str):
return val.replace(repl_var, res_name) return val.replace(repl_var, res_name)
elif isinstance(val, collections.Mapping): elif isinstance(val, collections.abc.Mapping):
return {k: recurse(v) for k, v in val.items()} return {k: recurse(v) for k, v in val.items()}
elif isinstance(val, collections.Sequence): elif isinstance(val, collections.abc.Sequence):
return [recurse(v) for v in val] return [recurse(v) for v in val]
return val return val

View File

@ -166,7 +166,7 @@ class StructuredDeployment(sd.SoftwareDeployment):
input_key, input_key,
check_input_val=check_input_val) check_input_val=check_input_val)
if isinstance(snippet, collections.Mapping): if isinstance(snippet, collections.abc.Mapping):
fn_arg = StructuredDeployment.get_input_key_arg(snippet, input_key) fn_arg = StructuredDeployment.get_input_key_arg(snippet, input_key)
if fn_arg is not None: if fn_arg is not None:
return StructuredDeployment.get_input_key_value(fn_arg, inputs, return StructuredDeployment.get_input_key_value(fn_arg, inputs,
@ -175,7 +175,7 @@ class StructuredDeployment(sd.SoftwareDeployment):
return dict((k, parse(v)) for k, v in snippet.items()) return dict((k, parse(v)) for k, v in snippet.items())
elif (not isinstance(snippet, str) and elif (not isinstance(snippet, str) and
isinstance(snippet, collections.Iterable)): isinstance(snippet, collections.abc.Iterable)):
return [parse(v) for v in snippet] return [parse(v) for v in snippet]
else: else:
return snippet return snippet

View File

@ -106,10 +106,10 @@ class L2Gateway(neutron.NeutronResource):
@staticmethod @staticmethod
def _remove_none_value_props(props): def _remove_none_value_props(props):
if isinstance(props, collections.Mapping): if isinstance(props, collections.abc.Mapping):
return dict((k, L2Gateway._remove_none_value_props(v)) for k, v return dict((k, L2Gateway._remove_none_value_props(v)) for k, v
in props.items() if v is not None) in props.items() if v is not None)
elif (isinstance(props, collections.Sequence) and elif (isinstance(props, collections.abc.Sequence) and
not isinstance(props, str)): not isinstance(props, str)):
return list(L2Gateway._remove_none_value_props(p) for p in props return list(L2Gateway._remove_none_value_props(p) for p in props
if p is not None) if p is not None)

View File

@ -57,7 +57,7 @@ class BaseWaitConditionHandle(signal_responder.SignalResponder):
return status in self.WAIT_STATUSES return status in self.WAIT_STATUSES
def _metadata_format_ok(self, metadata): def _metadata_format_ok(self, metadata):
if not isinstance(metadata, collections.Mapping): if not isinstance(metadata, collections.abc.Mapping):
return False return False
if set(metadata) != set(self.METADATA_KEYS): if set(metadata) != set(self.METADATA_KEYS):
return False return False

View File

@ -113,17 +113,17 @@ class ResourceDefinition(object):
assert isinstance(self.description, str) assert isinstance(self.description, str)
if properties is not None: if properties is not None:
assert isinstance(properties, (collections.Mapping, assert isinstance(properties, (collections.abc.Mapping,
function.Function)) function.Function))
self._hash ^= _hash_data(properties) self._hash ^= _hash_data(properties)
if metadata is not None: if metadata is not None:
assert isinstance(metadata, (collections.Mapping, assert isinstance(metadata, (collections.abc.Mapping,
function.Function)) function.Function))
self._hash ^= _hash_data(metadata) self._hash ^= _hash_data(metadata)
if depends is not None: if depends is not None:
assert isinstance(depends, (collections.Sequence, assert isinstance(depends, (collections.abc.Sequence,
function.Function)) function.Function))
assert not isinstance(depends, str) assert not isinstance(depends, str)
self._hash ^= _hash_data(depends) self._hash ^= _hash_data(depends)
@ -133,7 +133,7 @@ class ResourceDefinition(object):
self._hash ^= _hash_data(deletion_policy) self._hash ^= _hash_data(deletion_policy)
if update_policy is not None: if update_policy is not None:
assert isinstance(update_policy, (collections.Mapping, assert isinstance(update_policy, (collections.abc.Mapping,
function.Function)) function.Function))
self._hash ^= _hash_data(update_policy) self._hash ^= _hash_data(update_policy)
@ -432,10 +432,10 @@ def _hash_data(data):
data = copy.deepcopy(data) data = copy.deepcopy(data)
if not isinstance(data, str): if not isinstance(data, str):
if isinstance(data, collections.Sequence): if isinstance(data, collections.abc.Sequence):
return hash(tuple(_hash_data(d) for d in data)) return hash(tuple(_hash_data(d) for d in data))
if isinstance(data, collections.Mapping): if isinstance(data, collections.abc.Mapping):
item_hashes = (hash(k) ^ _hash_data(v) for k, v in data.items()) item_hashes = (hash(k) ^ _hash_data(v) for k, v in data.items())
return functools.reduce(operator.xor, item_hashes, 0) return functools.reduce(operator.xor, item_hashes, 0)

View File

@ -178,10 +178,14 @@ def check_io_schema_list(io_configs):
Raises TypeError if the list itself is not a list, or if any of the Raises TypeError if the list itself is not a list, or if any of the
members are not dicts. members are not dicts.
""" """
if (not isinstance(io_configs, collections.Sequence) or if (
isinstance(io_configs, collections.Mapping) or not isinstance(io_configs, collections.abc.Sequence) or
isinstance(io_configs, str)): isinstance(io_configs, collections.abc.Mapping) or
isinstance(io_configs, str)
):
raise TypeError('Software Config I/O Schema must be in a list') raise TypeError('Software Config I/O Schema must be in a list')
if not all(isinstance(conf, collections.Mapping) for conf in io_configs): if not all(
isinstance(conf, collections.abc.Mapping) for conf in io_configs
):
raise TypeError('Software Config I/O Schema must be a dict') raise TypeError('Software Config I/O Schema must be a dict')

View File

@ -100,7 +100,7 @@ def reset_state_on_error(func):
return handle_exceptions return handle_exceptions
class Stack(collections.Mapping): class Stack(collections.abc.Mapping):
ACTIONS = ( ACTIONS = (
CREATE, DELETE, UPDATE, ROLLBACK, SUSPEND, RESUME, ADOPT, CREATE, DELETE, UPDATE, ROLLBACK, SUSPEND, RESUME, ADOPT,

View File

@ -89,7 +89,7 @@ def get_template_class(template_data):
raise exception.InvalidTemplateVersion(explanation=explanation) raise exception.InvalidTemplateVersion(explanation=explanation)
class Template(collections.Mapping): class Template(collections.abc.Mapping):
"""Abstract base class for template format plugins. """Abstract base class for template format plugins.
All template formats (both internal and third-party) should derive from All template formats (both internal and third-party) should derive from
@ -355,7 +355,7 @@ class Template(collections.Mapping):
def parse(functions, stack, snippet, path='', template=None): def parse(functions, stack, snippet, path='', template=None):
recurse = functools.partial(parse, functions, stack, template=template) recurse = functools.partial(parse, functions, stack, template=template)
if isinstance(snippet, collections.Mapping): if isinstance(snippet, collections.abc.Mapping):
def mkpath(key): def mkpath(key):
return '.'.join([path, str(key)]) return '.'.join([path, str(key)])
@ -380,7 +380,7 @@ def parse(functions, stack, snippet, path='', template=None):
return dict((k, recurse(v, mkpath(k))) return dict((k, recurse(v, mkpath(k)))
for k, v in snippet.items()) for k, v in snippet.items())
elif (not isinstance(snippet, str) and elif (not isinstance(snippet, str) and
isinstance(snippet, collections.Iterable)): isinstance(snippet, collections.abc.Iterable)):
def mkpath(idx): def mkpath(idx):
return ''.join([path, '[%d]' % idx]) return ''.join([path, '[%d]' % idx])

View File

@ -80,18 +80,18 @@ class CommonTemplate(template.Template):
yield ('properties', yield ('properties',
self._parse_resource_field(self.RES_PROPERTIES, self._parse_resource_field(self.RES_PROPERTIES,
(collections.Mapping, (collections.abc.Mapping,
function.Function), 'object', function.Function), 'object',
name, data, parse)) name, data, parse))
yield ('metadata', yield ('metadata',
self._parse_resource_field(self.RES_METADATA, self._parse_resource_field(self.RES_METADATA,
(collections.Mapping, (collections.abc.Mapping,
function.Function), 'object', function.Function), 'object',
name, data, parse)) name, data, parse))
depends = self._parse_resource_field(self.RES_DEPENDS_ON, depends = self._parse_resource_field(self.RES_DEPENDS_ON,
collections.Sequence, collections.abc.Sequence,
'list or string', 'list or string',
name, data, no_parse) name, data, no_parse)
if isinstance(depends, str): if isinstance(depends, str):
@ -122,7 +122,7 @@ class CommonTemplate(template.Template):
yield ('update_policy', yield ('update_policy',
self._parse_resource_field(self.RES_UPDATE_POLICY, self._parse_resource_field(self.RES_UPDATE_POLICY,
(collections.Mapping, (collections.abc.Mapping,
function.Function), 'object', function.Function), 'object',
name, data, parse)) name, data, parse))
@ -143,7 +143,7 @@ class CommonTemplate(template.Template):
return cached_conds return cached_conds
raw_defs = self._get_condition_definitions() raw_defs = self._get_condition_definitions()
if not isinstance(raw_defs, collections.Mapping): if not isinstance(raw_defs, collections.abc.Mapping):
message = _('Condition definitions must be a map. Found a ' message = _('Condition definitions must be a map. Found a '
'%s instead') % type(raw_defs).__name__ '%s instead') % type(raw_defs).__name__
raise exception.StackValidationFailed( raise exception.StackValidationFailed(
@ -166,7 +166,7 @@ class CommonTemplate(template.Template):
def get_outputs(): def get_outputs():
for key, val in outputs.items(): for key, val in outputs.items():
if not isinstance(val, collections.Mapping): if not isinstance(val, collections.abc.Mapping):
message = _('Output definitions must be a map. Found a ' message = _('Output definitions must be a map. Found a '
'%s instead') % type(val).__name__ '%s instead') % type(val).__name__
raise exception.StackValidationFailed( raise exception.StackValidationFailed(

View File

@ -28,7 +28,7 @@ class ReadOnlyDict(dict):
raise ValueError("Attempted to write to internal TemplateFiles cache") raise ValueError("Attempted to write to internal TemplateFiles cache")
class TemplateFiles(collections.Mapping): class TemplateFiles(collections.abc.Mapping):
def __init__(self, files): def __init__(self, files):
self.files = None self.files = None

View File

@ -3397,7 +3397,7 @@ class ServersTest(common.HeatTestCase):
ws.resource_id = server.id ws.resource_id = server.id
self.patchobject(self.fc.servers, 'get', return_value=server) self.patchobject(self.fc.servers, 'get', return_value=server)
console_urls = ws._resolve_any_attribute('console_urls') console_urls = ws._resolve_any_attribute('console_urls')
self.assertIsInstance(console_urls, collections.Mapping) self.assertIsInstance(console_urls, collections.abc.Mapping)
supported_consoles = ('novnc', 'xvpvnc', 'spice-html5', 'rdp-html5', supported_consoles = ('novnc', 'xvpvnc', 'spice-html5', 'rdp-html5',
'serial', 'webmks') 'serial', 'webmks')
self.assertEqual(set(supported_consoles), self.assertEqual(set(supported_consoles),

View File

@ -4433,7 +4433,7 @@ class TestResourceMapping(common.HeatTestCase):
def _check_mapping_func(self, func, module): def _check_mapping_func(self, func, module):
self.assertTrue(callable(func)) self.assertTrue(callable(func))
res = func() res = func()
self.assertIsInstance(res, collections.Mapping) self.assertIsInstance(res, collections.abc.Mapping)
for r_type, r_class in res.items(): for r_type, r_class in res.items():
self.assertIsInstance(r_type, str) self.assertIsInstance(r_type, str)
type_elements = r_type.split('::') type_elements = r_type.split('::')