diff --git a/Src/IronPythonTest/Cases/CPythonCasesManifest.ini b/Src/IronPythonTest/Cases/CPythonCasesManifest.ini index 93457fda2..1ddaf2a36 100644 --- a/Src/IronPythonTest/Cases/CPythonCasesManifest.ini +++ b/Src/IronPythonTest/Cases/CPythonCasesManifest.ini @@ -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 @@ -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 @@ -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 @@ -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 @@ -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] @@ -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 diff --git a/Src/IronPythonTest/Cases/IronPythonCasesManifest.ini b/Src/IronPythonTest/Cases/IronPythonCasesManifest.ini index a9e81483c..5c8fd993b 100644 --- a/Src/IronPythonTest/Cases/IronPythonCasesManifest.ini +++ b/Src/IronPythonTest/Cases/IronPythonCasesManifest.ini @@ -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 @@ -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 diff --git a/Src/StdLib/Lib/subprocess.py b/Src/StdLib/Lib/subprocess.py index fe22f100e..4a0d1e87f 100644 --- a/Src/StdLib/Lib/subprocess.py +++ b/Src/StdLib/Lib/subprocess.py @@ -345,6 +345,7 @@ class Popen(args, bufsize=-1, executable=None, """ import sys +ironpython = (sys.implementation.name == 'ironpython') mswindows = (sys.platform == "win32") import io @@ -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 @@ -457,6 +463,8 @@ def __repr__(self): __del__ = Close __str__ = __repr__ +elif ironpython: + __all__.extend(["Process"]) try: MAXFD = os.sysconf("SC_OPEN_MAX") @@ -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: @@ -984,7 +999,6 @@ def _check_timeout(self, endtime, orig_timeout): if _time() > endtime: raise TimeoutExpired(self.args, orig_timeout) - if mswindows: # # Windows methods @@ -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 diff --git a/Src/StdLib/Lib/test/regrtest.py b/Src/StdLib/Lib/test/regrtest.py index ebdcdad61..582f57fdc 100755 --- a/Src/StdLib/Lib/test/regrtest.py +++ b/Src/StdLib/Lib/test/regrtest.py @@ -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__'): diff --git a/Src/StdLib/Lib/test/test_uuid.py b/Src/StdLib/Lib/test/test_uuid.py index 1e8cba30b..ebbf2630f 100644 --- a/Src/StdLib/Lib/test/test_uuid.py +++ b/Src/StdLib/Lib/test/test_uuid.py @@ -4,6 +4,7 @@ import io import os import shutil +import sys import uuid def importable(name): @@ -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