# This file is part of Shuup.
#
# Copyright (c) 2012-2021, Shuup Commerce Inc. All rights reserved.
#
# This source code is licensed under the OSL-3.0 license found in the
# LICENSE file in the root directory of this source tree.
import six
[docs]def compare_partial_dicts(source, comparee):
"""
Compare dicts in a "partial" manner.
All key/value pairs in `source` must exist and be equal to those in `comparee`.
This differs from a raw == in that keys that do not exist in `source` may exist in `comparee`.
:param source: source dict
:type source: dict
:param comparee: comparee dict
:type comparee: dict
:rtype: bool
:return: True or False
"""
for key, value in six.iteritems(source):
if key not in comparee or value != comparee[key]:
return False
return True
[docs]def compact(in_obj, none_only=True, deep=True):
"""
Compact iterable by removing falsy values.
Iterable may be a mapping or a list.
By default uses ``not value`` to test for falseness, but if
`none_only` is set, will use ``value is None``.
By default, iterables within the iterable are also compacted. This
can be controlled by the `deep` argument.
:param in_obj: The object to compact
:type in_obj: Iterable
:param none_only: Remove only Nones
:type none_only: bool
:param deep: Recurse through iterables within `in_obj`
:type deep: bool
:return: Flattened iterable
:rtype: list|dict
"""
if isinstance(in_obj, dict) or hasattr(in_obj, "keys"):
is_dict = True
iterator = six.iteritems(in_obj)
out_obj = {}
else:
is_dict = False
iterator = enumerate(in_obj)
out_obj = []
for key, value in iterator:
if none_only and value is None:
continue
if not value:
continue
if deep and hasattr(value, "__iter__") and not isinstance(value, six.string_types):
value = compact(value, none_only=none_only, deep=True)
if is_dict:
out_obj[key] = value
else:
out_obj.append(value)
return out_obj