2626package com .oracle .graal .python .builtins .modules ;
2727
2828import static com .oracle .graal .python .builtins .PythonBuiltinClassType .EOFError ;
29+ import static com .oracle .graal .python .builtins .PythonBuiltinClassType .KeyboardInterrupt ;
30+ import static com .oracle .graal .python .builtins .PythonBuiltinClassType .OSError ;
2931import static com .oracle .graal .python .builtins .PythonBuiltinClassType .RuntimeError ;
3032import static com .oracle .graal .python .builtins .PythonBuiltinClassType .StopIteration ;
3133import static com .oracle .graal .python .builtins .PythonBuiltinClassType .SyntaxError ;
8688import static com .oracle .graal .python .nodes .BuiltinNames .T___GRAALPYTHON__ ;
8789import static com .oracle .graal .python .nodes .PGuards .isNoValue ;
8890import static com .oracle .graal .python .nodes .SpecialAttributeNames .T___DICT__ ;
91+ import static com .oracle .graal .python .nodes .SpecialMethodNames .T_FILENO ;
8992import static com .oracle .graal .python .nodes .SpecialMethodNames .T___FORMAT__ ;
9093import static com .oracle .graal .python .nodes .SpecialMethodNames .T___MRO_ENTRIES__ ;
9194import static com .oracle .graal .python .nodes .SpecialMethodNames .T___ROUND__ ;
178181import com .oracle .graal .python .lib .PyEvalGetLocals ;
179182import com .oracle .graal .python .lib .PyIterCheckNode ;
180183import com .oracle .graal .python .lib .PyIterNextNode ;
184+ import com .oracle .graal .python .lib .PyLongAsLongNode ;
181185import com .oracle .graal .python .lib .PyMappingCheckNode ;
182186import com .oracle .graal .python .lib .PyNumberAbsoluteNode ;
183187import com .oracle .graal .python .lib .PyNumberAddNode ;
258262import com .oracle .graal .python .pegparser .sst .ModTy ;
259263import com .oracle .graal .python .pegparser .tokenizer .SourceRange ;
260264import com .oracle .graal .python .runtime .ExecutionContext .IndirectCallContext ;
265+ import com .oracle .graal .python .runtime .GilNode ;
261266import com .oracle .graal .python .runtime .IndirectCallData ;
267+ import com .oracle .graal .python .runtime .PosixSupportLibrary ;
262268import com .oracle .graal .python .runtime .PythonContext ;
263269import com .oracle .graal .python .runtime .PythonOptions ;
264270import com .oracle .graal .python .runtime .exception .PException ;
298304import com .oracle .truffle .api .exception .AbstractTruffleException ;
299305import com .oracle .truffle .api .frame .Frame ;
300306import com .oracle .truffle .api .frame .VirtualFrame ;
307+ import com .oracle .truffle .api .interop .InteropException ;
301308import com .oracle .truffle .api .interop .InteropLibrary ;
302309import com .oracle .truffle .api .interop .UnsupportedMessageException ;
303310import com .oracle .truffle .api .library .CachedLibrary ;
@@ -2628,20 +2635,21 @@ static Object input(VirtualFrame frame, Object prompt,
26282635 }
26292636
26302637 @ TruffleBoundary
2631- private static Object doInput (Object prompt , Node inliningTarget , PythonContext context ) {
2638+ @ SuppressWarnings ("try" )
2639+ private static Object doInput (Object prompt , Node node , PythonContext context ) {
26322640 PythonModule sysModule = context .getSysModule ();
26332641 Object stdin = PyObjectLookupAttr .executeUncached (sysModule , T_STDIN );
26342642 Object stdout = PyObjectLookupAttr .executeUncached (sysModule , T_STDOUT );
26352643 Object stderr = PyObjectLookupAttr .executeUncached (sysModule , T_STDERR );
26362644
26372645 if (stdin instanceof PNone ) {
2638- throw PRaiseNode .raiseStatic (inliningTarget , RuntimeError , ErrorMessages .INPUT_LOST_SYS_S , T_STDIN );
2646+ throw PRaiseNode .raiseStatic (node , RuntimeError , ErrorMessages .INPUT_LOST_SYS_S , T_STDIN );
26392647 }
26402648 if (stdout instanceof PNone ) {
2641- throw PRaiseNode .raiseStatic (inliningTarget , RuntimeError , ErrorMessages .INPUT_LOST_SYS_S , T_STDOUT );
2649+ throw PRaiseNode .raiseStatic (node , RuntimeError , ErrorMessages .INPUT_LOST_SYS_S , T_STDOUT );
26422650 }
26432651 if (stderr instanceof PNone ) {
2644- throw PRaiseNode .raiseStatic (inliningTarget , RuntimeError , ErrorMessages .INPUT_LOST_SYS_S , T_STDERR );
2652+ throw PRaiseNode .raiseStatic (node , RuntimeError , ErrorMessages .INPUT_LOST_SYS_S , T_STDERR );
26452653 }
26462654
26472655 SysModuleBuiltins .AuditNode .auditUncached ("builtins.input" , prompt != NO_VALUE ? prompt : NONE );
@@ -2652,6 +2660,51 @@ private static Object doInput(Object prompt, Node inliningTarget, PythonContext
26522660 // Ignore
26532661 }
26542662
2663+ Object consoleHandler = PyObjectLookupAttr .executeUncached (sysModule , tsLiteral ("_console_handler" ));
2664+ if (!(consoleHandler instanceof PNone )) {
2665+ boolean tty = false ;
2666+ try {
2667+ long fileno = PyLongAsLongNode .executeUncached (PyObjectCallMethodObjArgs .executeUncached (stdin , T_FILENO ));
2668+ if (fileno == 0 ) {
2669+ tty = PosixSupportLibrary .getUncached ().isatty (context .getPosixSupport (), 0 );
2670+ }
2671+ } catch (AbstractTruffleException e ) {
2672+ // not a tty
2673+ }
2674+ if (tty ) {
2675+ InteropLibrary lib = InteropLibrary .getUncached ();
2676+ try {
2677+ boolean havePrompt = !(prompt instanceof PNone );
2678+ if (havePrompt ) {
2679+ TruffleString promptStr = PyObjectStrAsTruffleStringNode .executeUncached (prompt );
2680+ lib .invokeMember (consoleHandler , "setPrompt" , promptStr );
2681+ }
2682+ try (var gil = GilNode .uncachedRelease ()) {
2683+ // TODO can we make it interruptible?
2684+ Object line ;
2685+ try {
2686+ line = lib .invokeMember (consoleHandler , "readLine" , havePrompt );
2687+ } catch (AbstractTruffleException e ) {
2688+ try {
2689+ if ("UserInterruptException" .equals (lib .asString (lib .getMetaSimpleName (lib .getMetaObject (e ))))) {
2690+ throw PRaiseNode .raiseStatic (node , KeyboardInterrupt );
2691+ }
2692+ } catch (InteropException ex ) {
2693+ // Fallthrough
2694+ }
2695+ throw PRaiseNode .raiseStatic (node , OSError , ErrorMessages .M , e );
2696+ }
2697+ if (lib .isNull (line )) {
2698+ throw PRaiseNode .raiseStatic (node , EOFError );
2699+ }
2700+ return lib .asTruffleString (line ).switchEncodingUncached (TS_ENCODING );
2701+ }
2702+ } catch (InteropException e ) {
2703+ // fall back to simple read
2704+ }
2705+ }
2706+ }
2707+
26552708 if (!(prompt instanceof PNone )) {
26562709 Object promptStr = PyObjectStrAsObjectNode .executeUncached (prompt );
26572710 PyObjectCallMethodObjArgs .executeUncached (stdout , T_WRITE , promptStr );
@@ -2667,7 +2720,7 @@ private static Object doInput(Object prompt, Node inliningTarget, PythonContext
26672720 TruffleString strLine = CastToTruffleStringNode .castKnownStringUncached (line );
26682721 int len = strLine .codePointLengthUncached (TS_ENCODING );
26692722 if (len == 0 ) {
2670- throw PRaiseNode .raiseStatic (inliningTarget , EOFError , ErrorMessages .EOF_WHEN_READING_A_LINE );
2723+ throw PRaiseNode .raiseStatic (node , EOFError , ErrorMessages .EOF_WHEN_READING_A_LINE );
26712724 }
26722725 int lastChar = strLine .codePointAtIndexUncached (len - 1 , TS_ENCODING );
26732726 if (lastChar == '\n' ) {
@@ -2677,7 +2730,7 @@ private static Object doInput(Object prompt, Node inliningTarget, PythonContext
26772730 } else if (PyBytesCheckNode .executeUncached (line )) {
26782731 byte [] bytesLine = PythonBufferAccessLibrary .getUncached ().getCopiedByteArray (BytesNodes .GetBytesStorage .executeUncached (line ));
26792732 if (bytesLine .length == 0 ) {
2680- throw PRaiseNode .raiseStatic (inliningTarget , EOFError , ErrorMessages .EOF_WHEN_READING_A_LINE );
2733+ throw PRaiseNode .raiseStatic (node , EOFError , ErrorMessages .EOF_WHEN_READING_A_LINE );
26812734 }
26822735 PythonLanguage language = context .getLanguage ();
26832736 if (bytesLine [bytesLine .length - 1 ] == '\n' ) {
@@ -2686,7 +2739,7 @@ private static Object doInput(Object prompt, Node inliningTarget, PythonContext
26862739 return PFactory .createBytes (language , bytesLine );
26872740 }
26882741 } else {
2689- throw PRaiseNode .raiseStatic (inliningTarget , TypeError , ErrorMessages .OBJECT_READLINE_RETURNED_NON_STRING );
2742+ throw PRaiseNode .raiseStatic (node , TypeError , ErrorMessages .OBJECT_READLINE_RETURNED_NON_STRING );
26902743 }
26912744 }
26922745 }
0 commit comments