From 1df0ae0759ec83ff98c4e82a1aed2e96f077eb4e Mon Sep 17 00:00:00 2001 From: Alex Vong Date: Mon, 18 Jul 2022 22:23:21 +0000 Subject: [PATCH] private/python_ipc_system: Convert to Cygwin path when needed. This should fix some errors when Python is running in Cygwin-like environment. But there could still be errors in other places. See #1182. * inst/private/cygpath.m: New function. * inst/private/python_env_is_cygwin_like.m: New function. * inst/private/python_ipc_system.m: Use them. --- inst/private/cygpath.m | 50 ++++++++++++++++++ inst/private/python_env_is_cygwin_like.m | 64 ++++++++++++++++++++++++ inst/private/python_ipc_system.m | 9 +++- 3 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 inst/private/cygpath.m create mode 100644 inst/private/python_env_is_cygwin_like.m diff --git a/inst/private/cygpath.m b/inst/private/cygpath.m new file mode 100644 index 000000000..8773406dc --- /dev/null +++ b/inst/private/cygpath.m @@ -0,0 +1,50 @@ +%% Copyright (C) 2022 Alex Vong +%% +%% This file is part of OctSymPy. +%% +%% OctSymPy is free software; you can redistribute it and/or modify +%% it under the terms of the GNU General Public License as published +%% by the Free Software Foundation; either version 3 of the License, +%% or (at your option) any later version. +%% +%% This software is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty +%% of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See +%% the GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public +%% License along with this software; see the file COPYING. +%% If not, see . + +%% -*- texinfo -*- +%% @defun cygpath () +%% Convert Windows native path to Cygwin POSIX-style path. +%% +%% @seealso{python_env_is_cygwin_like} +%% @end defun + +function posix_path = cygpath (native_path) + args = {'-u', native_path}; + [fin, fout, pid] = popen2 ('cygpath', args); + if pid == -1 + error ('cygpath: failed to create cygpath subprocess'); + end + + assert (fclose (fin) == 0); + + err = errno ('EAGAIN'); + while err == errno ('EAGAIN') + pause (0.1); + posix_path = fgetl (fout); + err = errno (); + end + + assert (ischar (posix_path)); + assert (feof (fout)); + assert (fclose (fout) == 0); + + [retpid, status, msg] = waitpid (pid); + if retpid < 0 + error ('cygpath: failed to wait for python: %s', msg); + end +end diff --git a/inst/private/python_env_is_cygwin_like.m b/inst/private/python_env_is_cygwin_like.m new file mode 100644 index 000000000..072d7e25a --- /dev/null +++ b/inst/private/python_env_is_cygwin_like.m @@ -0,0 +1,64 @@ +%% Copyright (C) 2022 Alex Vong +%% +%% This file is part of OctSymPy. +%% +%% OctSymPy is free software; you can redistribute it and/or modify +%% it under the terms of the GNU General Public License as published +%% by the Free Software Foundation; either version 3 of the License, +%% or (at your option) any later version. +%% +%% This software is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty +%% of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See +%% the GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public +%% License along with this software; see the file COPYING. +%% If not, see . + +%% -*- texinfo -*- +%% @defun python_env_is_cygwin_like (pyexec) +%% Check if Python @var{pyexec} is running in a Cygwin-like POSIX environment, +%% such as Cygwin or MSYS2. The result is memoized to speed up subsequent +%% calls. +%% +%% @seealso{cygpath} +%% @end defun + +function r = python_env_is_cygwin_like (pyexec) + persistent python_env_is_cygwin_like_memo + + if ~isempty (python_env_is_cygwin_like_memo) + r = python_env_is_cygwin_like_memo; + elseif ispc () + args = {'-c', 'import os; print(os.name)'}; + [fin, fout, pid] = popen2 (pyexec, args); + if pid == -1 + error ('python_env_is_cygwin_like: failed to create python subprocess'); + end + + assert (fclose (fin) == 0); + + err = errno ('EAGAIN'); + while err == errno ('EAGAIN') + pause (0.1); + os = fgetl (fout); + err = errno (); + end + + assert (ischar (os)); + assert (feof (fout)); + assert (fclose (fout) == 0); + + [retpid, status, msg] = waitpid (pid); + if retpid < 0 + error ('python_env_is_cygwin_like: failed to wait for python: %s', msg); + end + + r = strcmp (os, 'posix'); + python_env_is_cygwin_like_memo = r; + else + r = false; + python_env_is_cygwin_like_memo = r; + end +end diff --git a/inst/private/python_ipc_system.m b/inst/private/python_ipc_system.m index c264f153b..7bb868045 100644 --- a/inst/private/python_ipc_system.m +++ b/inst/private/python_ipc_system.m @@ -1,4 +1,5 @@ %% Copyright (C) 2014-2016, 2022 Colin B. Macdonald +%% Copyright (C) 2022 Alex Vong %% %% This file is part of OctSymPy. %% @@ -131,7 +132,13 @@ error ('system ipc: failed to close %s (fd %d) after writing', ... tmpfilename, fd); end - [status, out] = system ([pyexec ' ' tmpfilename]); + + if python_env_is_cygwin_like (pyexec) + converted_tmpfilename = cygpath (tmpfilename); + else + converted_tmpfilename = tmpfilename; + end + [status, out] = system ([pyexec ' ' converted_tmpfilename]); end info.raw = out;