SPPAS 4.22

https://sppas.org/

Module sppas.src.utils

Class sppasCompare

Description

Utility class to compare data.

Example
 >>> sc = sppasCompare()
 >>> d1 = {1:"one", 2:"two"}
 >>> d2 = {2:"TWO", 1:"ONE"}
 >>> sc.equals(d1, d2)
 >>> True
 >>> sc.equals_lists(d1.keys(), d2.keys())
 >>> False
 >>> sc.set_case_sensitive(True)
 >>> sc.equals(d1, d2)
 >>> False

Constructor

Create a sppasCompare instance and set options.

Parameters
  • verbose: (bool) Print comparison results on stdout
  • case_sensitive: (bool) Only to compare strings
View Source
def __init__(self, verbose=False, case_sensitive=False):
    """Create a sppasCompare instance and set options.

    :param verbose: (bool) Print comparison results on stdout
    :param case_sensitive: (bool) Only to compare strings

    """
    self._verbose = verbose
    self._case_sensitive = case_sensitive

Public functions

set_verbose

Print comparison results on stdout or not.

Parameters
  • v: (bool) Enable or disable verbosity
View Source
def set_verbose(self, v):
    """Print comparison results on stdout or not.

        :param v: (bool) Enable or disable verbosity

        """
    self._verbose = bool(v)

set_case_sensitive

Compare strings with lower/upper case.

Parameters
  • v: (bool) Enable or not the case sensitive comparison of strings
View Source
def set_case_sensitive(self, v):
    """Compare strings with lower/upper case.

        :param v: (bool) Enable or not the case sensitive comparison of strings

        """
    self._case_sensitive = bool(v)

equals

Compare two data sets of any type.

Parameters

data1(any) The data to compare. data2(any) The data to be compared with.

Returns
  • (bool) whether the 2 data sets are equals or not
View Source
def equals(self, data1, data2):
    """Compare two data sets of any type.

        :param data1 (any) The data to compare.
        :param data2 (any) The data to be compared with.
        :returns: (bool) whether the 2 data sets are equals or not

        """
    if data1 is None or data2 is None:
        if self._verbose:
            logging.info('TypeError: None instead of data.')
        return False
    if type(data1) is list:
        return self.equals_lists(data1, data2)
    if sppasType.is_dict(data1) is True:
        return self.equals_dictionaries(data1, data2)
    return self.equals_items(data1, data2)

equals_lists

Compare two lists.

Parameters

list1(list) The list to compare. list2(list) The list to be compared with.

Returns
  • (bool) whether the 2 lists are equals or not
View Source
def equals_lists(self, list1, list2):
    """Compare two lists.

        :param list1 (list) The list to compare.
        :param list2 (list) The list to be compared with.
        :returns: (bool) whether the 2 lists are equals or not

        """
    if list1 is None or list2 is None:
        if self._verbose is True:
            logging.info('TypeError: None instead of lists.')
        return False
    if type(list1) != type(list2) or type(list1) is not list or type(list2) is not list:
        if self._verbose is True:
            logging.info('TypeError: Not same types (expected 2 lists).')
        return False
    if len(list1) != len(list2):
        if self._verbose is True:
            logging.info('FALSE: Not the same number of items: {0} {1}.'.format(len(list1), len(list2)))
        return False
    for item1, item2 in zip(list1, list2):
        if sppasType.is_dict(item1) is True:
            items_are_equals = self.equals_dictionaries(item1, item2)
        elif type(item1) is list:
            items_are_equals = self.equals_lists(item1, item2)
        else:
            items_are_equals = self.equals_items(item1, item2)
        if items_are_equals is False:
            return False
    return True

equals_dictionaries

Compare two dictionaries.

Parameters
  • dict1: (dict or collection) The dict to compare.
  • dict2: (dict or collection) The dict to be compared with.
Returns
  • (bool) whether the 2 dictionaries are equals or not
View Source
def equals_dictionaries(self, dict1, dict2):
    """Compare two dictionaries.

        :param dict1: (dict or collection) The dict to compare.
        :param dict2: (dict or collection) The dict to be compared with.
        :returns: (bool) whether the 2 dictionaries are equals or not

        """
    if dict1 is None or dict2 is None:
        if self._verbose is True:
            logging.info('TypeError: None instead of lists.')
        return False
    if sppasType.is_dict(dict1) is False or sppasType.is_dict(dict2) is False:
        if self._verbose is True:
            logging.info('TypeError: Not same types (expected two dictionaries).')
        return False
    shared_keys = set(dict2.keys()) & set(dict2.keys())
    if not len(shared_keys) == len(dict1.keys()) or not len(shared_keys) == len(dict2.keys()):
        if self._verbose is True:
            logging.info('FALSE: not shared keys: {0} vs {1}'.format(dict1.keys(), dict2.keys()))
        return False
    for key in dict1:
        if sppasType.is_dict(dict1[key]) is True:
            items_are_equals = self.equals_dictionaries(dict1[key], dict2[key])
        elif type(dict1[key]) is list:
            items_are_equals = self.equals_lists(dict1[key], dict2[key])
        else:
            items_are_equals = self.equals_items(dict1[key], dict2[key])
        if items_are_equals is False:
            return False
    return True

equals_items

Compare 2 items of type string or numeric.

Parameters
  • item1: The string or numeric to compare
  • item2: The string or numeric to be compared with
Returns
  • (bool) whether the 2 items are equals or not
View Source
def equals_items(self, item1, item2):
    """Compare 2 items of type string or numeric.

        :param item1: The string or numeric to compare
        :param item2: The string or numeric to be compared with
        :returns: (bool) whether the 2 items are equals or not

        """
    if isinstance(item1, (text_type, binary_type)) is True:
        return self.equals_strings(item1, item2)
    if type(item1) is float or type(item2) is float:
        if round(item1, 4) != round(item2, 4):
            if self._verbose is True:
                logging.info('Float values rounded to 4 digits are not equals: {:0.4f} != {:0.4f}'.format(item1, item2))
            return False
        return True
    if item1 != item2:
        if self._verbose is True:
            logging.info('Not equals: {0} {1}'.format(item1, item2))
        return False
    return True

equals_strings

Compare 2 data of type string or unicode.

Parameters
  • item1: The string to compare
  • item2: The string to be compared with
Returns
  • (bool) whether the 2 items are equals or not
View Source
def equals_strings(self, item1, item2):
    """Compare 2 data of type string or unicode.

        :param item1: The string to compare
        :param item2: The string to be compared with
        :returns: (bool) whether the 2 items are equals or not

        """
    if isinstance(item1, (text_type, binary_type)) is False or isinstance(item2, (text_type, binary_type)) is False:
        if self._verbose is True:
            logging.info('TypeError: Not same types (expected two strings).')
        return False
    if isinstance(item1, binary_type):
        item1 = u(item1)
    if isinstance(item2, binary_type):
        item2 = u(item2)
    if self._case_sensitive is False:
        return item1.lower() == item2.lower()
    return item1 == item2

contains

Check if a list is contained in another one.

Parameters
  • list1: (list)
  • list2: (list)
Returns
  • (bool)
View Source
@staticmethod
def contains(list1, list2):
    """Check if a list is contained in another one.

        :param list1: (list)
        :param list2: (list)
        :returns: (bool)

        """
    for i in range(len(list1) - len(list2) + 1):
        if list1[i:i + len(list2)] == list2:
            return True
    return False