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
20 changes: 0 additions & 20 deletions Src/IronPythonTest/Cases/CPythonCasesManifest.ini
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,6 @@ Ignore=true
Ignore=true
Reason=Current implementation of get_last_error needs to be debugged

[CPython.ctypes.test_find]
RunCondition=NOT $(IS_POSIX)
Reason=Blocked by https://github.com/IronLanguages/ironpython3/issues/541

[CPython.ctypes.test_frombuffer]
Ignore=true

Expand All @@ -60,10 +56,6 @@ Ignore=true
[CPython.ctypes.test_libc]
Ignore=true

[CPython.ctypes.test_loading]
RunCondition=NOT $(IS_POSIX)
Reason=Blocked by https://github.com/IronLanguages/ironpython3/issues/541

[CPython.ctypes.test_objects]
Ignore=true
Reason=CPython implementation detail
Expand Down Expand Up @@ -193,10 +185,6 @@ Ignore=true
Ignore=true
Reason=ImportError: No module named audioop

[CPython.test_base64]
RunCondition=NOT $(IS_POSIX)
Reason=Blocked by https://github.com/IronLanguages/ironpython3/issues/541

[CPython.test_bigmem]
Ignore=true

Expand Down Expand Up @@ -586,8 +574,6 @@ Ignore=true

[CPython.test_keyword]
NotParallelSafe=true
RunCondition=NOT $(IS_POSIX)
Reason=https://github.com/IronLanguages/ironpython3/issues/541

[CPython.test_keywordonlyarg]
Ignore=true
Expand Down Expand Up @@ -921,8 +907,6 @@ Ignore=true
Ignore=true

[CPython.test_source_encoding]
RunCondition=NOT $(IS_POSIX)
Reason=https://github.com/IronLanguages/ironpython3/issues/541
IsolationLevel=ENGINE # source file in a non-UTF-8 encoding

[CPython.test_spwd]
Expand Down Expand Up @@ -1125,10 +1109,6 @@ Reason=https://github.com/IronLanguages/ironpython3/issues/581
IsolationLevel=ENGINE
MaxRecursion=100

[CPython.test_uuid]
RunCondition=NOT $(IS_POSIX)
Reason=https://github.com/IronLanguages/ironpython3/issues/541

[CPython.test_venv]
Ignore=true

Expand Down
16 changes: 4 additions & 12 deletions Src/IronPythonTest/Cases/IronPythonCasesManifest.ini
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,8 @@ Redirect=false
Timeout=120000 # 2 minute timeout

[IronPython.test_builtin_stdlib]
RunCondition=NOT $(IS_POSIX)
Reason=Blocked by https://github.com/IronLanguages/ironpython3/issues/541

[IronPython.test_bz2_stdlib]
RunCondition=NOT $(IS_POSIX)
Reason=Blocked by https://github.com/IronLanguages/ironpython3/issues/541
RunCondition=NOT $(IS_MONO)
Reason=Exception on adding DocTestSuite

[IronPython.test_class]
Ignore=true
Expand Down Expand Up @@ -198,17 +194,13 @@ IsolationLevel=PROCESS # changes the locale which can cause other tests to fail
[IronPython.modules.system_related.test_nt]
RunCondition=NOT $(IS_POSIX)

[IronPython.modules.system_related.test_sys]
RunCondition=NOT $(IS_POSIX)
Reason=Blocked by https://github.com/IronLanguages/ironpython3/issues/541

[IronPython.modules.system_related.test_sys_getframe]
IsolationLevel=PROCESS # https://github.com/IronLanguages/ironpython3/issues/489
FullFrames=true

[IronPython.modules.system_related.test_thread]
RunCondition=NOT $(IS_POSIX)
Reason=Blocked by https://github.com/IronLanguages/ironpython3/issues/541
RunCondition=NOT $(IS_MONO)
Reason=Blocked by https://github.com/IronLanguages/ironpython3/issues/937

