List the packages currently installed as a dict. By default, the dict
    contains versions as a comma separated string::

        {'<package_name>': '<version>[,<version>...]'}

    versions_as_list:
        If set to true, the versions are provided as a list

        {'<package_name>': ['<version>', '<version>']}

    attr:
        If a list of package attributes is specified, returned value will
        contain them in addition to version, eg.::

        {'<package_name>': [{'version' : 'version', 'arch' : 'arch'}]}

        Valid attributes are: ``epoch``, ``version``, ``release``, ``arch``,
        ``install_date``, ``install_date_time_t``.

        If ``all`` is specified, all valid attributes will be returned.

            .. versionadded:: 2018.3.0

    CLI Example:

    .. code-block:: bash

        salt '*' pkg.list_pkgs
        salt '*' pkg.list_pkgs attr=version,arch
        salt '*' pkg.list_pkgs attr='["version", "arch"]'

def list_pkgs(versions_as_list=False, **kwargs):
    '''
    List the packages currently installed as a dict. By default, the dict
    contains versions as a comma separated string::

        {'<package_name>': '<version>[,<version>...]'}

    versions_as_list:
        If set to true, the versions are provided as a list

        {'<package_name>': ['<version>', '<version>']}

    attr:
        If a list of package attributes is specified, returned value will
        contain them in addition to version, eg.::

        {'<package_name>': [{'version' : 'version', 'arch' : 'arch'}]}

        Valid attributes are: ``epoch``, ``version``, ``release``, ``arch``,
        ``install_date``, ``install_date_time_t``.

        If ``all`` is specified, all valid attributes will be returned.

            .. versionadded:: 2018.3.0

    CLI Example:

    .. code-block:: bash

        salt '*' pkg.list_pkgs
        salt '*' pkg.list_pkgs attr=version,arch
        salt '*' pkg.list_pkgs attr='["version", "arch"]'
    '''
    versions_as_list = salt.utils.data.is_true(versions_as_list)
    # not yet implemented or not applicable
    if any([salt.utils.data.is_true(kwargs.get(x))
            for x in ('removed', 'purge_desired')]):
        return {}

    attr = kwargs.get('attr')
    if attr is not None:
        attr = salt.utils.args.split_input(attr)

    contextkey = 'pkg.list_pkgs'

    if contextkey not in __context__:
        ret = {}
        cmd = ['rpm', '-qa', '--queryformat',
               salt.utils.pkg.rpm.QUERYFORMAT.replace('%{REPOID}', '(none)') + '\n']
        output = __salt__['cmd.run'](cmd,
                                     python_shell=False,
                                     output_loglevel='trace')
        for line in output.splitlines():
            pkginfo = salt.utils.pkg.rpm.parse_pkginfo(
                line,
                osarch=__grains__['osarch']
            )
            if pkginfo is not None:
                # see rpm version string rules available at https://goo.gl/UGKPNd
                pkgver = pkginfo.version
                epoch = ''
                release = ''
                if ':' in pkgver:
                    epoch, pkgver = pkgver.split(":", 1)
                if '-' in pkgver:
                    pkgver, release = pkgver.split("-", 1)
                all_attr = {
                    'epoch': epoch,
                    'version': pkgver,
                    'release': release,
                    'arch': pkginfo.arch,
                    'install_date': pkginfo.install_date,
                    'install_date_time_t': pkginfo.install_date_time_t
                }
                __salt__['pkg_resource.add_pkg'](ret, pkginfo.name, all_attr)

        for pkgname in ret:
            ret[pkgname] = sorted(ret[pkgname], key=lambda d: d['version'])

        __context__[contextkey] = ret

    return __salt__['pkg_resource.format_pkg_list'](
        __context__[contextkey],
        versions_as_list,
        attr)