# Buggy code
def get_file(
    self, path, dest="", makedirs=False, saltenv="base", gzip=None, cachedir=None
):
    """
    Get a single file from the salt-master
    path must be a salt server location, aka, salt://path/to/file, if
    dest is omitted, then the downloaded file will be placed in the minion
    cache
    """
    path, senv = salt.utils.url.split_env(path)
    if senv:
        saltenv = senv

    if not salt.utils.is_windows():
        hash_server, stat_server = self.hash_and_stat_file(path, saltenv)
        try:
            mode_server = stat_server[0]
        except (IndexError, TypeError):
            mode_server = None
    else:
        hash_server = self.hash_file(path, saltenv)
        mode_server = None

    # Check if file exists on server, before creating files and
    # directories
    if hash_server == "":
        log.debug("Could not find file '%s' in saltenv '%s'", path, saltenv)
        return False

    # Hash compare local copy with master and skip download
    # if no difference found.
    dest2check = dest
    if not dest2check:
        rel_path = self._check_proto(path)

        log.debug(
            "In saltenv '%s', looking at rel_path '%s' to resolve '%s'",
            saltenv,
            rel_path,
            path,
        )
        with self._cache_loc(rel_path, saltenv, cachedir=cachedir) as cache_dest:
            dest2check = cache_dest

    log.debug(
        "In saltenv '%s', ** considering ** path '%s' to resolve '%s'",
        saltenv,
        dest2check,
        path,
    )

    if dest2check and os.path.isfile(dest2check):
        if not salt.utils.is_windows():
            hash_local, stat_local = self.hash_and_stat_file(dest2check, saltenv)
            try:
                mode_local = stat_local[0]
            except IndexError:
                mode_local = None
        else:
            hash_local = self.hash_file(dest2check, saltenv)
            mode_local = None

        if hash_local == hash_server:
            if not salt.utils.is_windows():
                if mode_server is None:
                    log.debug("No file mode available for '%s'", path)
                elif mode_local is None:
                    log.debug("No file mode available for '%s'", dest2check)
                else:
                    if mode_server == mode_local:
                        log.info(
                            "Fetching file from saltenv '%s', "
                            "** skipped ** latest already in cache "
                            "'%s', mode up-to-date",
                            saltenv,
                            path,
                        )
                    else:
                        try:
                            os.chmod(dest2check, mode_server)
                            log.info(
                                "Fetching file from saltenv '%s', "
                                "** updated ** latest already in cache, "
                                "'%s', mode updated from %s to %s",
                                saltenv,
                                path,
                                salt.utils.st_mode_to_octal(mode_local),
                                salt.utils.st_mode_to_octal(mode_server),
                            )
                        except OSError as exc:
                            log.warning("Failed to chmod %s: %s", dest2check, exc)
                # We may not have been able to check/set the mode, but we
                # don't want to re-download the file because of a failure
                # in mode checking. Return the cached path.
                return dest2check
            else:
                log.info(
                    "Fetching file from saltenv '%s', ** skipped ** "
                    "latest already in cache '%s'",
                    saltenv,
                    path,
                )
                return dest2check

    log.debug("Fetching file from saltenv '%s', ** attempting ** '%s'", saltenv, path)
    d_tries = 0
    transport_tries = 0
    path = self._check_proto(path)
    load = {"path": path, "saltenv": saltenv, "cmd": "_serve_file"}
    if gzip:
        gzip = int(gzip)
        load["gzip"] = gzip

    fn_ = None
    if dest:
        destdir = os.path.dirname(dest)
        if not os.path.isdir(destdir):
            if makedirs:
                os.makedirs(destdir)
            else:
                return False
        fn_ = salt.utils.fopen(dest, "wb+")
    else:
        log.debug("No dest file found")

    while True:
        if not fn_:
            load["loc"] = 0
        else:
            load["loc"] = fn_.tell()
        data = self.channel.send(load, raw=True)
        if six.PY3:
            # Sometimes the source is local (eg when using
            # 'salt.filesystem.FSChan'), in which case the keys are
            # already strings. Sometimes the source is remote, in which
            # case the keys are bytes due to raw mode. Standardize on
            # strings for the top-level keys to simplify things.
            data = decode_dict_keys_to_str(data)
        try:
            if not data["data"]:
                if not fn_ and data["dest"]:
                    # This is a 0 byte file on the master
                    with self._cache_loc(
                        data["dest"], saltenv, cachedir=cachedir
                    ) as cache_dest:
                        dest = cache_dest
                        with salt.utils.fopen(cache_dest, "wb+") as ofile:
                            ofile.write(data["data"])
                if "hsum" in data and d_tries < 3:
                    # Master has prompted a file verification, if the
                    # verification fails, re-download the file. Try 3 times
                    d_tries += 1
                    hsum = salt.utils.get_hash(
                        dest, salt.utils.to_str(data.get("hash_type", b"md5"))
                    )
                    if hsum != data["hsum"]:
                        log.warning(
                            "Bad download of file %s, attempt %d of 3", path, d_tries
                        )
                        continue
                break
            if not fn_:
                with self._cache_loc(
                    data["dest"], saltenv, cachedir=cachedir
                ) as cache_dest:
                    dest = cache_dest
                    # If a directory was formerly cached at this path, then
                    # remove it to avoid a traceback trying to write the file
                    if os.path.isdir(dest):
                        salt.utils.rm_rf(dest)
                    fn_ = salt.utils.fopen(dest, "wb+")
            if data.get("gzip", None):
                data = salt.utils.gzip_util.uncompress(data["data"])
            else:
                data = data["data"]
            fn_.write(data)
        except (TypeError, KeyError) as exc:
            try:
                data_type = type(data).__name__
            except AttributeError:
                # Shouldn't happen, but don't let this cause a traceback.
                data_type = str(type(data))
            transport_tries += 1
            log.warning(
                "Data transport is broken, got: %s, type: %s, "
                "exception: %s, attempt %d of 3",
                data,
                data_type,
                exc,
                transport_tries,
            )
            self._refresh_channel()
            if transport_tries > 3:
                log.error(
                    "Data transport is broken, got: %s, type: %s, "
                    "exception: %s, retry attempts exhausted",
                    data,
                    data_type,
                    exc,
                )
                break

    if fn_:
        fn_.close()
        log.info("Fetching file from saltenv '%s', ** done ** '%s'", saltenv, path)
    else:
        log.debug("In saltenv '%s', we are ** missing ** the file '%s'", saltenv, path)

    if not salt.utils.is_windows():
        if mode_server is not None:
            try:
                if os.stat(dest).st_mode != mode_server:
                    try:
                        os.chmod(dest, mode_server)
                        log.info(
                            "Fetching file from saltenv '%s', "
                            "** done ** '%s', mode set to %s",
                            saltenv,
                            path,
                            salt.utils.st_mode_to_octal(mode_server),
                        )
                    except OSError:
                        log.warning("Failed to chmod %s: %s", dest, exc)
            except OSError:
                pass
    return dest


