import boto from unittest import SkipTest from collections.abc import Iterable from sure import assertion def version_tuple(v): return tuple(map(int, (v.split(".")))) # Note: See https://github.com/spulec/moto/issues/201 for why this is a # separate method. def skip_test(): raise SkipTest class requires_boto_gte(object): """Decorator for requiring boto version greater than or equal to 'version'""" def __init__(self, version): self.version = version def __call__(self, test): boto_version = version_tuple(boto.__version__) required = version_tuple(self.version) if boto_version >= required: return test return skip_test @assertion def containing_item_with_attributes(context, **kwargs): contains = False if kwargs and isinstance(context.obj, Iterable): for item in context.obj: if not isinstance(item, dict): continue for k, v in kwargs.items(): if k not in item or item[k] != v: break else: contains = True if context.negative: assert not contains, f"{context.obj} contains matching item {kwargs}" else: assert contains, f"{context.obj} does not contain matching item {kwargs}" return True