def _get_full_name(code_name: str, proj=None) ->str:
    """
    Return the label of an object retrieved by name

    If a :class:`Project` has been provided, code names can be converted into
    labels for plotting. This function is different to `framework.get_label()` though,
    because it supports converting population names to labels as well (this information is
    in the project's data, not in the framework), and it also supports converting
    link syntax (e.g. `sus:vac`) into full names as well. Note also that this means that the strings
    returned by `_get_full_name` can be as specific as necessary for plotting.

    :param code_name: The code name for a variable (e.g. `'sus'`, `'pris'`, `'sus:vac'`)
    :param proj: Optionally specify a :class:`Project` instance
    :return: If a project was provided, returns the full name. Otherwise, just returns the code name
    """
    if proj is None:
        return code_name
    if code_name in proj.data.pops:
        return proj.data.pops[code_name]['label']
    if ':' in code_name:
        output_tokens = code_name.split(':')
        if len(output_tokens) == 2:
            output_tokens.append('')
        src, dest, par = output_tokens
        if dest == 'flow':
            if src in proj.framework:
                return '{0} (flow)'.format(proj.framework.get_label(src))
            else:
                return '{0} (flow)'.format(src)
        if src and src in proj.framework:
            src = proj.framework.get_label(src)
        if dest and dest in proj.framework:
            dest = proj.framework.get_label(dest)
        if par and par in proj.framework:
            par = proj.framework.get_label(par)
        full = 'Flow'
        if src:
            full += ' from {}'.format(src)
        if dest:
            full += ' to {}'.format(dest)
        if par:
            full += ' ({})'.format(par)
        return full
    elif code_name in proj.framework:
        return proj.framework.get_label(code_name)
    else:
        return code_name