# Traceback (AttributeError)
root@nmadhok.local:~/salt/salt# salt-call state.sls sample.state test=true
[WARNING ] Key 'file_ignore_glob' with value None has an invalid type of NoneType, a list or basestring is required for this value
[WARNING ] Key 'file_ignore_regex' with value None has an invalid type of NoneType, a list or basestring is required for this value
[INFO    ] Loading fresh modules for state activity
[ERROR   ] An un-handled exception was caught by salt's global exception handler:
AttributeError: 'bool' object has no attribute 'get'
Traceback (most recent call last):
File "/usr/bin/salt-call", line 11, in <module>
salt_call()
File "/usr/lib/python2.6/site-packages/salt/scripts.py", line 352, in salt_call
client.run()
File "/usr/lib/python2.6/site-packages/salt/cli/call.py", line 58, in run
caller.run()
File "/usr/lib/python2.6/site-packages/salt/cli/caller.py", line 134, in run
ret = self.call()
File "/usr/lib/python2.6/site-packages/salt/cli/caller.py", line 197, in call
ret['return'] = func(*args, **kwargs)
File "/usr/lib/python2.6/site-packages/salt/modules/state.py", line 985, in sls
high_, errors = st_.render_highstate({saltenv: mods})
File "/usr/lib/python2.6/site-packages/salt/state.py", line 3149, in render_highstate
sls, saltenv, mods, matches)
File "/usr/lib/python2.6/site-packages/salt/state.py", line 2803, in render_state
state_data = self.client.get_state(sls, saltenv)
File "/usr/lib/python2.6/site-packages/salt/fileclient.py", line 394, in get_state
dest = self.cache_file(path, saltenv, cachedir=cachedir)
File "/usr/lib/python2.6/site-packages/salt/fileclient.py", line 177, in cache_file
return self.get_url(path, '', True, saltenv, cachedir=cachedir)
File "/usr/lib/python2.6/site-packages/salt/fileclient.py", line 475, in get_url
url, dest, makedirs, saltenv, cachedir=cachedir)
File "/usr/lib/python2.6/site-packages/salt/fileclient.py", line 972, in get_file
hash_server, stat_server = self.hash_and_stat_file(path, saltenv)
File "/usr/lib/python2.6/site-packages/salt/fileclient.py", line 1282, in hash_and_stat_file
stat_result = fnd.get('stat')
AttributeError: 'bool' object has no attribute 'get'
Traceback (most recent call last):
File "/usr/bin/salt-call", line 11, in <module>
salt_call()
File "/usr/lib/python2.6/site-packages/salt/scripts.py", line 352, in salt_call
client.run()
File "/usr/lib/python2.6/site-packages/salt/cli/call.py", line 58, in run
caller.run()
File "/usr/lib/python2.6/site-packages/salt/cli/caller.py", line 134, in run
ret = self.call()
File "/usr/lib/python2.6/site-packages/salt/cli/caller.py", line 197, in call
ret['return'] = func(*args, **kwargs)
File "/usr/lib/python2.6/site-packages/salt/modules/state.py", line 985, in sls
high_, errors = st_.render_highstate({saltenv: mods})
File "/usr/lib/python2.6/site-packages/salt/state.py", line 3149, in render_highstate
sls, saltenv, mods, matches)
File "/usr/lib/python2.6/site-packages/salt/state.py", line 2803, in render_state
state_data = self.client.get_state(sls, saltenv)
File "/usr/lib/python2.6/site-packages/salt/fileclient.py", line 394, in get_state
dest = self.cache_file(path, saltenv, cachedir=cachedir)
File "/usr/lib/python2.6/site-packages/salt/fileclient.py", line 177, in cache_file
return self.get_url(path, '', True, saltenv, cachedir=cachedir)
File "/usr/lib/python2.6/site-packages/salt/fileclient.py", line 475, in get_url
url, dest, makedirs, saltenv, cachedir=cachedir)
File "/usr/lib/python2.6/site-packages/salt/fileclient.py", line 972, in get_file
hash_server, stat_server = self.hash_and_stat_file(path, saltenv)
File "/usr/lib/python2.6/site-packages/salt/fileclient.py", line 1282, in hash_and_stat_file
stat_result = fnd.get('stat')
AttributeError: 'bool' object has no attribute 'get'