[IronPython.scripts.test_builder]
Ignore=true
Expand Down
127 changes: 126 additions & 1 deletion Src/StdLib/Lib/subprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,7 @@ class Popen(args, bufsize=-1, executable=None,
"""

import sys
ironpython = (sys.implementation.name == 'ironpython')
mswindows = (sys.platform == "win32")

import io
Expand Down Expand Up @@ -401,6 +402,11 @@ class STARTUPINFO:
hStdOutput = None
hStdError = None
wShowWindow = 0
elif ironpython:
import threading
import clr
clr.AddReference("System")
from System.Diagnostics import Process
else:
import _posixsubprocess
import select
Expand Down Expand Up @@ -457,6 +463,8 @@ def __repr__(self):

__del__ = Close
__str__ = __repr__
elif ironpython:
__all__.extend(["Process"])

try:
MAXFD = os.sysconf("SC_OPEN_MAX")
Expand Down Expand Up @@ -778,6 +786,13 @@ def __init__(self, args, bufsize=-1, executable=None,
raise ValueError(
"close_fds is not supported on Windows platforms"
" if you redirect stdin/stdout/stderr")

elif ironpython:
if preexec_fn is not None:
raise ValueError("preexec_fn is not supported by IronPython")
# if close_fds:
# raise ValueError("close_fds is not supported by IronPython")

else:
# POSIX
if close_fds is _PLATFORM_DEFAULT_CLOSE_FDS:
Expand Down Expand Up @@ -984,7 +999,6 @@ def _check_timeout(self, endtime, orig_timeout):
if _time() > endtime:
raise TimeoutExpired(self.args, orig_timeout)


if mswindows:
#
# Windows methods
Expand Down Expand Up @@ -1272,6 +1286,117 @@ def terminate(self):

kill = terminate


elif ironpython:
#
# Dotnet methods
#
def _get_handles(self, stdin, stdout, stderr):
# Can't get redirect file before Process.Start() is called
# postpone it to _execute_child
return (stdin, -1, -1, stdout, -1, stderr)

def _execute_child(self, args, executable, preexec_fn, close_fds,
pass_fds, cwd, env,
startupinfo, creationflags, shell,
stdin, unused_p2cwrite,
unused_c2pread, stdout,
unused_errread, stderr,
unused_restore_signals, unused_start_new_session):
"""Execute program (Dotnet version)"""
p = Process()
s = p.StartInfo

if env:
for k, v in env.items():
s.Environment[k] = v

if shell:
if not isinstance(args, str):
args = list2cmdline(args)
# escape backslash and double quote
args = ''.join('\\' + c if c in {'\\', '"'} else c for c in args)
s.Arguments = '-c "{}"'.format(args)
s.FileName = executable or '/bin/sh'
else:
if not isinstance(args, str):
s.FileName = args[0]
s.Arguments = list2cmdline(args[1:])
else:
s.FileName = args

s.RedirectStandardInput = stdin is not None
s.RedirectStandardOutput = stdout is not None
s.RedirectStandardError = stderr is not None
s.WorkingDirectory = cwd
s.UseShellExecute = False

p.Start()

self.pid = p.Id
self._child_created = True
self._handle = p

if stdin == PIPE:
self.stdin = open(p.StandardInput.BaseStream)
if stdout == PIPE:
self.stdout = io.BufferedReader(open(p.StandardOutput.BaseStream))
if stderr == PIPE:
self.stderr = io.BufferedReader(open(p.StandardError.BaseStream))

# dotnet can't redirect stdio to file/stream, thus has to feed from parent
if stdin not in (None, DEVNULL, PIPE):
# assume file-like object
input = stdin.read()
with open(self._handle.StandardInput.BaseStream) as f:
f.write(input)

def _internal_poll(self):
"""Check if child process has terminated. Returns returncode
attribute.

This method is called by __del__, so it can only refer to objects
in its local scope.

"""
if self.returncode is None and self._handle.HasExited:
self.returncode = self._handle.ExitCode
return self.returncode

def wait(self, timeout=None, endtime=None):
"""Wait for child process to terminate. Returns returncode
attribute."""
if endtime is not None:
timeout = self._remaining_time(endtime)
if timeout is None:
self._handle.WaitForExit()
else:
self._handle.WaitForExit(int(timeout * 1000))
self.returncode = self._handle.ExitCode
return self.returncode

def _communicate(self, input, endtime, orig_timeout):
# .NET framework caches stdout and stderr
# so we can simply wait then read
if self.stdin:
if input:
self.stdin.write(input)
self.stdin.close()

if orig_timeout is not None:
self.wait(endtime=endtime)

return (
self.stdout.read() if self.stdout else None,
self.stderr.read() if self.stderr else None,
)

def terminate(self):
"""Terminates the process."""
self._handle.Kill()

kill = terminate

else:
#
# POSIX methods
Expand Down
2 changes: 2 additions & 0 deletions Src/StdLib/Lib/test/regrtest.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,8 @@
# Therefore it is necessary to absolutize manually the __file__ and __path__ of
# the packages to prevent later imports to fail when the CWD is different.
for module in sys.modules.values():
if type(module).__name__ == 'namespace#': # namespace in IronPython
continue
if hasattr(module, '__path__'):
module.__path__ = [os.path.abspath(path) for path in module.__path__]
if hasattr(module, '__file__'):
Expand Down
6 changes: 5 additions & 1 deletion Src/StdLib/Lib/test/test_uuid.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import io
import os
import shutil
import sys
import uuid

def importable(name):
Expand Down Expand Up @@ -386,7 +387,10 @@ def test_uuid5(self):
equal(u, uuid.UUID(v))
equal(str(u), v)

@unittest.skipUnless(os.name == 'posix', 'requires Posix')
@unittest.skipUnless(
os.name == 'posix' and sys.implementation.name != 'ironpython',
'requires os.fork'
)
def testIssue8621(self):
# On at least some versions of OSX uuid.uuid4 generates
# the same sequence of UUIDs in the parent and any
Expand Down