Repository: go-python/gpython
Pull request #177 (2022-04-10 17:31:51)

Improve some things around how errors are reported when parsing a file
Given the malformed input "/Users/jpoole/gpython/test.py":
```
def foo(name : str):
    return name

foo(


foo(name = "test"))

foo(

```

Before:
```
Exception &py.Exception{Base:(*py.Type)(0xc00012dc20), Args:py.Tuple{"invalid syntax"}, Traceback:py.Object(nil), Context:py.Object(nil), Cause:py.Object(nil), SuppressContext:false, Dict:py.StringDict{"filename":"<string>", "line":"", "lineno":10, "offset":0}}
-- No traceback available --
2022/04/10 18:31:19 
  File "<string>", line 10, offset 0
    

SyntaxError: 'invalid syntax'
```

After 
```
Exception 
  File "/Users/jpoole/gpython/test.py", line 10, offset 0
    

SyntaxError: 'unexpected EOF while parsing'
-- No traceback available --

```

Tatskaari: > apologies for dropping the ball.
> 
> LGTM, modulo some tests that need to be fixed.
> 
> thanks for the PR.

Nice! Fixed the tests up. They pass locally now. 
sbinet: there's one remaining error, though:
```
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: "name 'aksfjakf' is not defined"
--- FAIL: TestREPL (0.00s)
    repl_test.go:32: compileError: Output wrong, want "Compile error: \n  File \"<string>\", line 1, offset 2\n    if\n\n\nSyntaxError: 'invalid syntax'" got "Compile error: \n  File \"<stdin>\", line 1, offset 2\n    if\n\n\nSyntaxError: 'invalid syntax'"
FAIL
FAIL	github.com/go-python/gpython/repl	0.003s
```
sbinet: needs https://github.com/go-python/license/pull/17   
sbinet: I took the liberty of fixing the last remaining error and pushing my changes, so I could merge this PR in :)

thanks a lot.

