# Buggy code
def bin_pkg_info(path, saltenv="base"):
    """
    .. versionadded:: 2015.8.0

    Parses RPM metadata and returns a dictionary of information about the
    package (name, version, etc.).

    path
        Path to the file. Can either be an absolute path to a file on the
        minion, or a salt fileserver URL (e.g. ``salt://path/to/file.rpm``).
        If a salt fileserver URL is passed, the file will be cached to the
        minion so that it can be examined.

    saltenv : base
        Salt fileserver envrionment from which to retrieve the package. Ignored
        if ``path`` is a local file path on the minion.

    CLI Example:

    .. code-block:: bash

        salt '*' lowpkg.bin_pkg_info /root/salt-2015.5.1-2.el7.noarch.rpm
        salt '*' lowpkg.bin_pkg_info salt://salt-2015.5.1-2.el7.noarch.rpm
    """
    # If the path is a valid protocol, pull it down using cp.cache_file
    if __salt__["config.valid_fileproto"](path):
        newpath = __salt__["cp.cache_file"](path, saltenv)
        if not newpath:
            raise CommandExecutionError(
                "Unable to retrieve {0} from saltenv '{1}'".format(path, saltenv)
            )
        path = newpath
    else:
        if not os.path.exists(path):
            raise CommandExecutionError("{0} does not exist on minion".format(path))
        elif not os.path.isabs(path):
            raise SaltInvocationError("{0} does not exist on minion".format(path))

    # REPOID is not a valid tag for the rpm command. Remove it and replace it
    # with 'none'
    queryformat = salt.utils.pkg.rpm.QUERYFORMAT.replace("%{REPOID}", "none")
    output = __salt__["cmd.run_stdout"](
        ["rpm", "-qp", "--queryformat", queryformat, path],
        output_loglevel="trace",
        ignore_retcode=True,
        python_shell=False,
    )
    ret = {}
    pkginfo = salt.utils.pkg.rpm.parse_pkginfo(output, osarch=__grains__["osarch"])
    for field in pkginfo._fields:
        ret[field] = getattr(pkginfo, field)
    return ret


# Traceback (AttributeError)
[ERROR   ] An exception occurred in this state: Traceback (most recent call last):
File "/usr/lib/python2.7/site-packages/salt/state.py", line 1822, in call
**cdata['kwargs'])
File "/usr/lib/python2.7/site-packages/salt/loader.py", line 1727, in wrapper
return f(*args, **kwargs)
File "/usr/lib/python2.7/site-packages/salt/states/pkg.py", line 1300, in installed
**kwargs)
File "/usr/lib/python2.7/site-packages/salt/states/pkg.py", line 541, in _find_install_targets
source_info = __salt__['lowpkg.bin_pkg_info'](cached_path)
File "/usr/lib/python2.7/site-packages/salt/modules/rpm.py", line 120, in bin_pkg_info
for field in pkginfo._fields:
AttributeError: 'NoneType' object has no attribute '_fields'

[WARNING ] The function "module.run" is using its deprecated version and will expire in version "Fluorine".

# Fixed code
def bin_pkg_info(path, saltenv="base"):
    """
    .. versionadded:: 2015.8.0

    Parses RPM metadata and returns a dictionary of information about the
    package (name, version, etc.).

    path
        Path to the file. Can either be an absolute path to a file on the
        minion, or a salt fileserver URL (e.g. ``salt://path/to/file.rpm``).
        If a salt fileserver URL is passed, the file will be cached to the
        minion so that it can be examined.

    saltenv : base
        Salt fileserver envrionment from which to retrieve the package. Ignored
        if ``path`` is a local file path on the minion.

    CLI Example:

    .. code-block:: bash

        salt '*' lowpkg.bin_pkg_info /root/salt-2015.5.1-2.el7.noarch.rpm
        salt '*' lowpkg.bin_pkg_info salt://salt-2015.5.1-2.el7.noarch.rpm
    """
    # If the path is a valid protocol, pull it down using cp.cache_file
    if __salt__["config.valid_fileproto"](path):
        newpath = __salt__["cp.cache_file"](path, saltenv)
        if not newpath:
            raise CommandExecutionError(
                "Unable to retrieve {0} from saltenv '{1}'".format(path, saltenv)
            )
        path = newpath
    else:
        if not os.path.exists(path):
            raise CommandExecutionError("{0} does not exist on minion".format(path))
        elif not os.path.isabs(path):
            raise SaltInvocationError("{0} does not exist on minion".format(path))

    # REPOID is not a valid tag for the rpm command. Remove it and replace it
    # with 'none'
    queryformat = salt.utils.pkg.rpm.QUERYFORMAT.replace("%{REPOID}", "none")
    output = __salt__["cmd.run_stdout"](
        ["rpm", "-qp", "--queryformat", queryformat, path],
        output_loglevel="trace",
        ignore_retcode=True,
        python_shell=False,
    )
    ret = {}
    pkginfo = salt.utils.pkg.rpm.parse_pkginfo(output, osarch=__grains__["osarch"])
    try:
        for field in pkginfo._fields:
            ret[field] = getattr(pkginfo, field)
    except AttributeError:
        # pkginfo is None
        return None
    return ret