Push the current working directory (CWD) onto a stack, set CWD to 'dir'

    Save the CWD onto a global stack so that we can return to it later. If dir
    is None, the function simply stores the CWD onto the stack and returns.
    Use :py:meth:`popd()` to restore the original directory.

    Parameters
    ----------
        dir : str, optional
            The directory to switch to or None. If None, the default if it
            is not passed, this function will simply push the current working
            directory onto the global stack and return.
        throw_if_dir_invalid : bool, optional
            Whether or not to pass back up any exception raised by chdir().
            Default is True.

    Returns
    -------
        True : bool
            Success
        False : bool
            Failure

    Raises
    ------
        OSError
            If `throw_if_dir_invalid` is True and chdir raises an exception,
            this function will chain the same exception as chdir, typically 
            OSError

        TypeError
            If the type of ``dir`` is not an instance of `str`

    Notes
    -----
    This method and its counterpart :py:meth:`popd` are `not` thread safe!

def pushd(dir=None, throw_if_dir_invalid=True):
    """Push the current working directory (CWD) onto a stack, set CWD to 'dir'

    Save the CWD onto a global stack so that we can return to it later. If dir
    is None, the function simply stores the CWD onto the stack and returns.
    Use :py:meth:`popd()` to restore the original directory.

    Parameters
    ----------
        dir : str, optional
            The directory to switch to or None. If None, the default if it
            is not passed, this function will simply push the current working
            directory onto the global stack and return.
        throw_if_dir_invalid : bool, optional
            Whether or not to pass back up any exception raised by chdir().
            Default is True.

    Returns
    -------
        True : bool
            Success
        False : bool
            Failure

    Raises
    ------
        OSError
            If `throw_if_dir_invalid` is True and chdir raises an exception,
            this function will chain the same exception as chdir, typically 
            OSError

        TypeError
            If the type of ``dir`` is not an instance of `str`

    Notes
    -----
    This method and its counterpart :py:meth:`popd` are `not` thread safe!
    """
    global _pushdstack
    from os import getcwd, chdir

    if dir is None:
        dir = getcwd()

    if not isinstance(dir,type('')):
        raise TypeError("pushd() expected string object, but got {}".format(type(dir)))

    _pushdstack.append(getcwd())
    
    if not dir:
        return

    try:
        chdir(dir)
        err = 0
    except OSError:
        _pushdstack.pop()
        if throw_if_dir_invalid:
            raise
        err = 1

    return True if err == 0 else False