Skip to content

Commit 329cd82

Browse files
committed
support more flags in the python options and make init and startup imports more regular
1 parent 49ab15b commit 329cd82

File tree

11 files changed

+185
-204
lines changed

11 files changed

+185
-204
lines changed

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

Lines changed: 90 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,18 @@ public static void main(String[] args) {
5858
}
5959

6060
private static final String LANGUAGE_ID = "python";
61-
private static final Source QUIT_EOF = Source.newBuilder(LANGUAGE_ID, "import site\nexit()", "<exit-on-eof>").internal(true).buildLiteral();
6261

6362
private ArrayList<String> programArgs = null;
6463
private String commandString = null;
6564
private String inputFile = null;
65+
private String module = null;
66+
private boolean ignoreEnv = false;
6667
private boolean inspectFlag = false;
6768
private boolean verboseFlag = false;
69+
private boolean quietFlag = false;
70+
private boolean noUserSite = false;
71+
private boolean noSite = false;
72+
private boolean stdinIsInteractive = System.console() != null;
6873
private boolean runCC = false;
6974
private boolean runLD = false;
7075
private VersionAction versionAction = VersionAction.None;
@@ -76,11 +81,49 @@ protected List<String> preprocessArguments(List<String> arguments, Map<String, S
7681
for (int i = 0; i < arguments.size(); i++) {
7782
String arg = arguments.get(i);
7883
switch (arg) {
84+
case "-B":
85+
System.out.println("Warning: " + arg + " does nothing on GraalPython.");
86+
break;
87+
case "-c":
88+
i += 1;
89+
if (i < arguments.size()) {
90+
commandString = arguments.get(i);
91+
} else {
92+
print("Argument expected for the -c option");
93+
printShortHelp();
94+
}
95+
break;
96+
case "-E":
97+
ignoreEnv = true;
98+
break;
99+
case "-h":
100+
unrecognized.add("--help");
101+
break;
102+
case "-i":
103+
inspectFlag = true;
104+
break;
105+
case "-m":
106+
i += 1;
107+
if (i < arguments.size()) {
108+
module = arguments.get(i);
109+
} else {
110+
print("Argument expected for the -m option");
111+
printShortHelp();
112+
}
113+
break;
79114
case "-O":
80115
case "-OO":
81-
case "-B":
82116
System.out.println("Warning: " + arg + " does nothing on GraalPython.");
83117
break;
118+
case "-q":
119+
quietFlag = true;
120+
break;
121+
case "-s":
122+
noUserSite = true;
123+
break;
124+
case "-S":
125+
noSite = true;
126+
break;
84127
case "-v":
85128
verboseFlag = true;
86129
break;
@@ -99,21 +142,6 @@ protected List<String> preprocessArguments(List<String> arguments, Map<String, S
99142
runLD = true;
100143
programArgs.addAll(arguments.subList(i + 1, arguments.size()));
101144
return unrecognized;
102-
case "-c":
103-
i += 1;
104-
if (i < arguments.size()) {
105-
commandString = arguments.get(i);
106-
} else {
107-
print("Argument expected for the -c option");
108-
printShortHelp();
109-
}
110-
break;
111-
case "-h":
112-
unrecognized.add("--help");
113-
break;
114-
case "-i":
115-
inspectFlag = true;
116-
break;
117145
default:
118146
if (!arg.startsWith("-")) {
119147
inputFile = arg;
@@ -123,7 +151,8 @@ protected List<String> preprocessArguments(List<String> arguments, Map<String, S
123151
unrecognized.add(arg);
124152
}
125153
}
126-
if (inputFile != null || commandString != null) {
154+
155+
if (inputFile != null || commandString != null || module != null) {
127156
i += 1;
128157
if (i < arguments.size()) {
129158
programArgs.addAll(arguments.subList(i, arguments.size()));
@@ -159,28 +188,44 @@ protected void launch(Builder contextBuilder) {
159188
return;
160189
}
161190

191+
if (!ignoreEnv) {
192+
String pythonpath = System.getenv("PYTHONPATH");
193+
if (pythonpath != null) {
194+
contextBuilder.option("python.PythonPath", pythonpath);
195+
}
196+
inspectFlag = inspectFlag || System.getenv("PYTHONINSPECT") != null;
197+
noUserSite = noUserSite || System.getenv("PYTHONNOUSERSITE") != null;
198+
verboseFlag = verboseFlag || System.getenv("PYTHONVERBOSE") != null;
199+
}
200+
162201
// setting this to make sure our TopLevelExceptionHandler calls the excepthook
163202
// to print Python exceptions
164203
contextBuilder.option("python.AlwaysRunExcepthook", "true");
165-
if (inspectFlag) {
166-
contextBuilder.option("python.InspectFlag", "true");
167-
}
204+
contextBuilder.option("python.InspectFlag", Boolean.toString(inspectFlag));
205+
contextBuilder.option("python.VerboseFlag", Boolean.toString(verboseFlag));
168206
if (verboseFlag) {
169-
contextBuilder.option("python.VerboseFlag", "true");
170207
contextBuilder.option("log.python.level", "FINE");
171208
}
172-
173-
String pythonpath = System.getenv("PYTHONPATH");
174-
if (pythonpath != null) {
175-
contextBuilder.option("python.PythonPath", pythonpath);
176-
}
209+
contextBuilder.option("python.QuietFlag", Boolean.toString(quietFlag));
210+
contextBuilder.option("python.NoUserSiteFlag", Boolean.toString(noUserSite));
211+
contextBuilder.option("python.NoSiteFlag", Boolean.toString(noSite));
177212

178213
ConsoleHandler consoleHandler = createConsoleHandler(System.in, System.out);
179214
contextBuilder.arguments(getLanguageId(), programArgs.toArray(new String[0])).in(consoleHandler.createInputStream());
180215

181216
int rc = 1;
182217
try (Context context = contextBuilder.build()) {
183218
runVersionAction(versionAction, context.getEngine());
219+
220+
if (!quietFlag && (verboseFlag || (commandString == null && inputFile == null && module == null && stdinIsInteractive))) {
221+
print("Python " + evalInternal(context, "import sys; sys.version + ' on ' + sys.platform").asString());
222+
if (!noSite) {
223+
print("Type \"help\", \"copyright\", \"credits\" or \"license\" for more information.");
224+
}
225+
}
226+
if (!noSite) {
227+
evalInternal(context, "import site\n");
228+
}
184229
System.err.println("Please note: This Python implementation is in the very early stages, " +
185230
"and can run little more than basic benchmarks at this point.");
186231
consoleHandler.setContext(context);
@@ -429,7 +474,7 @@ protected void printHelp(OptionCategory maxCategory) {
429474
"-h : print this help message and exit (also --help)\n" +
430475
"-i : inspect interactively after running script; forces a prompt even\n" +
431476
" if stdin does not appear to be a terminal; also PYTHONINSPECT=x\n" +
432-
// "-m mod : run library module as a script (terminates option list)\n" +
477+
"-m mod : run library module as a script (terminates option list)\n" +
433478
"-O : optimize generated bytecode slightly; also PYTHONOPTIMIZE=x\n" +
434479
"-OO : remove doc-strings in addition to the -O optimizations\n" +
435480
// "-R : use a pseudo-random salt to make hash() values of various types
@@ -438,16 +483,17 @@ protected void printHelp(OptionCategory maxCategory) {
438483
// " a defense against denial-of-service attacks\n" +
439484
// "-Q arg : division options: -Qold (default), -Qwarn, -Qwarnall, -Qnew\n"
440485
// +
441-
// "-s : don't add user site directory to sys.path; also PYTHONNOUSERSITE\n"
442-
// +
443-
// "-S : don't imply 'import site' on initialization\n" +
486+
"-q : don't print version and copyright messages on interactive startup" +
487+
"-s : don't add user site directory to sys.path; also PYTHONNOUSERSITE\n" +
488+
"-S : don't imply 'import site' on initialization\n" +
444489
// "-t : issue warnings about inconsistent tab usage (-tt: issue errors)\n"
445490
// +
446491
// "-u : unbuffered binary stdout and stderr; also PYTHONUNBUFFERED=x\n" +
447492
// " see man page for details on internal buffering relating to '-u'\n" +
448-
// "-v : verbose (trace import statements); also PYTHONVERBOSE=x\n" +
449-
// " can be supplied multiple times to increase verbosity\n" +
493+
"-v : verbose (trace import statements); also PYTHONVERBOSE=x\n" +
494+
" can be supplied multiple times to increase verbosity\n" +
450495
"-V : print the Python version number and exit (also --version)\n" +
496+
" when given twice, print more information about the build" +
451497
// "-W arg : warning control; arg is
452498
// action:message:category:module:lineno\n" +
453499
// " also PYTHONWARNINGS=arg\n" +
@@ -482,7 +528,7 @@ protected void printHelp(OptionCategory maxCategory) {
482528

483529
@Override
484530
protected String[] getDefaultLanguages() {
485-
return new String[]{getLanguageId(), "llvm"};
531+
return new String[]{getLanguageId(), "llvm", "regex"};
486532
}
487533

488534
@Override
@@ -516,9 +562,8 @@ public ConsoleHandler createConsoleHandler(InputStream inStream, OutputStream ou
516562
public int readEvalPrint(Context context, ConsoleHandler consoleHandler) {
517563
int lastStatus = 0;
518564
try {
519-
setupReadline(context, consoleHandler);
520-
Value sys = context.eval(Source.create(getLanguageId(), "import sys; sys"));
521-
context.eval(Source.create(getLanguageId(), "del sys\ndel site\ndel readline"));
565+
setupREPL(context, consoleHandler);
566+
Value sys = evalInternal(context, "import sys; sys");
522567

523568
while (true) { // processing inputs
524569
boolean doEcho = doEcho(context);
@@ -570,7 +615,7 @@ public int readEvalPrint(Context context, ConsoleHandler consoleHandler) {
570615
}
571616
} catch (EOFException e) {
572617
try {
573-
context.eval(QUIT_EOF);
618+
evalInternal(context, "import site; exit()\n");
574619
} catch (PolyglotException e2) {
575620
if (e2.isExit()) {
576621
// don't use the exit code from the PolyglotException
@@ -591,12 +636,15 @@ public int readEvalPrint(Context context, ConsoleHandler consoleHandler) {
591636
}
592637
}
593638

594-
private void setupReadline(Context context, ConsoleHandler consoleHandler) {
595-
// First run nothing to trigger the setup of interactive mode (site import and so on)
596-
context.eval(Source.newBuilder(getLanguageId(), "None", "setup-interactive").interactive(true).buildLiteral());
639+
private Value evalInternal(Context context, String code) {
640+
return context.eval(Source.newBuilder(getLanguageId(), code, "<internal>").internal(true).buildLiteral());
641+
}
642+
643+
private void setupREPL(Context context, ConsoleHandler consoleHandler) {
597644
// Then we can get the readline module and see if any completers were registered and use its
598645
// history feature
599-
final Value readline = context.eval(Source.create(getLanguageId(), "import readline; readline"));
646+
evalInternal(context, "import sys\ngetattr(sys, '__interactivehook__', lambda: None)()\n");
647+
final Value readline = evalInternal(context, "import readline; readline");
600648
final Value completer = readline.getMember("get_completer").execute();
601649
final Value shouldRecord = readline.getMember("get_auto_history");
602650
final Value addHistory = readline.getMember("add_history");

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
import com.oracle.graal.python.builtins.objects.PNone;
3939
import com.oracle.graal.python.builtins.objects.PythonAbstractObject;
4040
import com.oracle.graal.python.builtins.objects.code.PCode;
41-
import com.oracle.graal.python.builtins.objects.common.HashingStorage;
4241
import com.oracle.graal.python.builtins.objects.function.PArguments;
4342
import com.oracle.graal.python.builtins.objects.function.PBuiltinFunction;
4443
import com.oracle.graal.python.builtins.objects.function.PFunction;
@@ -229,35 +228,20 @@ protected void initializeContext(PythonContext context) throws Exception {
229228
@Override
230229
protected CallTarget parse(ParsingRequest request) throws Exception {
231230
PythonContext context = this.getContextReference().get();
232-
PythonCore pythonCore = context.getCore();
231+
PythonCore core = context.getCore();
233232
Source source = request.getSource();
234233
CompilerDirectives.transferToInterpreter();
235-
if (pythonCore.isInitialized()) {
234+
if (core.isInitialized()) {
236235
context.initializeMainModule(source.getPath());
237-
238-
// if we are running the interpreter, module 'site' is automatically imported
239-
if (source.isInteractive()) {
240-
runInteractiveStartup(pythonCore);
241-
}
242236
}
243-
RootNode root = doParse(pythonCore, source);
244-
if (pythonCore.isInitialized()) {
237+
RootNode root = doParse(core, source);
238+
if (core.isInitialized()) {
245239
return Truffle.getRuntime().createCallTarget(new TopLevelExceptionHandler(this, root));
246240
} else {
247241
return Truffle.getRuntime().createCallTarget(root);
248242
}
249243
}
250244

251-
private void runInteractiveStartup(PythonCore pythonCore) {
252-
PythonContext context = pythonCore.getContext();
253-
HashingStorage sysModules = context.getImportedModules().getDictStorage();
254-
String siteModuleName = "site";
255-
if (!sysModules.hasKey(siteModuleName, HashingStorage.getSlowPathEquivalence(siteModuleName))) {
256-
Source src = Source.newBuilder(ID, "import site\nimport sys\ngetattr(sys, '__interactivehook__', lambda: None)()\n", "<site import>").build();
257-
Truffle.getRuntime().createCallTarget(new TopLevelExceptionHandler(this, doParse(pythonCore, src))).call();
258-
}
259-
}
260-
261245
private RootNode doParse(PythonCore pythonCore, Source source) {
262246
try {
263247
return (RootNode) pythonCore.getParser().parse(source.isInteractive() ? ParserMode.InteractiveStatement : ParserMode.File, pythonCore, source, null);
@@ -380,8 +364,11 @@ protected Iterable<Scope> findLocalScopes(PythonContext context, Node node, Fram
380364
@Override
381365
protected Iterable<Scope> findTopScopes(PythonContext context) {
382366
ArrayList<Scope> scopes = new ArrayList<>();
383-
scopes.add(Scope.newBuilder("__main__", context.getMainModule()).build());
384-
scopes.add(Scope.newBuilder("builtins", context.getBuiltins()).build());
367+
if (context.getBuiltins() != null) {
368+
// false during initialization
369+
scopes.add(Scope.newBuilder("__main__", context.getMainModule()).build());
370+
scopes.add(Scope.newBuilder("builtins", context.getBuiltins()).build());
371+
}
385372
return scopes;
386373
}
387374

@@ -407,6 +394,10 @@ protected SourceSection findSourceLocation(PythonContext context, Object value)
407394
@Override
408395
protected String toString(PythonContext context, Object value) {
409396
final PythonModule builtins = context.getBuiltins();
397+
if (builtins == null) {
398+
// true during initialization
399+
return value.toString();
400+
}
410401
PBuiltinFunction reprMethod = ((PBuiltinMethod) builtins.getAttribute(BuiltinNames.REPR)).getFunction();
411402
Object[] userArgs = PArguments.create(2);
412403
PArguments.setArgument(userArgs, 0, PNone.NONE);
@@ -479,7 +470,7 @@ protected void initializeMultipleContexts() {
479470

480471
private final ConcurrentHashMap<String, PCode> cachedCode = new ConcurrentHashMap<>();
481472

482-
public Object cacheCode(String filename, Supplier<PCode> createCode) {
473+
public PCode cacheCode(String filename, Supplier<PCode> createCode) {
483474
return cachedCode.computeIfAbsent(filename, f -> createCode.get());
484475
}
485476

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import java.util.Map;
4141
import java.util.Map.Entry;
4242
import java.util.ServiceLoader;
43+
import java.util.function.Supplier;
4344

4445
import com.oracle.graal.python.PythonLanguage;
4546
import com.oracle.graal.python.builtins.modules.ArrayModuleBuiltins;
@@ -79,6 +80,7 @@
7980
import com.oracle.graal.python.builtins.objects.bytes.BytesBuiltins;
8081
import com.oracle.graal.python.builtins.objects.cell.CellBuiltins;
8182
import com.oracle.graal.python.builtins.objects.code.CodeBuiltins;
83+
import com.oracle.graal.python.builtins.objects.code.PCode;
8284
import com.oracle.graal.python.builtins.objects.complex.ComplexBuiltins;
8385
import com.oracle.graal.python.builtins.objects.dict.DictBuiltins;
8486
import com.oracle.graal.python.builtins.objects.dict.DictItemsIteratorBuiltins;
@@ -135,15 +137,17 @@
135137
import com.oracle.graal.python.runtime.PythonCore;
136138
import com.oracle.graal.python.runtime.PythonOptions;
137139
import com.oracle.graal.python.runtime.PythonParser;
140+
import com.oracle.graal.python.runtime.PythonParser.ParserMode;
138141
import com.oracle.graal.python.runtime.exception.PException;
139142
import com.oracle.graal.python.runtime.object.PythonObjectFactory;
140-
import com.oracle.truffle.api.CallTarget;
141143
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
142144
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
145+
import com.oracle.truffle.api.RootCallTarget;
143146
import com.oracle.truffle.api.TruffleFile;
144147
import com.oracle.truffle.api.TruffleLanguage.Env;
145148
import com.oracle.truffle.api.TruffleOptions;
146149
import com.oracle.truffle.api.nodes.Node;
150+
import com.oracle.truffle.api.nodes.RootNode;
147151
import com.oracle.truffle.api.source.Source;
148152
import com.oracle.truffle.api.source.SourceSection;
149153

@@ -169,7 +173,6 @@ public final class Python3Core implements PythonCore {
169173
"_warnings",
170174
"posix",
171175
"_io",
172-
"_frozen_importlib_external",
173176
"_frozen_importlib",
174177
"classes",
175178
"_weakref",
@@ -610,7 +613,8 @@ private Source getSource(String basename, String prefix) {
610613

611614
private void loadFile(String s, String prefix) {
612615
Source source = getSource(s, prefix);
613-
CallTarget callTarget = getContext().getEnv().parse(source);
616+
Supplier<PCode> getCode = () -> factory.createCode((RootNode) getParser().parse(ParserMode.File, this, source, null));
617+
RootCallTarget callTarget = getLanguage().cacheCode(source.getName(), getCode).getRootCallTarget();
614618
PythonModule mod = lookupBuiltinModule(s);
615619
if (mod == null) {
616620
// use an anonymous module for the side-effects

0 commit comments

Comments
 (0)