"""
Stack ADT.

Operations:
    pop: remove and return top item
    push(item): store item on top of stack
    is_empty: return whether stack is empty.
"""


class Stack:

    """A last-in, first-out (LIFO) stack of items"""

    def __init__(self: 'Stack', data: list =None) -> None:
        """Create a new empty Stack using data

        data --- initial contents of Stack
        """
        if data: # data is a non-empty list
            self._data = data[:] # a copy
        else:
            self._data = []

    def pop(self: 'Stack') -> object:
        """Remove and return the top item."""
        # use the pop method of list...
        return self._data.pop()

    def is_empty(self: 'Stack') -> bool:
        """Return whether the stack is empty."""
        return self._data == []

    def push(self: 'Stack', o: object) -> None:
        """Place o on top of the stack."""
        self._data.append(o)

    def __eq__(self: 'Stack', other: 'Stack') -> bool:
        """Return whether self is equivalent to other.

	>>> s1 = Stack()
	>>> s2 = Stack()
	>>> s1 == s2
	True
	>>> s1.push(7)
	>>> s1 == s2
	False
	>>> s2.push(7)
	>>> s1 == s2
	True
	"""
        # We're comparing self to a Stack AND our _datas are equivalent
        return isinstance(other, Stack) and self._data == other._data

    def __repr__(self: 'Stack') -> str:
        """Return representation of self as a string.

        >>> s = Stack()
        >>> s.push(3)
        >>> s
        Stack([3])
        """
        # Create a string that can be cut-and-pasted into
        # shell to create an equivalent Stack
        return 'Stack(' + repr(self._data) + ')'

if __name__ == '__main__':
    import doctest
    doctest.testmod()
