# Buggy code
def _file_transport_command(self, in_path, out_path, sftp_action):
    # scp and sftp require square brackets for IPv6 addresses, but
    # accept them for hostnames and IPv4 addresses too.
    host = "[%s]" % self.host

    smart_methods = ["sftp", "scp", "piped"]

    # Windows does not support dd so we cannot use the piped method
    if getattr(self._shell, "_IS_WINDOWS", False):
        smart_methods.remove("piped")

    # Transfer methods to try
    methods = []

    # Use the transfer_method option if set, otherwise use scp_if_ssh
    ssh_transfer_method = self._play_context.ssh_transfer_method
    if ssh_transfer_method is not None:
        if not (ssh_transfer_method in ("smart", "sftp", "scp", "piped")):
            raise AnsibleOptionsError(
                "transfer_method needs to be one of [smart|sftp|scp|piped]"
            )
        if ssh_transfer_method == "smart":
            methods = smart_methods
        else:
            methods = [ssh_transfer_method]
    else:
        # since this can be a non-bool now, we need to handle it correctly
        scp_if_ssh = C.DEFAULT_SCP_IF_SSH
        if not isinstance(scp_if_ssh, bool):
            scp_if_ssh = scp_if_ssh.lower()
            if scp_if_ssh in BOOLEANS:
                scp_if_ssh = boolean(scp_if_ssh, strict=False)
            elif scp_if_ssh != "smart":
                raise AnsibleOptionsError(
                    "scp_if_ssh needs to be one of [smart|True|False]"
                )
        if scp_if_ssh == "smart":
            methods = smart_methods
        elif scp_if_ssh is True:
            methods = ["scp"]
        else:
            methods = ["sftp"]

    for method in methods:
        returncode = stdout = stderr = None
        if method == "sftp":
            cmd = self._build_command(
                self.get_option("sftp_executable"), to_bytes(host)
            )
            in_data = "{0} {1} {2}\n".format(
                sftp_action, shlex_quote(in_path), shlex_quote(out_path)
            )
            in_data = to_bytes(in_data, nonstring="passthru")
            (returncode, stdout, stderr) = self._bare_run(cmd, in_data, checkrc=False)
        elif method == "scp":
            scp = self.get_option("scp_executable")

            if sftp_action == "get":
                cmd = self._build_command(
                    scp, "{0}:{1}".format(host, self._shell.quote(in_path)), out_path
                )
            else:
                cmd = self._build_command(
                    scp, in_path, "{0}:{1}".format(host, self._shell.quote(out_path))
                )
            in_data = None
            (returncode, stdout, stderr) = self._bare_run(cmd, in_data, checkrc=False)
        elif method == "piped":
            if sftp_action == "get":
                # we pass sudoable=False to disable pty allocation, which
                # would end up mixing stdout/stderr and screwing with newlines
                (returncode, stdout, stderr) = self.exec_command(
                    "dd if=%s bs=%s" % (in_path, BUFSIZE), sudoable=False
                )
                with open(
                    to_bytes(out_path, errors="surrogate_or_strict"), "wb+"
                ) as out_file:
                    out_file.write(stdout)
            else:
                with open(to_bytes(in_path, errors="surrogate_or_strict"), "rb") as f:
                    in_data = to_bytes(f.read(), nonstring="passthru")
                if not in_data:
                    count = " count=0"
                else:
                    count = ""
                (returncode, stdout, stderr) = self.exec_command(
                    "dd of=%s bs=%s%s" % (out_path, BUFSIZE, count),
                    in_data=in_data,
                    sudoable=False,
                )

        # Check the return code and rollover to next method if failed
        if returncode == 0:
            return (returncode, stdout, stderr)
        else:
            # If not in smart mode, the data will be printed by the raise below
            if len(methods) > 1:
                display.warning(
                    "%s transfer mechanism failed on %s. Use ANSIBLE_DEBUG=1 to see detailed information"
                    % (method, host)
                )
                display.debug("%s" % to_text(stdout))
                display.debug("%s" % to_text(stderr))

    if returncode == 255:
        raise AnsibleConnectionFailure(
            "Failed to connect to the host via %s: %s" % (method, to_native(stderr))
        )
    else:
        raise AnsibleError(
            "failed to transfer file to %s %s:\n%s\n%s"
            % (
                to_native(in_path),
                to_native(out_path),
                to_native(stdout),
                to_native(stderr),
            )
        )


