tomerfiliba / plumbum

Plumbum: Shell Combinators
https://plumbum.readthedocs.io
MIT License
2.8k stars 182 forks source link

session().run() breaks when the command output does not ends with newline #494

Open deniswvieira opened 4 years ago

deniswvieira commented 4 years ago

python 2.7 plumbum 1.6.8

Command which output does not ends with '\n' breaks running with session().run().

The problem occurs at the method communicate() of plumbum.machines.session.SessionPopen on the line 144:

class SessionPopen
   . . .
    def communicate():
        . . .
        self.returncode = int(stdout.pop(-1))

Since the command does not returns '\n', and plumbum echoes the returncode after the command output (full_cmd += "echo $? ; echo '%s'" % (marker, )), the readline interpretes the returncode as a part of the command output.

A simple snnipet that breaks:

from plumbum import local

session = local.session()
session.run('echo -n abc')

Plumbum will generate the following command:

echo -n abc ; echo $? ; echo \'--.END648391697.571.--\' ; echo \'--.END648391697.571.--\' 1>&2

And it's output will be (before trying to get the retcode and raising the Exception):

abc0
'--.END648391697.571.--'
'--.END648391697.571.--'

Here is the traceback:

In [37]: s.run('echo -n abc')
---------------------------------------------------------------------------
ProcessExecutionError                     Traceback (most recent call last)
<ipython-input-37-f917de1405c5> in <module>()
----> 1 s.run('echo -n abc')

/usr/local/lib/python2.7/dist-packages/plumbum/machines/session.pyc in run(self, cmd, retcode)
    275         :returns: A tuple of (return code, stdout, stderr)
    276         """
--> 277         return run_proc(self.popen(cmd), retcode)

/usr/local/lib/python2.7/dist-packages/plumbum/commands/processes.pyc in run_proc(proc, retcode, timeout)
    245         stderr = stderr.decode(proc.custom_encoding, "ignore")
    246 
--> 247     return _check_process(proc, retcode, timeout, stdout, stderr)
    248 
    249 

/usr/local/lib/python2.7/dist-packages/plumbum/commands/processes.pyc in _check_process(proc, retcode, timeout, stdout, stderr)
     21 #===================================================================================================
     22 def _check_process(proc, retcode, timeout, stdout, stderr):
---> 23     proc.verify(retcode, timeout, stdout, stderr)
     24     return proc.returncode, stdout, stderr
     25 

/usr/local/lib/python2.7/dist-packages/plumbum/machines/base.pyc in verify(self, retcode, timeout, stdout, stderr)
     24                 raise ProcessExecutionError(
     25                     getattr(self, "argv", None), self.returncode, stdout,
---> 26                     stderr)
     27 
     28 

ProcessExecutionError: Unexpected exit code: Unknown
Command line: | e c h o ' ' - n ' ' a b c ' ' ';' ' ' e c h o ' ' '$' '?' ' ' ';' ' ' e c h o ' ' ''"'"'' - - . E N D 1 6 2 0 4 5 9 5 7 . 7 3 1 . - - ''"'"'' ' ' ';' ' ' e c h o ' ' ''"'"'' - - . E N D 1 6 2 0 4 5 9 5 7 . 7 3 1 . - - ''"'"'' ' ' 1 '>' '&' 2