Convert input into a pandas only dtype object or a numpy dtype object.

    Parameters
    ----------
    dtype : object to be converted

    Returns
    -------
    np.dtype or a pandas dtype

    Raises
    ------
    TypeError if not a dtype

def pandas_dtype(dtype):
    """
    Convert input into a pandas only dtype object or a numpy dtype object.

    Parameters
    ----------
    dtype : object to be converted

    Returns
    -------
    np.dtype or a pandas dtype

    Raises
    ------
    TypeError if not a dtype
    """
    # short-circuit
    if isinstance(dtype, np.ndarray):
        return dtype.dtype
    elif isinstance(dtype, (np.dtype, PandasExtensionDtype, ExtensionDtype)):
        return dtype

    # registered extension types
    result = registry.find(dtype)
    if result is not None:
        return result

    # try a numpy dtype
    # raise a consistent TypeError if failed
    try:
        npdtype = np.dtype(dtype)
    except Exception:
        # we don't want to force a repr of the non-string
        if not isinstance(dtype, str):
            raise TypeError("data type not understood")
        raise TypeError("data type '{}' not understood".format(
            dtype))

    # Any invalid dtype (such as pd.Timestamp) should raise an error.
    # np.dtype(invalid_type).kind = 0 for such objects. However, this will
    # also catch some valid dtypes such as object, np.object_ and 'object'
    # which we safeguard against by catching them earlier and returning
    # np.dtype(valid_dtype) before this condition is evaluated.
    if is_hashable(dtype) and dtype in [object, np.object_, 'object', 'O']:
        # check hashability to avoid errors/DeprecationWarning when we get
        # here and `dtype` is an array
        return npdtype
    elif npdtype.kind == 'O':
        raise TypeError("dtype '{}' not understood".format(dtype))

    return npdtype