# Traceback (UnicodeDecodeError)
TASK [stat] *************************************************************************************************************************************************************
task path: /home/jenkins/playbook.yml:3
Friday 14 June 2019  10:36:17 +0200 (0:00:00.170)       0:00:00.170 ***********
Using module file /jenkins/test/ansible/lib/python2.6/site-packages/ansible/modules/files/stat.py
<server> ESTABLISH SSH CONNECTION FOR USER: myuser
<server> SSH: EXEC ssh -o PreferredAuthentications=publickey -o StrictHostKeyChecking=no -o Port=22 -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=myuser -o ConnectTimeout=20 server '/bin/sh -c '"'"'/usr/bin/python &amp;&amp; sleep 0'"'"''
<server> (1, '\n{"msg": "Permission denied", "failed": true, "exception": "  File \\"/tmp/ansible_Vvkdbf/ansible_module_stat.py\\", line 476, in main\\n    st = os.lstat(b_path)\\n", "invocation": {"module_args": {"checksum_algorithm": "sha1", "get_checksum": true, "follow": false, "path": "/home/anotheruser/lvi", "get_md5": null, "get_mime": true, "get_attributes": true}}}\n', "ATTENTION:\nQuiconque acc\xc3\xa9derait ou tenterait d'acc\xc3\xa9der \xc3\xa0 ce syst\xc3\xa8me.\n\n")
The full traceback is:
Traceback (most recent call last):
File "/jenkins/test/ansible/lib/python2.6/site-packages/ansible/executor/task_executor.py", line 139, in run
res = self._execute()
File "/jenkins/test/ansible/lib/python2.6/site-packages/ansible/executor/task_executor.py", line 584, in _execute
result = self._handler.run(task_vars=variables)
File "/jenkins/test/ansible/lib/python2.6/site-packages/ansible/plugins/action/normal.py", line 46, in run
result = merge_hash(result, self._execute_module(task_vars=task_vars, wrap_async=wrap_async))
File "/jenkins/test/ansible/lib/python2.6/site-packages/ansible/plugins/action/__init__.py", line 853, in _execute_module
res = self._low_level_execute_command(cmd, sudoable=sudoable, in_data=in_data)
File "/jenkins/test/ansible/lib/python2.6/site-packages/ansible/plugins/action/__init__.py", line 960, in _low_level_execute_command
rc, stdout, stderr = self._connection.exec_command(cmd, in_data=in_data, sudoable=sudoable)
File "/jenkins/test/ansible/lib/python2.6/site-packages/ansible/plugins/connection/ssh.py", line 1080, in exec_command
(returncode, stdout, stderr) = self._run(cmd, in_data, sudoable=sudoable)
File "/jenkins/test/ansible/lib/python2.6/site-packages/ansible/plugins/connection/ssh.py", line 354, in wrapped
_handle_error(remaining_retries, cmd[0], return_tuple, self._play_context.no_log, self.host)
File "/jenkins/test/ansible/lib/python2.6/site-packages/ansible/plugins/connection/ssh.py", line 307, in _handle_error
display.vvv(msg, host=host)
File "/jenkins/test/ansible/lib/python2.6/site-packages/ansible/utils/display.py", line 183, in vvv
return self.verbose(msg, host=host, caplevel=2)
File "/jenkins/test/ansible/lib/python2.6/site-packages/ansible/utils/display.py", line 206, in verbose
self.display("<%s> %s" % (host, msg), color=C.COLOR_VERBOSE, screen_only=True)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 63: ordinal not in range(128)

fatal: [server]: FAILED! => {
"msg": "Unexpected failure during module execution.",
"stdout": ""
}

