def latest_version(*names, **kwargs):
    """
    Return the latest version of the named package available for upgrade or
    installation. If more than one package name is specified, a dict of
    name/version pairs is returned.

    If the latest version of a given package is already installed, an empty
    string will be returned for that package.

    A specific repo can be requested using the ``fromrepo`` keyword argument.

    cache_valid_time

        .. versionadded:: 2016.11.0

        Skip refreshing the package database if refresh has already occurred within
        <value> seconds

    CLI Example:

    .. code-block:: bash

        salt '*' pkg.latest_version <package name>
        salt '*' pkg.latest_version <package name> fromrepo=unstable
        salt '*' pkg.latest_version <package1> <package2> <package3> ...
    """
    refresh = salt.utils.data.is_true(kwargs.pop("refresh", True))
    show_installed = salt.utils.data.is_true(kwargs.pop("show_installed", False))
    if "repo" in kwargs:
        raise SaltInvocationError(
            "The 'repo' argument is invalid, use 'fromrepo' instead"
        )
    fromrepo = kwargs.pop("fromrepo", None)
    cache_valid_time = kwargs.pop("cache_valid_time", 0)

    if not names:
        return ""
    ret = {}
    # Initialize the dict with empty strings
    for name in names:
        ret[name] = ""
    pkgs = list_pkgs(versions_as_list=True)
    repo = ["-o", "APT::Default-Release={}".format(fromrepo)] if fromrepo else None

    # Refresh before looking for the latest version available
    if refresh:
        refresh_db(cache_valid_time)

    for name in names:
        cmd = ["apt-cache", "-q", "policy", name]
        if repo is not None:
            cmd.extend(repo)
        out = _call_apt(cmd, scope=False)

        candidate = ""
        for line in salt.utils.itertools.split(out["stdout"], "\n"):
            if "Candidate" in line:
                comps = line.split()
                if len(comps) >= 2:
                    candidate = comps[-1]
                    if candidate.lower() == "(none)":
                        candidate = ""
                break

        installed = pkgs.get(name, [])
        if not installed:
            ret[name] = candidate
        elif installed and show_installed:
            ret[name] = candidate
        elif candidate:
            # If there are no installed versions that are greater than or equal
            # to the install candidate, then the candidate is an upgrade, so
            # add it to the return dict
            if not any(
                salt.utils.versions.compare(
                    ver1=x, oper=">=", ver2=candidate, cmp_func=version_cmp
                )
                for x in installed
            ):
                ret[name] = candidate

    # Return a string if only one package name passed
    if len(names) == 1:
        return ret[names[0]]
    return ret