string representation of function definition

    Returns:
        str: a representation of func with args, kwargs, and type_aliases

    Args:
        func (function):
        args (list): argument values (default = [])
        kwargs (dict): kwargs values (default = {})
        type_aliases (list): (default = [])
        packed (bool): (default = False)
        packkw (None): (default = None)

    Returns:
        str: func_str

    CommandLine:
        python -m utool.util_str --exec-func_str

    Example:
        >>> # ENABLE_DOCTEST
        >>> from utool.util_str import *  # NOQA
        >>> func = byte_str
        >>> args = [1024, 'MB']
        >>> kwargs = dict(precision=2)
        >>> type_aliases = []
        >>> packed = False
        >>> packkw = None
        >>> _str = func_str(func, args, kwargs, type_aliases, packed, packkw)
        >>> result = _str
        >>> print(result)
        byte_str(1024, 'MB', precision=2)

def func_str(func, args=[], kwargs={}, type_aliases=[], packed=False,
             packkw=None, truncate=False):
    """
    string representation of function definition

    Returns:
        str: a representation of func with args, kwargs, and type_aliases

    Args:
        func (function):
        args (list): argument values (default = [])
        kwargs (dict): kwargs values (default = {})
        type_aliases (list): (default = [])
        packed (bool): (default = False)
        packkw (None): (default = None)

    Returns:
        str: func_str

    CommandLine:
        python -m utool.util_str --exec-func_str

    Example:
        >>> # ENABLE_DOCTEST
        >>> from utool.util_str import *  # NOQA
        >>> func = byte_str
        >>> args = [1024, 'MB']
        >>> kwargs = dict(precision=2)
        >>> type_aliases = []
        >>> packed = False
        >>> packkw = None
        >>> _str = func_str(func, args, kwargs, type_aliases, packed, packkw)
        >>> result = _str
        >>> print(result)
        byte_str(1024, 'MB', precision=2)
    """
    import utool as ut
    # if truncate:
    # truncatekw = {'maxlen': 20}
    # else:
    truncatekw = {}

    argrepr_list = ([] if args is None else
                    ut.get_itemstr_list(args, nl=False, truncate=truncate,
                                        truncatekw=truncatekw))
    kwrepr_list = ([] if kwargs is None else
                   ut.dict_itemstr_list(kwargs, explicit=True, nl=False,
                                        truncate=truncate,
                                        truncatekw=truncatekw))
    repr_list = argrepr_list + kwrepr_list

    argskwargs_str = ', '.join(repr_list)
    _str = '%s(%s)' % (meta_util_six.get_funcname(func), argskwargs_str)
    if packed:
        packkw_ = dict(textwidth=80, nlprefix='    ', break_words=False)
        if packkw is not None:
            packkw_.update(packkw_)
        _str = packstr(_str, **packkw_)
    return _str