# Fixed code
def _file_transport_command(self, in_path, out_path, sftp_action):
    # scp and sftp require square brackets for IPv6 addresses, but
    # accept them for hostnames and IPv4 addresses too.
    host = "[%s]" % self.host

    smart_methods = ["sftp", "scp", "piped"]

    # Windows does not support dd so we cannot use the piped method
    if getattr(self._shell, "_IS_WINDOWS", False):
        smart_methods.remove("piped")

    # Transfer methods to try
    methods = []

    # Use the transfer_method option if set, otherwise use scp_if_ssh
    ssh_transfer_method = self._play_context.ssh_transfer_method
    if ssh_transfer_method is not None:
        if not (ssh_transfer_method in ("smart", "sftp", "scp", "piped")):
            raise AnsibleOptionsError(
                "transfer_method needs to be one of [smart|sftp|scp|piped]"
            )
        if ssh_transfer_method == "smart":
            methods = smart_methods
        else:
            methods = [ssh_transfer_method]
    else:
        # since this can be a non-bool now, we need to handle it correctly
        scp_if_ssh = C.DEFAULT_SCP_IF_SSH
        if not isinstance(scp_if_ssh, bool):
            scp_if_ssh = scp_if_ssh.lower()
            if scp_if_ssh in BOOLEANS:
                scp_if_ssh = boolean(scp_if_ssh, strict=False)
            elif scp_if_ssh != "smart":
                raise AnsibleOptionsError(
                    "scp_if_ssh needs to be one of [smart|True|False]"
                )
        if scp_if_ssh == "smart":
            methods = smart_methods
        elif scp_if_ssh is True:
            methods = ["scp"]
        else:
            methods = ["sftp"]

    for method in methods:
        returncode = stdout = stderr = None
        if method == "sftp":
            cmd = self._build_command(
                self.get_option("sftp_executable"), to_bytes(host)
            )
            in_data = "{0} {1} {2}\n".format(
                sftp_action, shlex_quote(in_path), shlex_quote(out_path)
            )
            in_data = to_bytes(in_data, nonstring="passthru")
            (returncode, stdout, stderr) = self._bare_run(cmd, in_data, checkrc=False)
        elif method == "scp":
            scp = self.get_option("scp_executable")

            if sftp_action == "get":
                cmd = self._build_command(
                    scp, "{0}:{1}".format(host, self._shell.quote(in_path)), out_path
                )
            else:
                cmd = self._build_command(
                    scp, in_path, "{0}:{1}".format(host, self._shell.quote(out_path))
                )
            in_data = None
            (returncode, stdout, stderr) = self._bare_run(cmd, in_data, checkrc=False)
        elif method == "piped":
            if sftp_action == "get":
                # we pass sudoable=False to disable pty allocation, which
                # would end up mixing stdout/stderr and screwing with newlines
                (returncode, stdout, stderr) = self.exec_command(
                    "dd if=%s bs=%s" % (in_path, BUFSIZE), sudoable=False
                )
                with open(
                    to_bytes(out_path, errors="surrogate_or_strict"), "wb+"
                ) as out_file:
                    out_file.write(stdout)
            else:
                with open(to_bytes(in_path, errors="surrogate_or_strict"), "rb") as f:
                    in_data = to_bytes(f.read(), nonstring="passthru")
                if not in_data:
                    count = " count=0"
                else:
                    count = ""
                (returncode, stdout, stderr) = self.exec_command(
                    "dd of=%s bs=%s%s" % (out_path, BUFSIZE, count),
                    in_data=in_data,
                    sudoable=False,
                )

        # Check the return code and rollover to next method if failed
        if returncode == 0:
            return (returncode, stdout, stderr)
        else:
            # If not in smart mode, the data will be printed by the raise below
            if len(methods) > 1:
                display.warning(
                    "%s transfer mechanism failed on %s. Use ANSIBLE_DEBUG=1 to see detailed information"
                    % (method, host)
                )
                display.debug("%s" % to_text(stdout))
                display.debug("%s" % to_text(stderr))

    if returncode == 255:
        raise AnsibleConnectionFailure(
            "Failed to connect to the host via %s: %s" % (method, to_native(stderr))
        )
    else:
        raise AnsibleError(
            "failed to transfer file to %s %s:\n%s\n%s"
            % (
                to_native(in_path),
                to_native(out_path),
                to_native(stdout),
                to_native(stderr),
            )
        )