Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions tests/test_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -940,6 +940,50 @@ async def test():


class Test_UV_Process(_TestProcess, tb.UVTestCase):
@unittest.skipIf(sys.platform != "win32", "problem is windows related only")
def test_windows_issue_153(self):
"""Winloop issue 153 is related to bringing back the shlex parser
which because there is a different system involved from regular
python subprocess's system to prevent the libuv library
from doing something worse and needing to change up more code.

SEE: https://github.com/Vizonex/Winloop/issues/153
"""

async def test():
CMD = 'python -c "import sys; print(\'hi\')"'
proc = await asyncio.create_subprocess_shell(
CMD,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE,
)

out, err = await proc.communicate()
assert out == b"hi\r\n"
assert err == b''
assert proc.returncode == 0
self.loop.run_until_complete(test())

@unittest.skipIf(sys.platform != "win32", "problem is windows related only")
def test_windows_issue_153_bytes(self):
"""Winloop issue 153 is related to bringing back the shlex parser
which because there is a different system involved from regular
python subprocess's system to prevent the libuv library
from doing something worse and needing to change up more code."""
async def test():
CMD = b'python -c "import sys; print(\'hi\')"'
proc = await asyncio.create_subprocess_shell(
CMD,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE,
)
out, err = await proc.communicate()
assert out == b"hi\r\n"
assert err == b''
assert proc.returncode == 0
self.loop.run_until_complete(test())


def test_process_double_close(self):
script = textwrap.dedent("""
import os
Expand Down
4 changes: 4 additions & 0 deletions winloop/includes/stdlib.pxi
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import subprocess
import ssl
import stat
import sys
import shlex
import threading
import traceback
import time
Expand Down Expand Up @@ -101,6 +102,7 @@ cdef int socket_EAI_PROTOCOL = getattr(socket, 'EAI_PROTOCOL', -1)
cdef int socket_EAI_SERVICE = getattr(socket, 'EAI_SERVICE', -1)
cdef int socket_EAI_SOCKTYPE = getattr(socket, 'EAI_SOCKTYPE', -1)

cdef shlex_split = shlex.split

cdef str os_name = os.name
cdef os_path_isabs = os.path.isabs
Expand All @@ -119,6 +121,7 @@ cdef os_remove = os.remove
cdef os_stat = os.stat
cdef os_unlink = os.unlink
cdef os_fspath = os.fspath
cdef os_fsdecode = os.fsdecode

cdef stat_S_ISSOCK = stat.S_ISSOCK

Expand Down Expand Up @@ -181,3 +184,4 @@ del asyncio, concurrent, collections, errno
del functools, inspect, itertools, socket, os, threading
del signal, subprocess, ssl
del time, traceback, warnings, weakref
del shlex
17 changes: 14 additions & 3 deletions winloop/loop.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,10 @@ cdef inline run_in_context2(context, method, arg1, arg2):
# *reuse_address* parameter
_unset = object()

cdef list split_windows_shell_command(object cmd):
if isinstance(cmd, bytes):
cmd = cmd.decode("utf-8", "surrogateescape")
return shlex_split(cmd)

@cython.no_gc_clear
cdef class Loop:
Expand Down Expand Up @@ -2834,9 +2838,16 @@ cdef class Loop:
if not os_path_isabs(comspec):
raise FileNotFoundError('shell not found: neither %ComSpec% nor %SystemRoot% is set')

args = [comspec]
args.append('/c')
args.append(cmd)
args = [comspec, b'/c']

# XXX: We don't want to change more code than what is
# currently required and supporting bytes is better
# than windows stdlib (subprocesses.Popen disallows bytes)
# so a small workaround with the shlex parser was needed.
# Originally it was removed but brought back.
# SEE: https://github.com/Vizonex/Winloop/issues/153

args.extend(split_windows_shell_command(cmd))

return await self.__subprocess_run(protocol_factory, args, shell=True,
**kwargs)
Expand Down
Loading