def safe_repr(obj, short=False, max_length=80) -> str:
    """
    Create a string representation of this object using :py:func:`repr`. If the
    object doesn't have a repr defined, then falls back onto the default
    :py:func:`object.__repr__`. Finally, if ``short`` is true, then the string
    will be truncated to the max_length value.

    Args:
        obj (Any): Any object to repr.
        short (bool): Whether or not to truncate to the max_length.
        max_length (int): How many maximum characters to use, if short is True.
    """
    try:
        result = repr(obj)
    except Exception:
        result = object.__repr__(obj)
    if short and len(result) >= max_length:
        result = result[:max_length] + ' [truncated]...'
    result = result
    return result