def all_equal(left, right, cache=None):
    'Check whether two objects `left` and `right` are equal.\n\n    Parameters\n    ----------\n    left : Union[object, Expr, Node]\n    right : Union[object, Expr, Node]\n    cache : Optional[Dict[Tuple[Node, Node], bool]]\n        A dictionary indicating whether two Nodes are equal\n    '
    if (cache is None):
        cache = {}
    if util.is_iterable(left):
        return (util.is_iterable(right) and (len(left) == len(right)) and all(itertools.starmap(functools.partial(all_equal, cache=cache), zip(left, right))))
    if hasattr(left, 'equals'):
        return left.equals(right, cache=cache)
    return (left == right)
Check whether two objects `left` and `right` are equal.

Parameters
----------
left : Union[object, Expr, Node]
right : Union[object, Expr, Node]
cache : Optional[Dict[Tuple[Node, Node], bool]]
    A dictionary indicating whether two Nodes are equal
def all_equal(left, right, cache=None):
    'Check whether two objects `left` and `right` are equal.\n\n    Parameters\n    ----------\n    left : Union[object, Expr, Node]\n    right : Union[object, Expr, Node]\n    cache : Optional[Dict[Tuple[Node, Node], bool]]\n        A dictionary indicating whether two Nodes are equal\n    '
    if (cache is None):
        cache = {}
    if util.is_iterable(left):
        return (util.is_iterable(right) and (len(left) == len(right)) and all(itertools.starmap(functools.partial(all_equal, cache=cache), zip(left, right))))
    if hasattr(left, 'equals'):
        return left.equals(right, cache=cache)
    return (left == right)