Fixes to the controller text model (#17527)

* Fixes to the controller text model

* Change command line args to text type
* Make display replace undecodable bytes with replacement chars.  This
  is only a problem on pyhton3 where surrogates can enter into the msg
  but sys.stdout doesn't know how to handle them.
* Remove a deprecated playbook syntax in unicode.yml

* Fix up run_cmd to change its parameters to byte string at appropriate times.
This commit is contained in:
Toshio Kuratomi 2016-09-12 12:57:41 -07:00 committed by GitHub
parent 9868117d1f
commit bf29961947
4 changed files with 27 additions and 9 deletions

View file

@ -91,9 +91,16 @@ if __name__ == '__main__':
else:
raise
cli = mycli(sys.argv)
cli.parse()
exit_code = cli.run()
try:
args = [to_text(a, errors='surrogate_or_strict') for a in sys.argv]
except UnicodeError:
display.error('Command line args are not in utf-8, unable to continue. Ansible currently only understands utf-8')
display.display(u"The full traceback was:\n\n%s" % to_text(traceback.format_exc()))
exit_code = 6
else:
cli = mycli(args)
cli.parse()
exit_code = cli.run()
except AnsibleOptionsError as e:
cli.parser.print_help()

View file

@ -24,15 +24,26 @@ import shlex
import subprocess
import select
from ansible.compat.six import PY2
from ansible.module_utils._text import to_bytes
def run_cmd(cmd, live=False, readsize=10):
#readsize = 10
# On python2, shlex needs byte strings
if PY2:
cmd = to_bytes(cmd, errors='surrogate_or_strict')
cmdargs = shlex.split(cmd)
# subprocess should be passed byte strings. (on python2.6 it must be
# passed byte strtings)
cmdargs = [to_bytes(a, errors='surrogate_or_strict') for a in cmdargs]
p = subprocess.Popen(cmdargs, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout = ''
stderr = ''
stdout = b''
stderr = b''
rpipes = [p.stdout, p.stderr]
while True:
rfd, wfd, efd = select.select(rpipes, [], rpipes, 1)
@ -42,14 +53,14 @@ def run_cmd(cmd, live=False, readsize=10):
if live:
sys.stdout.write(dat)
stdout += dat
if dat == '':
if dat == b'':
rpipes.remove(p.stdout)
if p.stderr in rfd:
dat = os.read(p.stderr.fileno(), readsize)
stderr += dat
if live:
sys.stdout.write(dat)
if dat == '':
if dat == b'':
rpipes.remove(p.stderr)
# only break out if we've emptied the pipes, or there is nothing to
# read from and the process has finished.

View file

@ -124,7 +124,7 @@ class Display:
# Convert back to text string on python3
# We first convert to a byte string so that we get rid of
# characters that are invalid in the user's locale
msg2 = to_text(msg2, self._output_encoding(stderr=stderr))
msg2 = to_text(msg2, self._output_encoding(stderr=stderr), errors='replace')
if not stderr:
fileobj = sys.stdout

View file

@ -32,7 +32,7 @@
groups: 'ĪīĬĭ'
ansible_ssh_host: 127.0.0.1
ansible_connection: local
with_items: hostnames
with_items: "{{ hostnames }}"
- name: 'A task with unicode extra vars'
debug: var=extra_var