def __dir__(self): """Includes all slots in the `dir` method""" result = set() result.update(dir(self.__class__), self.__all_slots__) if hasattr(self, '__dict__'): result.update(compat.iterkeys(self.__dict__)) return list(result)
def nested_equal(a, b): """Compares two objects recursively by their elements. Also handles numpy arrays, pandas data and sparse matrices. First checks if the data falls into the above categories. If not, it is checked if a or b are some type of sequence or mapping and the contained elements are compared. If this is not the case, it is checked if a or b do provide a custom `__eq__` that evaluates to a single boolean value. If this is not the case, the attributes of a and b are compared. If this does not help either, normal `==` is used. Assumes hashable items are not mutable in a way that affects equality. Based on the suggestion from HERE_, thanks again Lauritz V. Thaulow :-) .. _HERE: http://stackoverflow.com/questions/18376935/best-practice-for-equality-in-python """ if a is b: return True if a is None or b is None: return False a_sparse = spsp.isspmatrix(a) b_sparse = spsp.isspmatrix(b) if a_sparse != b_sparse: return False if a_sparse: if a.nnz == 0: return b.nnz == 0 else: return not np.any((a != b).data) a_panel = isinstance(a, (pd.Panel, pd.Panel4D)) b_panel = isinstance(b, (pd.Panel, pd.Panel4D)) if a_panel != b_panel: return False if a_panel: return nested_equal(a.to_frame(), b.to_frame()) a_series = isinstance(a, pd.Series) b_series = isinstance(b, pd.Series) if a_series != b_series: return False if a_series: try: eq = (a == b).all() return eq except (TypeError, ValueError): # If Sequence itself contains numpy arrays we get here if not len(a) == len(b): return False for idx, itema in enumerate(a): itemb = b[idx] if not nested_equal(itema, itemb): return False return True a_frame = isinstance(a, pd.DataFrame) b_frame = isinstance(b, pd.DataFrame) if a_frame != b_frame: return False if a_frame: try: if a.empty and b.empty: return True new_frame = a == b new_frame = new_frame | (pd.isnull(a) & pd.isnull(b)) if isinstance(new_frame, pd.DataFrame): return np.all(new_frame.as_matrix()) except (ValueError, TypeError): # The Value Error can happen if the data frame is of dtype=object and contains # numpy arrays. Numpy array comparisons do not evaluate to a single truth value for name in a: cola = a[name] if not name in b: return False colb = b[name] if not len(cola) == len(colb): return False for idx, itema in enumerate(cola): itemb = colb[idx] if not nested_equal(itema, itemb): return False return True a_array = isinstance(a, np.ndarray) b_array = isinstance(b, np.ndarray) if a_array != b_array: return False if a_array: if a.shape != b.shape: return False return np.all(a == b) a_list = isinstance(a, (Sequence, list, tuple)) b_list = isinstance(b, (Sequence, list, tuple)) if a_list != b_list: return False if a_list: return all(nested_equal(x, y) for x, y in zip(a, b)) a_mapping = isinstance(a, (Mapping, dict)) b_mapping = isinstance(b, (Mapping, dict)) if a_mapping != b_mapping: return False if a_mapping: keys_a = a.keys() if set(keys_a) != set(b.keys()): return False return all(nested_equal(a[k], b[k]) for k in keys_a) # Equality for general objects # for types that support __eq__ or __cmp__ equality = NotImplemented try: equality = a.__eq__(b) except (AttributeError, NotImplementedError, TypeError, ValueError): pass if equality is NotImplemented: try: equality = b.__eq__(a) except (AttributeError, NotImplementedError, TypeError, ValueError): pass if equality is NotImplemented: try: cmp = a.__cmp__(b) if cmp is not NotImplemented: equality = cmp == 0 except (AttributeError, NotImplementedError, TypeError, ValueError): pass if equality is NotImplemented: try: cmp = b.__cmp__(a) if cmp is not NotImplemented: equality = cmp == 0 except (AttributeError, NotImplementedError, TypeError, ValueError): pass if equality is not NotImplemented: try: return bool(equality) except (AttributeError, NotImplementedError, TypeError, ValueError): pass # Compare objects based on their attributes attributes_a = get_all_attributes(a) attributes_b = get_all_attributes(b) if len(attributes_a) != len(attributes_b): return False if len(attributes_a) > 0: keys_a = compat.listkeys(attributes_a) if set(keys_a) != set(compat.iterkeys(attributes_b)): return False return all(nested_equal(attributes_a[k], attributes_b[k]) for k in keys_a) # Ok they are really not equal return False
def __iter__(self): iter_list = [compat.iterkeys(mapping) for mapping in self._maps] return itools.chain(*iter_list)
def nested_equal(a, b): """Compares two objects recursively by their elements. Also handles numpy arrays, pandas data and sparse matrices. First checks if the data falls into the above categories. If not, it is checked if a or b are some type of sequence or mapping and the contained elements are compared. If this is not the case, it is checked if a or b do provide a custom `__eq__` that evaluates to a single boolean value. If this is not the case, the attributes of a and b are compared. If this does not help either, normal `==` is used. Assumes hashable items are not mutable in a way that affects equality. Based on the suggestion from HERE_, thanks again Lauritz V. Thaulow :-) .. _HERE: http://stackoverflow.com/questions/18376935/best-practice-for-equality-in-python """ if a is b: return True if a is None or b is None: return False a_sparse = spsp.isspmatrix(a) b_sparse = spsp.isspmatrix(b) if a_sparse != b_sparse: return False if a_sparse: if a.nnz == 0: return b.nnz == 0 else: return not np.any((a != b).data) a_panel = isinstance(a, (pd.Panel, pd.Panel4D)) b_panel = isinstance(b, (pd.Panel, pd.Panel4D)) if a_panel != b_panel: return False if a_panel: return nested_equal(a.to_frame(), b.to_frame()) a_series = isinstance(a, pd.Series) b_series = isinstance(b, pd.Series) if a_series != b_series: return False if a_series: try: eq = (a == b).all() return eq except (TypeError, ValueError): # If Sequence itself contains numpy arrays we get here if not len(a) == len(b): return False for idx, itema in enumerate(a): itemb = b[idx] if not nested_equal(itema, itemb): return False return True a_frame = isinstance(a, pd.DataFrame) b_frame = isinstance(b, pd.DataFrame) if a_frame != b_frame: return False if a_frame: try: if a.empty and b.empty: return True new_frame = a == b new_frame = new_frame | (pd.isnull(a) & pd.isnull(b)) if isinstance(new_frame, pd.DataFrame): return np.all(new_frame.as_matrix()) except (ValueError, TypeError): # The Value Error can happen if the data frame is of dtype=object and contains # numpy arrays. Numpy array comparisons do not evaluate to a single truth value for name in a: cola = a[name] if not name in b: return False colb = b[name] if not len(cola) == len(colb): return False for idx, itema in enumerate(cola): itemb = colb[idx] if not nested_equal(itema, itemb): return False return True a_array = isinstance(a, np.ndarray) b_array = isinstance(b, np.ndarray) if a_array != b_array: return False if a_array: if a.shape != b.shape: return False return np.all(a == b) a_list = isinstance(a, (Sequence, list, tuple)) b_list = isinstance(b, (Sequence, list, tuple)) if a_list != b_list: return False if a_list: return all(nested_equal(x, y) for x, y in zip(a, b)) a_mapping = isinstance(a, (Mapping, dict)) b_mapping = isinstance(b, (Mapping, dict)) if a_mapping != b_mapping: return False if a_mapping: keys_a = a.keys() if set(keys_a) != set(b.keys()): return False return all(nested_equal(a[k], b[k]) for k in keys_a) # Equality for general objects # for types that support __eq__ or __cmp__ equality = NotImplemented try: equality = a.__eq__(b) except (AttributeError, NotImplementedError, TypeError, ValueError): pass if equality is NotImplemented: try: equality = b.__eq__(a) except (AttributeError, NotImplementedError, TypeError, ValueError): pass if equality is NotImplemented: try: cmp = a.__cmp__(b) if cmp is not NotImplemented: equality = cmp == 0 except (AttributeError, NotImplementedError, TypeError, ValueError): pass if equality is NotImplemented: try: cmp = b.__cmp__(a) if cmp is not NotImplemented: equality = cmp == 0 except (AttributeError, NotImplementedError, TypeError, ValueError): pass if equality is not NotImplemented: try: return bool(equality) except (AttributeError, NotImplementedError, TypeError, ValueError): pass # Compare objects based on their attributes attributes_a = get_all_attributes(a) attributes_b = get_all_attributes(b) if len(attributes_a) != len(attributes_b): return False if len(attributes_a) > 0: keys_a = compat.listkeys(attributes_a) if set(keys_a) != set(compat.iterkeys(attributes_b)): return False return all( nested_equal(attributes_a[k], attributes_b[k]) for k in keys_a) # Ok they are really not equal return False