Patch:
diff --git a/compile/compile.go b/compile/compile.go
index 775717a..6b9d926 100644
--- a/compile/compile.go
+++ b/compile/compile.go
@@ -9,6 +9,7 @@ package compile
 // FIXME kill ast.Identifier and turn into string?
 
 import (
+	"bytes"
 	"fmt"
 	"log"
 	"strings"
@@ -107,7 +108,7 @@ func init() {
 // in addition to any features explicitly specified.
 func Compile(src, srcDesc string, mode py.CompileMode, futureFlags int, dont_inherit bool) (*py.Code, error) {
 	// Parse Ast
-	Ast, err := parser.ParseString(src, mode)
+	Ast, err := parser.Parse(bytes.NewBufferString(src), srcDesc, mode)
 	if err != nil {
 		return nil, err
 	}
diff --git a/main.go b/main.go
index bc906aa..4598a62 100644
--- a/main.go
+++ b/main.go
@@ -78,7 +78,7 @@ func xmain(args []string) {
 		_, err := py.RunFile(ctx, args[0], py.CompileOpts{}, nil)
 		if err != nil {
 			py.TracebackDump(err)
-			log.Fatal(err)
+			os.Exit(1)
 		}
 	}
 }
diff --git a/parser/lexer.go b/parser/lexer.go
index 7684789..801215b 100644
--- a/parser/lexer.go
+++ b/parser/lexer.go
@@ -916,7 +916,7 @@ func (x *yyLex) SyntaxErrorf(format string, a ...interface{}) {
 func (x *yyLex) ErrorReturn() error {
 	if x.error {
 		if x.errorString == "" {
-			if x.eof && x.interactive {
+			if x.eof {
 				x.errorString = "unexpected EOF while parsing"
 			} else {
 				x.errorString = "invalid syntax"
diff --git a/py/traceback.go b/py/traceback.go
index bf7ba6d..6dcc9ce 100644
--- a/py/traceback.go
+++ b/py/traceback.go
@@ -64,10 +64,10 @@ func TracebackDump(err interface{}) {
 	case *ExceptionInfo:
 		e.TracebackDump(os.Stderr)
 	case *Exception:
-		fmt.Fprintf(os.Stderr, "Exception %#v\n", e)
+		fmt.Fprintf(os.Stderr, "Exception %v\n", e)
 		fmt.Fprintf(os.Stderr, "-- No traceback available --\n")
 	default:
-		fmt.Fprintf(os.Stderr, "Error %#v\n", err)
+		fmt.Fprintf(os.Stderr, "Error %v\n", err)
 		fmt.Fprintf(os.Stderr, "-- No traceback available --\n")
 	}
 }


Test patch:
diff --git a/parser/grammar_data_test.go b/parser/grammar_data_test.go
index 4079325..b0b53ee 100644
--- a/parser/grammar_data_test.go
+++ b/parser/grammar_data_test.go
@@ -33,8 +33,8 @@ var grammarTestData = []struct {
 	{"b'abc' b'''123'''", "eval", "Expression(body=Bytes(s=b'abc123'))", nil, ""},
 	{"1234", "eval", "Expression(body=Num(n=1234))", nil, ""},
 	{"01234", "eval", "", py.SyntaxError, "illegal decimal with leading zero"},
-	{"1234d", "eval", "", py.SyntaxError, "invalid syntax"},
-	{"1234d", "exec", "", py.SyntaxError, "invalid syntax"},
+	{"1234d", "eval", "", py.SyntaxError, "unexpected EOF while parsing"},
+	{"1234d", "exec", "", py.SyntaxError, "unexpected EOF while parsing"},
 	{"1234d", "single", "", py.SyntaxError, "unexpected EOF while parsing"},
 	{"0x1234", "eval", "Expression(body=Num(n=4660))", nil, ""},
 	{"12.34", "eval", "Expression(body=Num(n=12.34))", nil, ""},
@@ -325,10 +325,10 @@ var grammarTestData = []struct {
 	{"pass\n", "single", "Interactive(body=[Pass()])", nil, ""},
 	{"if True:\n   pass\n\n", "single", "Interactive(body=[If(test=NameConstant(value=True), body=[Pass()], orelse=[])])", nil, ""},
 	{"while True:\n pass\nelse:\n return\n", "single", "Interactive(body=[While(test=NameConstant(value=True), body=[Pass()], orelse=[Return(value=None)])])", nil, ""},
-	{"a='potato", "eval", "", py.SyntaxError, "invalid syntax"},
+	{"a='potato", "eval", "", py.SyntaxError, "unexpected EOF while parsing"},
 	{"a='potato", "exec", "", py.SyntaxError, "EOL while scanning string literal"},
 	{"a='potato", "single", "", py.SyntaxError, "EOL while scanning string literal"},
-	{"a='''potato", "eval", "", py.SyntaxError, "invalid syntax"},
+	{"a='''potato", "eval", "", py.SyntaxError, "unexpected EOF while parsing"},
 	{"a='''potato", "exec", "", py.SyntaxError, "EOF while scanning triple-quoted string literal"},
 	{"a='''potato", "single", "", py.SyntaxError, "EOF while scanning triple-quoted string literal"},
 }
diff --git a/repl/repl_test.go b/repl/repl_test.go
index 0639523..b154bfe 100644
--- a/repl/repl_test.go
+++ b/repl/repl_test.go
@@ -25,6 +25,7 @@ func (rt *replTest) Print(out string) {
 }
 
 func (rt *replTest) assert(t *testing.T, what, wantPrompt, wantOut string) {
+	t.Helper()
 	if rt.prompt != wantPrompt {
 		t.Errorf("%s: Prompt wrong:\ngot= %q\nwant=%q", what, rt.prompt, wantPrompt)
 	}
@@ -63,7 +64,7 @@ func TestREPL(t *testing.T) {
 	rt.assert(t, "multi#5", NormalPrompt, "45")
 
 	r.Run("if")
-	rt.assert(t, "compileError", NormalPrompt, "Compile error: \n  File \"<string>\", line 1, offset 2\n    if\n\n\nSyntaxError: 'invalid syntax'")
+	rt.assert(t, "compileError", NormalPrompt, "Compile error: \n  File \"<stdin>\", line 1, offset 2\n    if\n\n\nSyntaxError: 'invalid syntax'")
 
 	// test comments in the REPL work properly
 	r.Run("# this is a comment")