Skip to content
This repository was archived by the owner on Mar 23, 2023. It is now read-only.

Commit 498b88e

Browse files
corona10trotterdylan
authored andcommitted
Implement raw_input() (#233)
1 parent 9ca28dd commit 498b88e

4 files changed

Lines changed: 91 additions & 1 deletion

File tree

runtime/builtin_types.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"fmt"
1919
"math"
2020
"math/big"
21+
"strings"
2122
"unicode"
2223
)
2324

@@ -110,6 +111,7 @@ var builtinTypes = map[*Type]*builtinTypeInfo{
110111
EllipsisType: {init: initEllipsisType, global: true},
111112
enumerateType: {init: initEnumerateType, global: true},
112113
EnvironmentErrorType: {global: true},
114+
EOFErrorType: {global: true},
113115
ExceptionType: {global: true},
114116
FileType: {init: initFileType, global: true},
115117
FloatType: {init: initFloatType, global: true},
@@ -559,6 +561,37 @@ func builtinRange(f *Frame, args Args, kwargs KWArgs) (*Object, *BaseException)
559561
return ListType.Call(f, []*Object{r}, nil)
560562
}
561563

564+
func builtinRawInput(f *Frame, args Args, kwargs KWArgs) (*Object, *BaseException) {
565+
if len(args) > 1 {
566+
msg := fmt.Sprintf("[raw_]input expcted at most 1 arguments, got %d", len(args))
567+
return nil, f.RaiseType(TypeErrorType, msg)
568+
}
569+
570+
if Stdin == nil {
571+
msg := fmt.Sprintf("[raw_]input: lost sys.stdin")
572+
return nil, f.RaiseType(RuntimeErrorType, msg)
573+
}
574+
575+
if Stdout == nil {
576+
msg := fmt.Sprintf("[raw_]input: lost sys.stdout")
577+
return nil, f.RaiseType(RuntimeErrorType, msg)
578+
}
579+
580+
if len(args) == 1 {
581+
err := pyPrint(f, args, "", "", Stdout)
582+
if err != nil {
583+
return nil, err
584+
}
585+
}
586+
587+
line, err := Stdin.reader.ReadString('\n')
588+
if err != nil {
589+
return nil, f.RaiseType(EOFErrorType, "EOF when reading a line")
590+
}
591+
line = strings.TrimRight(line, "\n")
592+
return NewStr(line).ToObject(), nil
593+
}
594+
562595
func builtinRepr(f *Frame, args Args, kwargs KWArgs) (*Object, *BaseException) {
563596
if raised := checkFunctionArgs(f, "repr", args, ObjectType); raised != nil {
564597
return nil, raised
@@ -693,6 +726,7 @@ func init() {
693726
"ord": newBuiltinFunction("ord", builtinOrd).ToObject(),
694727
"print": newBuiltinFunction("print", builtinPrint).ToObject(),
695728
"range": newBuiltinFunction("range", builtinRange).ToObject(),
729+
"raw_input": newBuiltinFunction("raw_input", builtinRawInput).ToObject(),
696730
"repr": newBuiltinFunction("repr", builtinRepr).ToObject(),
697731
"round": newBuiltinFunction("round", builtinRound).ToObject(),
698732
"setattr": newBuiltinFunction("setattr", builtinSetAttr).ToObject(),

runtime/builtin_types_test.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,60 @@ func TestBuiltinSetAttr(t *testing.T) {
425425
}
426426
}
427427

428+
func TestRawInput(t *testing.T) {
429+
fun := wrapFuncForTest(func(f *Frame, s string, args ...*Object) (*Object, *BaseException) {
430+
// Create a fake Stdin for input test.
431+
stdinFile, w, err := os.Pipe()
432+
if err != nil {
433+
return nil, f.RaiseType(RuntimeErrorType, fmt.Sprintf("failed to open pipe: %v", err))
434+
}
435+
436+
go func() {
437+
w.Write([]byte(s))
438+
w.Close()
439+
}()
440+
441+
oldStdin := Stdin
442+
Stdin = NewFileFromFD(stdinFile.Fd())
443+
defer func() {
444+
Stdin = oldStdin
445+
stdinFile.Close()
446+
}()
447+
448+
var input *Object
449+
output, raised := captureStdout(f, func() *BaseException {
450+
in, raised := builtinRawInput(f, args, nil)
451+
input = in
452+
return raised
453+
})
454+
455+
if raised != nil {
456+
return nil, raised
457+
}
458+
459+
return newTestTuple(input, output).ToObject(), nil
460+
})
461+
462+
cases := []invokeTestCase{
463+
{args: wrapArgs("HelloGrumpy\n", ""), want: newTestTuple("HelloGrumpy", "").ToObject()},
464+
{args: wrapArgs("HelloGrumpy\n", "ShouldBeShown\nShouldBeShown\t"), want: newTestTuple("HelloGrumpy", "ShouldBeShown\nShouldBeShown\t").ToObject()},
465+
{args: wrapArgs("HelloGrumpy\n", 5, 4), wantExc: mustCreateException(TypeErrorType, "[raw_]input expcted at most 1 arguments, got 2")},
466+
{args: wrapArgs("HelloGrumpy\nHelloGrumpy\n", ""), want: newTestTuple("HelloGrumpy", "").ToObject()},
467+
{args: wrapArgs("HelloGrumpy\nHelloGrumpy\n", "ShouldBeShown\nShouldBeShown\t"), want: newTestTuple("HelloGrumpy", "ShouldBeShown\nShouldBeShown\t").ToObject()},
468+
{args: wrapArgs("HelloGrumpy\nHelloGrumpy\n", 5, 4), wantExc: mustCreateException(TypeErrorType, "[raw_]input expcted at most 1 arguments, got 2")},
469+
{args: wrapArgs("", ""), wantExc: mustCreateException(EOFErrorType, "EOF when reading a line")},
470+
{args: wrapArgs("", "ShouldBeShown\nShouldBeShown\t"), wantExc: mustCreateException(EOFErrorType, "EOF when reading a line")},
471+
{args: wrapArgs("", 5, 4), wantExc: mustCreateException(TypeErrorType, "[raw_]input expcted at most 1 arguments, got 2")},
472+
}
473+
474+
for _, cas := range cases {
475+
if err := runInvokeTestCase(fun, &cas); err != "" {
476+
t.Error(err)
477+
}
478+
}
479+
480+
}
481+
428482
func newTestIndexObject(index int) *Object {
429483
indexType := newTestClass("Index", []*Type{ObjectType}, newStringDict(map[string]*Object{
430484
"__index__": newBuiltinFunction("__index__", func(f *Frame, _ Args, _ KWArgs) (*Object, *BaseException) {

runtime/exceptions.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ var (
2828
// EnvironmentErrorType corresponds to the Python type
2929
// 'EnvironmentError'.
3030
EnvironmentErrorType = newSimpleType("EnvironmentError", StandardErrorType)
31+
// EOFErrorType corresponds to the Python type 'EOFError'.
32+
EOFErrorType = newSimpleType("EOFError", StandardErrorType)
3133
// ExceptionType corresponds to the Python type 'Exception'.
3234
ExceptionType = newSimpleType("Exception", BaseExceptionType)
3335
// FutureWarningType corresponds to the Python type 'FutureWarning'.

runtime/file.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,6 @@ var (
361361
Stdin = NewFileFromFD(os.Stdin.Fd())
362362
// Stdout is an alias for sys.stdout.
363363
Stdout = NewFileFromFD(os.Stdout.Fd())
364-
// Stderr is an aliaas for sys.stderr.
364+
// Stderr is an alias for sys.stderr.
365365
Stderr = NewFileFromFD(os.Stderr.Fd())
366366
)

0 commit comments

Comments
 (0)