Skip to content

Commit e374961

Browse files
committed
[GR-13393] Patch venv so it'll work for us
PullRequest: graalpython/363
2 parents 11bd05c + 98df288 commit e374961

File tree

25 files changed

+792
-444
lines changed

25 files changed

+792
-444
lines changed

graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonMain.java

Lines changed: 122 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import java.util.Set;
4040

4141
import org.graalvm.launcher.AbstractLanguageLauncher;
42+
import org.graalvm.nativeimage.ImageInfo;
4243
import org.graalvm.nativeimage.ProcessProperties;
4344
import org.graalvm.options.OptionCategory;
4445
import org.graalvm.polyglot.Context;
@@ -72,11 +73,15 @@ public static void main(String[] args) {
7273
private boolean runLLI = false;
7374
private VersionAction versionAction = VersionAction.None;
7475
private String sulongLibraryPath = null;
76+
private List<String> givenArguments;
7577

7678
@Override
77-
protected List<String> preprocessArguments(List<String> arguments, Map<String, String> polyglotOptions) {
79+
protected List<String> preprocessArguments(List<String> givenArgs, Map<String, String> polyglotOptions) {
7880
ArrayList<String> unrecognized = new ArrayList<>();
79-
List<String> inputArgs = new ArrayList<>(arguments);
81+
ArrayList<String> inputArgs = new ArrayList<>(getDefaultEnvironmentArgs());
82+
inputArgs.addAll(givenArgs);
83+
givenArguments = new ArrayList<>(inputArgs);
84+
List<String> arguments = new ArrayList<>(inputArgs);
8085
List<String> subprocessArgs = new ArrayList<>();
8186
programArgs = new ArrayList<>();
8287
for (int i = 0; i < arguments.size(); i++) {
@@ -201,6 +206,60 @@ protected List<String> preprocessArguments(List<String> arguments, Map<String, S
201206
return unrecognized;
202207
}
203208

209+
private static enum State {
210+
NORMAL,
211+
SINGLE_QUOTE,
212+
DOUBLE_QUOTE,
213+
ESCAPE_SINGLE_QUOTE,
214+
ESCAPE_DOUBLE_QUOTE,
215+
}
216+
217+
private static List<String> getDefaultEnvironmentArgs() {
218+
String envArgsOpt = System.getenv("GRAAL_PYTHON_OPTIONS");
219+
ArrayList<String> envArgs = new ArrayList<>();
220+
State s = State.NORMAL;
221+
StringBuilder sb = new StringBuilder();
222+
if (envArgsOpt != null) {
223+
for (char x : envArgsOpt.toCharArray()) {
224+
if (s == State.NORMAL && Character.isWhitespace(x)) {
225+
if (sb.length() > 0) {
226+
envArgs.add(sb.toString());
227+
sb.setLength(0);
228+
}
229+
} else {
230+
if (x == '"') {
231+
if (s == State.NORMAL) {
232+
s = State.DOUBLE_QUOTE;
233+
} else if (s == State.DOUBLE_QUOTE) {
234+
s = State.NORMAL;
235+
} else if (s == State.ESCAPE_DOUBLE_QUOTE) {
236+
s = State.DOUBLE_QUOTE;
237+
sb.append(x);
238+
}
239+
} else if (x == '\'') {
240+
if (s == State.NORMAL) {
241+
s = State.SINGLE_QUOTE;
242+
} else if (s == State.SINGLE_QUOTE) {
243+
s = State.NORMAL;
244+
} else if (s == State.ESCAPE_SINGLE_QUOTE) {
245+
s = State.SINGLE_QUOTE;
246+
sb.append(x);
247+
}
248+
} else if (x == '\\') {
249+
if (s == State.SINGLE_QUOTE) {
250+
s = State.ESCAPE_SINGLE_QUOTE;
251+
} else if (s == State.DOUBLE_QUOTE) {
252+
s = State.ESCAPE_DOUBLE_QUOTE;
253+
}
254+
} else {
255+
sb.append(x);
256+
}
257+
}
258+
}
259+
}
260+
return envArgs;
261+
}
262+
204263
private static void printShortHelp() {
205264
print("usage: python [option] ... [-c cmd | -m mod | file | -] [arg] ...\n" +
206265
"Try `python -h' for more information.");
@@ -210,6 +269,43 @@ private static void print(String string) {
210269
System.out.println(string);
211270
}
212271

272+
private static String[] getExecutableList() {
273+
if (ImageInfo.inImageCode()) {
274+
return new String[]{getExecutable()};
275+
} else {
276+
StringBuilder sb = new StringBuilder();
277+
ArrayList<String> exec_list = new ArrayList<>();
278+
sb.append(System.getProperty("java.home")).append(File.separator).append("bin").append(File.separator).append("java");
279+
exec_list.add(sb.toString());
280+
for (String arg : ManagementFactory.getRuntimeMXBean().getInputArguments()) {
281+
if (arg.matches("-Xrunjdwp:transport=dt_socket,server=y,address=\\d+,suspend=y")) {
282+
arg = arg.replace("suspend=y", "suspend=n");
283+
}
284+
exec_list.add(arg);
285+
}
286+
exec_list.add("-classpath");
287+
exec_list.add(System.getProperty("java.class.path"));
288+
exec_list.add(GraalPythonMain.class.getName());
289+
return exec_list.toArray(new String[exec_list.size()]);
290+
}
291+
}
292+
293+
private static String getExecutable() {
294+
if (ImageInfo.inImageRuntimeCode()) {
295+
return ProcessProperties.getExecutableName();
296+
} else if (ImageInfo.inImageBuildtimeCode()) {
297+
return "";
298+
} else {
299+
String[] executableList = getExecutableList();
300+
for (int i = 0; i < executableList.length; i++) {
301+
if (executableList[i].matches("\\s")) {
302+
executableList[i] = "'" + executableList[i].replace("'", "\\'") + "'";
303+
}
304+
}
305+
return String.join(" ", executableList);
306+
}
307+
}
308+
213309
@Override
214310
protected void launch(Builder contextBuilder) {
215311
if (runLLI) {
@@ -233,7 +329,11 @@ protected void launch(Builder contextBuilder) {
233329
noUserSite = noUserSite || System.getenv("PYTHONNOUSERSITE") != null;
234330
verboseFlag = verboseFlag || System.getenv("PYTHONVERBOSE") != null;
235331
}
236-
sulongLibraryPath = System.getenv("SULONG_LIBRARY_PATH");
332+
333+
// The unlikely separator is used because options need to be strings. See
334+
// PythonOptions.getExecutableList()
335+
contextBuilder.option("python.ExecutableList", String.join("🏆", getExecutableList()));
336+
setContextOptionIfUnset(contextBuilder, "python.Executable", getExecutable());
237337

238338
// setting this to make sure our TopLevelExceptionHandler calls the excepthook
239339
// to print Python exceptions
@@ -246,6 +346,9 @@ protected void launch(Builder contextBuilder) {
246346
contextBuilder.option("python.QuietFlag", Boolean.toString(quietFlag));
247347
contextBuilder.option("python.NoUserSiteFlag", Boolean.toString(noUserSite));
248348
contextBuilder.option("python.NoSiteFlag", Boolean.toString(noSite));
349+
contextBuilder.option("python.IgnoreEnvironmentFlag", Boolean.toString(ignoreEnv));
350+
351+
sulongLibraryPath = System.getenv("SULONG_LIBRARY_PATH");
249352
if (sulongLibraryPath != null) {
250353
contextBuilder.option("llvm.libraryPath", sulongLibraryPath);
251354
}
@@ -302,6 +405,18 @@ protected void launch(Builder contextBuilder) {
302405
System.exit(rc);
303406
}
304407

408+
private void setContextOptionIfUnset(Builder contextBuilder, String key, String value) {
409+
if (System.getProperty("polyglot." + key) != null) {
410+
return;
411+
}
412+
for (String f : givenArguments) {
413+
if (f.startsWith("--" + key)) {
414+
return;
415+
}
416+
}
417+
contextBuilder.option(key, value);
418+
}
419+
305420
private static void printFileNotFoundException(NoSuchFileException e) {
306421
String reason = e.getReason();
307422
if (reason == null) {
@@ -423,7 +538,10 @@ protected void printHelp(OptionCategory maxCategory) {
423538
" str, bytes and datetime objects. It can also be set to an integer\n" +
424539
" in the range [0,4294967295] to get hash values with a predictable seed.\n" +
425540
"SULONG_LIBRARY_PATH: Specifies the library path for Sulong.\n" +
426-
" This is required when starting subprocesses of python.");
541+
" This is required when starting subprocesses of python.\n" +
542+
"GRAAL_PYTHON_OPTIONS: This environment variable can include default options that\n" +
543+
" are always passed to the launcher. These are not shell expanded and given to\n" +
544+
" the launcher as-is.");
427545
if (maxCategory.compareTo(OptionCategory.DEBUG) >= 0) {
428546
print("\nGraalPython performance debugging options:\n" +
429547
"-debug-perf : Enable tracing of Truffle compilations and its warnings\n" +

graalpython/com.oracle.graal.python.test/src/com/oracle/graal/python/test/PythonTests.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2018, Oracle and/or its affiliates.
2+
* Copyright (c) 2017, 2019, Oracle and/or its affiliates.
33
* Copyright (c) 2013, Regents of the University of California
44
*
55
* All rights reserved.
@@ -38,6 +38,7 @@
3838
import java.io.OutputStream;
3939
import java.io.PrintStream;
4040
import java.io.Reader;
41+
import java.lang.management.ManagementFactory;
4142
import java.lang.reflect.Field;
4243
import java.net.JarURLConnection;
4344
import java.net.URLConnection;
@@ -81,11 +82,24 @@ public class PythonTests {
8182
private static Engine engine = Engine.newBuilder().out(PythonTests.outStream).err(PythonTests.errStream).build();
8283
private static Context context = null;
8384

85+
private static final String executable;
86+
static {
87+
StringBuilder sb = new StringBuilder();
88+
sb.append(System.getProperty("java.home")).append(File.separator).append("bin").append(File.separator).append("java");
89+
for (String arg : ManagementFactory.getRuntimeMXBean().getInputArguments()) {
90+
sb.append(' ').append(arg);
91+
}
92+
sb.append(" -classpath ");
93+
sb.append(System.getProperty("java.class.path"));
94+
sb.append(" com.oracle.graal.python.shell.GraalPythonMain");
95+
executable = sb.toString();
96+
}
97+
8498
public static void enterContext(String... newArgs) {
8599
PythonTests.outArray.reset();
86100
PythonTests.errArray.reset();
87101
Context prevContext = context;
88-
context = Context.newBuilder().engine(engine).allowAllAccess(true).arguments("python", newArgs).build();
102+
context = Context.newBuilder().engine(engine).allowAllAccess(true).arguments("python", newArgs).option("python.Executable", executable).build();
89103
context.initialize("python");
90104
if (prevContext != null) {
91105
closeContext(prevContext);

0 commit comments

Comments
 (0)