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
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ private static void appendDecodedChars(StringBuilder builder, CharBuffer out) {
private boolean noUserSite = false;
private boolean noSite = false;
private boolean unbufferedIO = false;
private boolean legacyWindowsStdio = false;
private boolean multiContext = false;
private int repeatedRuns = 1;
private boolean snaptshotStartup = false;
Expand Down Expand Up @@ -794,6 +795,7 @@ protected void launch(Builder contextBuilder) {
safePath = safePath || getBoolEnv("PYTHONSAFEPATH");
verboseFlag = verboseFlag || getBoolEnv("PYTHONVERBOSE");
unbufferedIO = unbufferedIO || getBoolEnv("PYTHONUNBUFFERED");
legacyWindowsStdio = getBoolEnv("PYTHONLEGACYWINDOWSSTDIO");
dontWriteBytecode = dontWriteBytecode || getBoolEnv("PYTHONDONTWRITEBYTECODE");
String maxStrDigitsEnv = getEnv("PYTHONINTMAXSTRDIGITS");
if (intMaxStrDigits < 0 && maxStrDigitsEnv != null) {
Expand Down Expand Up @@ -877,6 +879,9 @@ protected void launch(Builder contextBuilder) {
}
contextBuilder.option("python.IgnoreEnvironmentFlag", Boolean.toString(ignoreEnv));
contextBuilder.option("python.UnbufferedIO", Boolean.toString(unbufferedIO));
if (IS_WINDOWS) {
contextBuilder.option("python.LegacyWindowsStdio", Boolean.toString(legacyWindowsStdio));
}

ConsoleHandler consoleHandler = createConsoleHandler(System.in, System.out);
contextBuilder.arguments(getLanguageId(), programArgs.toArray(new String[programArgs.size()]));
Expand Down Expand Up @@ -1288,6 +1293,7 @@ protected void printHelp(OptionCategory maxCategory) {
"PYTHON_CPU_COUNT: override the return value of os.cpu_count() (-X cpu_count).\n" +
"PYTHONCASEOK : ignore case in 'import' statements (Windows).\n" +
"PYTHONIOENCODING: Encoding[:errors] used for stdin/stdout/stderr.\n" +
"PYTHONLEGACYWINDOWSSTDIO: use legacy Windows console I/O.\n" +
"PYTHONHASHSEED: if this variable is set to 'random', the effect is the same\n" +
" as specifying the -R option: a random value is used to seed the hashes of\n" +
" str, bytes and datetime objects. It can also be set to an integer\n" +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@
import com.oracle.graal.python.builtins.modules.io.BufferedWriterBuiltins;
import com.oracle.graal.python.builtins.modules.io.BufferedWriterMixinBuiltins;
import com.oracle.graal.python.builtins.modules.io.BytesIOBuiltins;
import com.oracle.graal.python.builtins.modules.io.CommonFileIOBuiltins;
import com.oracle.graal.python.builtins.modules.io.FileIOBuiltins;
import com.oracle.graal.python.builtins.modules.io.IOBaseBuiltins;
import com.oracle.graal.python.builtins.modules.io.IOBaseDictBuiltins;
Expand All @@ -187,6 +188,7 @@
import com.oracle.graal.python.builtins.modules.io.StringIOBuiltins;
import com.oracle.graal.python.builtins.modules.io.TextIOBaseBuiltins;
import com.oracle.graal.python.builtins.modules.io.TextIOWrapperBuiltins;
import com.oracle.graal.python.builtins.modules.io.WindowsConsoleIOBuiltins;
import com.oracle.graal.python.builtins.modules.json.JSONEncoderBuiltins;
import com.oracle.graal.python.builtins.modules.json.JSONModuleBuiltins;
import com.oracle.graal.python.builtins.modules.json.JSONScannerBuiltins;
Expand Down Expand Up @@ -620,7 +622,9 @@ private static PythonBuiltins[] initializeBuiltins(TruffleLanguage.Env env) {
new BufferedReaderMixinBuiltins(),
new BufferedWriterMixinBuiltins(),
new BufferedIOMixinBuiltins(),
new CommonFileIOBuiltins(),
new FileIOBuiltins(),
new WindowsConsoleIOBuiltins(),
new TextIOWrapperBuiltins(),
new IncrementalNewlineDecoderBuiltins(),
new BufferedRWPairBuiltins(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@
import com.oracle.graal.python.builtins.modules.io.IncrementalNewlineDecoderBuiltins;
import com.oracle.graal.python.builtins.modules.io.StringIOBuiltins;
import com.oracle.graal.python.builtins.modules.io.TextIOWrapperBuiltins;
import com.oracle.graal.python.builtins.modules.io.WindowsConsoleIOBuiltins;
import com.oracle.graal.python.builtins.modules.json.JSONEncoderBuiltins;
import com.oracle.graal.python.builtins.modules.json.JSONScannerBuiltins;
import com.oracle.graal.python.builtins.modules.lsprof.ProfilerBuiltins;
Expand Down Expand Up @@ -921,7 +922,7 @@ It can be called either on the class (e.g. C.f()) or on an instance
"BufferedRandom",
PBufferedIOBase,
newBuilder().publishInModule("_io").basetype().addDict().slots(BufferedReaderMixinBuiltins.SLOTS, BufferedIOMixinBuiltins.SLOTS, BufferedRandomBuiltins.SLOTS)),
PWindowsConsoleIO("_WindowsConsoleIO", PRawIOBase, newBuilder().moduleName("_io").basetype()),
PWindowsConsoleIO("_WindowsConsoleIO", PRawIOBase, newBuilder().moduleName("_io").basetype().addDict().slots(WindowsConsoleIOBuiltins.SLOTS)),
PFileIO("FileIO", PRawIOBase, newBuilder().publishInModule("_io").basetype().addDict().slots(FileIOBuiltins.SLOTS)),
PTextIOWrapper("TextIOWrapper", PTextIOBase, newBuilder().publishInModule("_io").basetype().addDict().slots(TextIOWrapperBuiltins.SLOTS)),
PIncrementalNewlineDecoder("IncrementalNewlineDecoder", PythonObject, newBuilder().publishInModule("_io").basetype().slots(IncrementalNewlineDecoderBuiltins.SLOTS)),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.AttributeError;
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.DeprecationWarning;
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.ImportError;
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.PWindowsConsoleIO;
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.RuntimeError;
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.RuntimeWarning;
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.TypeError;
Expand Down Expand Up @@ -174,6 +175,7 @@
import com.oracle.graal.python.builtins.modules.io.PFileIO;
import com.oracle.graal.python.builtins.modules.io.PTextIO;
import com.oracle.graal.python.builtins.modules.io.TextIOWrapperNodesFactory.TextIOWrapperInitNodeGen;
import com.oracle.graal.python.builtins.modules.io.WindowsConsoleIOBuiltins;
import com.oracle.graal.python.builtins.objects.PNone;
import com.oracle.graal.python.builtins.objects.PythonAbstractObject;
import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodes.EnsurePythonObjectNode;
Expand Down Expand Up @@ -786,23 +788,45 @@ static void initStd(Python3Core core) {
BufferedReaderBuiltins.BufferedReaderInit.internalInit(stdinBuffer, stdinFileIO, BufferedReaderBuiltins.DEFAULT_BUFFER_SIZE, language, posixSupport, posixLib);
setWrapper(T_STDIN, T___STDIN__, T_R, stdioEncoding, stdioError, PNone.NONE, stdinBuffer, sysModule, language, true);

PFileIO stdoutFileIO = PFactory.createFileIO(language);
FileIOBuiltins.FileIOInit.internalInit(stdoutFileIO, toTruffleStringUncached("<stdout>"), 1, IOMode.WB);
PFileIO stdoutFileIO = createStdoutRaw(context, language, posixSupport, posixLib, toTruffleStringUncached("<stdout>"), 1);
Object stdoutBuffer = createBufferedIO(buffering, language, stdoutFileIO, posixSupport, posixLib);
setWrapper(T_STDOUT, T___STDOUT__, T_W, stdioEncoding, stdioError, PNone.NONE, stdoutBuffer, sysModule, language, buffering);
TruffleString stdoutEncoding = isWindowsConsoleIO(stdoutFileIO) ? StringLiterals.T_UTF8 : stdioEncoding;
setWrapper(T_STDOUT, T___STDOUT__, T_W, stdoutEncoding, stdioError, PNone.NONE, stdoutBuffer, sysModule, language, buffering);

PFileIO stderr = PFactory.createFileIO(language);
FileIOBuiltins.FileIOInit.internalInit(stderr, toTruffleStringUncached("<stderr>"), 2, IOMode.WB);
PFileIO stderr = createStdoutRaw(context, language, posixSupport, posixLib, toTruffleStringUncached("<stderr>"), 2);
Object stderrBuffer = createBufferedIO(buffering, language, stderr, posixSupport, posixLib);
setWrapper(T_STDERR, T___STDERR__, T_W, stdioEncoding, T_BACKSLASHREPLACE, PNone.NONE, stderrBuffer, sysModule, language, buffering);
TruffleString stderrEncoding = isWindowsConsoleIO(stderr) ? StringLiterals.T_UTF8 : stdioEncoding;
setWrapper(T_STDERR, T___STDERR__, T_W, stderrEncoding, T_BACKSLASHREPLACE, PNone.NONE, stderrBuffer, sysModule, language, buffering);
}

private static PFileIO createStdoutRaw(PythonContext context, PythonLanguage language, Object posixSupport, PosixSupportLibrary posixLib, TruffleString name, int fd) {
if (getPythonOS() == PLATFORM_WIN32 && !context.getOption(PythonOptions.LegacyWindowsStdio)) {
int consoleType = posixLib.getWindowsConsoleType(posixSupport, fd);
if (consoleType != 0) {
PFileIO consoleIO = WindowsConsoleIOBuiltins.create(language);
WindowsConsoleIOBuiltins.internalInit(consoleIO, name, fd, IOMode.WB, consoleType);
return consoleIO;
}
}
PFileIO fileIO = PFactory.createFileIO(language);
FileIOBuiltins.FileIOInit.internalInit(fileIO, name, fd, IOMode.WB);
return fileIO;
}

private static boolean isWindowsConsoleIO(PFileIO fileIO) {
return getPythonOS() == PLATFORM_WIN32 && fileIO.getPythonClass() == PWindowsConsoleIO;
}

private static Object createBufferedIO(boolean buffering, PythonLanguage language, PFileIO fileIo, Object posixSupport, PosixSupportLibrary posixLib) {
if (!buffering) {
return fileIo;
}
PBuffered writer = PFactory.createBufferedWriter(language);
BufferedWriterBuiltins.BufferedWriterInit.internalInit(writer, fileIo, BufferedReaderBuiltins.DEFAULT_BUFFER_SIZE, language, posixSupport, posixLib);
if (isWindowsConsoleIO(fileIo)) {
BufferedWriterBuiltins.BufferedWriterInit.internalInitConsole(writer, fileIo, BufferedReaderBuiltins.DEFAULT_BUFFER_SIZE, language);
} else {
BufferedWriterBuiltins.BufferedWriterInit.internalInit(writer, fileIo, BufferedReaderBuiltins.DEFAULT_BUFFER_SIZE, language, posixSupport, posixLib);
}
return writer;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The Universal Permissive License (UPL), Version 1.0
Expand Down Expand Up @@ -104,7 +104,7 @@ static void bufferSizeError(PBuffered self, int bufferSize,
throw PRaiseNode.raiseStatic(inliningTarget, ValueError, BUF_SIZE_POS);
}

private static void init(PBuffered self, int bufferSize, PythonLanguage language) {
static void init(PBuffered self, int bufferSize, PythonLanguage language) {
self.initBuffer(bufferSize);
self.setLock(PFactory.createLock(language));
self.setOwner(0);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The Universal Permissive License (UPL), Version 1.0
Expand Down Expand Up @@ -125,6 +125,15 @@ public static void internalInit(PBuffered self, PFileIO raw, int bufferSize, Pyt
self.setOK(true);

}

public static void internalInitConsole(PBuffered self, PFileIO raw, int bufferSize, PythonLanguage language) {
self.setDetached(false);
self.setRaw(raw, false);
BufferedInitNode.init(self, bufferSize, language);
self.resetWrite();
self.setPos(0);
self.setOK(true);
}
}

// BufferedWriter(raw[, buffer_size=DEFAULT_BUFFER_SIZE])
Expand Down
Loading
Loading