# Fixed code
def get_file(
    self, path, dest="", makedirs=False, saltenv="base", gzip=None, cachedir=None
):
    """
    Get a single file from the salt-master
    path must be a salt server location, aka, salt://path/to/file, if
    dest is omitted, then the downloaded file will be placed in the minion
    cache
    """
    path, senv = salt.utils.url.split_env(path)
    if senv:
        saltenv = senv

    if not salt.utils.is_windows():
        hash_server, stat_server = self.hash_and_stat_file(path, saltenv)
        try:
            mode_server = stat_server[0]
        except (IndexError, TypeError):
            mode_server = None
    else:
        hash_server = self.hash_file(path, saltenv)
        mode_server = None

    # Check if file exists on server, before creating files and
    # directories
    if hash_server == "":
        log.debug("Could not find file '%s' in saltenv '%s'", path, saltenv)
        return False

    # Hash compare local copy with master and skip download
    # if no difference found.
    dest2check = dest
    if not dest2check:
        rel_path = self._check_proto(path)

        log.debug(
            "In saltenv '%s', looking at rel_path '%s' to resolve '%s'",
            saltenv,
            rel_path,
            path,
        )
        with self._cache_loc(rel_path, saltenv, cachedir=cachedir) as cache_dest:
            dest2check = cache_dest

    log.debug(
        "In saltenv '%s', ** considering ** path '%s' to resolve '%s'",
        saltenv,
        dest2check,
        path,
    )

    if dest2check and os.path.isfile(dest2check):
        if not salt.utils.is_windows():
            hash_local, stat_local = self.hash_and_stat_file(dest2check, saltenv)
            try:
                mode_local = stat_local[0]
            except (IndexError, TypeError):
                mode_local = None
        else:
            hash_local = self.hash_file(dest2check, saltenv)
            mode_local = None

        if hash_local == hash_server:
            if not salt.utils.is_windows():
                if mode_server is None:
                    log.debug("No file mode available for '%s'", path)
                elif mode_local is None:
                    log.debug("No file mode available for '%s'", dest2check)
                else:
                    if mode_server == mode_local:
                        log.info(
                            "Fetching file from saltenv '%s', "
                            "** skipped ** latest already in cache "
                            "'%s', mode up-to-date",
                            saltenv,
                            path,
                        )
                    else:
                        try:
                            os.chmod(dest2check, mode_server)
                            log.info(
                                "Fetching file from saltenv '%s', "
                                "** updated ** latest already in cache, "
                                "'%s', mode updated from %s to %s",
                                saltenv,
                                path,
                                salt.utils.st_mode_to_octal(mode_local),
                                salt.utils.st_mode_to_octal(mode_server),
                            )
                        except OSError as exc:
                            log.warning("Failed to chmod %s: %s", dest2check, exc)
                # We may not have been able to check/set the mode, but we
                # don't want to re-download the file because of a failure
                # in mode checking. Return the cached path.
                return dest2check
            else:
                log.info(
                    "Fetching file from saltenv '%s', ** skipped ** "
                    "latest already in cache '%s'",
                    saltenv,
                    path,
                )
                return dest2check

    log.debug("Fetching file from saltenv '%s', ** attempting ** '%s'", saltenv, path)
    d_tries = 0
    transport_tries = 0
    path = self._check_proto(path)
    load = {"path": path, "saltenv": saltenv, "cmd": "_serve_file"}
    if gzip:
        gzip = int(gzip)
        load["gzip"] = gzip

    fn_ = None
    if dest:
        destdir = os.path.dirname(dest)
        if not os.path.isdir(destdir):
            if makedirs:
                os.makedirs(destdir)
            else:
                return False
        fn_ = salt.utils.fopen(dest, "wb+")
    else:
        log.debug("No dest file found")

    while True:
        if not fn_:
            load["loc"] = 0
        else:
            load["loc"] = fn_.tell()
        data = self.channel.send(load, raw=True)
        if six.PY3:
            # Sometimes the source is local (eg when using
            # 'salt.filesystem.FSChan'), in which case the keys are
            # already strings. Sometimes the source is remote, in which
            # case the keys are bytes due to raw mode. Standardize on
            # strings for the top-level keys to simplify things.
            data = decode_dict_keys_to_str(data)
        try:
            if not data["data"]:
                if not fn_ and data["dest"]:
                    # This is a 0 byte file on the master
                    with self._cache_loc(
                        data["dest"], saltenv, cachedir=cachedir
                    ) as cache_dest:
                        dest = cache_dest
                        with salt.utils.fopen(cache_dest, "wb+") as ofile:
                            ofile.write(data["data"])
                if "hsum" in data and d_tries < 3:
                    # Master has prompted a file verification, if the
                    # verification fails, re-download the file. Try 3 times
                    d_tries += 1
                    hsum = salt.utils.get_hash(
                        dest, salt.utils.to_str(data.get("hash_type", b"md5"))
                    )
                    if hsum != data["hsum"]:
                        log.warning(
                            "Bad download of file %s, attempt %d of 3", path, d_tries
                        )
                        continue
                break
            if not fn_:
                with self._cache_loc(
                    data["dest"], saltenv, cachedir=cachedir
                ) as cache_dest:
                    dest = cache_dest
                    # If a directory was formerly cached at this path, then
                    # remove it to avoid a traceback trying to write the file
                    if os.path.isdir(dest):
                        salt.utils.rm_rf(dest)
                    fn_ = salt.utils.fopen(dest, "wb+")
            if data.get("gzip", None):
                data = salt.utils.gzip_util.uncompress(data["data"])
            else:
                data = data["data"]
            fn_.write(data)
        except (TypeError, KeyError) as exc:
            try:
                data_type = type(data).__name__
            except AttributeError:
                # Shouldn't happen, but don't let this cause a traceback.
                data_type = str(type(data))
            transport_tries += 1
            log.warning(
                "Data transport is broken, got: %s, type: %s, "
                "exception: %s, attempt %d of 3",
                data,
                data_type,
                exc,
                transport_tries,
            )
            self._refresh_channel()
            if transport_tries > 3:
                log.error(
                    "Data transport is broken, got: %s, type: %s, "
                    "exception: %s, retry attempts exhausted",
                    data,
                    data_type,
                    exc,
                )
                break

    if fn_:
        fn_.close()
        log.info("Fetching file from saltenv '%s', ** done ** '%s'", saltenv, path)
    else:
        log.debug("In saltenv '%s', we are ** missing ** the file '%s'", saltenv, path)

    if not salt.utils.is_windows():
        if mode_server is not None:
            try:
                if os.stat(dest).st_mode != mode_server:
                    try:
                        os.chmod(dest, mode_server)
                        log.info(
                            "Fetching file from saltenv '%s', "
                            "** done ** '%s', mode set to %s",
                            saltenv,
                            path,
                            salt.utils.st_mode_to_octal(mode_server),
                        )
                    except OSError:
                        log.warning("Failed to chmod %s: %s", dest, exc)
            except OSError:
                pass
    return dest