def _generic_assert_type(arg, arg_name, type_handle, type_name, type_casting_ok):
    """Assert if the arg is of type(s) type_handle or, if type_casting_ok is 
    True, assert if the arg can be cast to any of type_handle.

    Parameters
    ----------
    arg : 
        The variable being checked.
    arg_name : string
        The name of the variable used for the error message.
    type_handle : 
        The handle for the variable type desired. Can be a single handle (e.g. 
        type_handle=int) or a sequence of handles (e.g. type_handle=(int, 
        float)).
    type_name : 
        The name of the type(s) for the error message. (e.g. 'int or float')
    type_casting_ok:
        Indicates whether type casting is allowed. However, the function only 
        checks that it is possible. **The function does not actually recast the 
        variable.** 

    Returns
    -------
    type_handle :
        The returned type handle will be the same as the input type_handle 
        unless type_casting_ok is True and there are multiple accepted types. 
        If so, the return handle will be the first successful type to cast the 
        variable.
    """
    error_message = f"{arg_name} ({type(arg)}) must be of type {type_name}"
    output_type_handle = type_handle
    try:
        # See if arg is of type(s) type_handle
        assert isinstance(arg, type_handle), error_message

    except AssertionError as wrong_type_error:
        # arg is not of type type_handle
       
        # If type casting is not allowed, re-raise the failure
        if not type_casting_ok:
            raise wrong_type_error

        # Type casting is allowed, see if arg can be casted to type(s) 
        # type_handle
        if isinstance(type_handle, (tuple, list)):
            # Multiple accepted types, see if arg can be cast to any
            # RETURNS the first type handle that is successful
            for th in type_handle:
                try:
                    assert isinstance(th(arg), th)
                    output_type_handle = th
                    break
                except:
                    pass
            else:
                # Failed to find a valid casting type
                raise wrong_type_error
        else:
            # Single accepted type, see if arg can be cast to it
            try:
                assert isinstance(type_handle(arg), type_handle)
            except (AssertionError, ValueError, TypeError):
                raise wrong_type_error

    # Assertions all passed
    return output_type_handle