Repository: xonsh/xonsh

Issue:
A trailing comma in the import list raises syntax error
A trailing comma in the import list raises syntax error (it is valid Python)

```
$ from x import (y, z,)
.
  File "<string>", line None
SyntaxError: <xonsh-code>:1:20: ('code: )',)
from x import (y, z,)
                    ^
```
I have tried and failed to fix it my self :( 

I thought it should be handled by this: 
https://github.com/xonsh/xonsh/blob/master/xonsh/parsers/base.py#L1471-L1478

Or am I wrong here...



Discussion:
I'd say that you are right and that the culprit is the `shift/reduce conflict for COMMA resolved as shift` in
```
state 845

    (37) comma_import_as_name_list_opt -> comma_import_as_name_list .
    (121) comma_import_as_name_list -> comma_import_as_name_list . comma_import_as_name
    (390) comma_import_as_name -> . COMMA import_as_name

  ! shift/reduce conflict for COMMA resolved as shift
    SEMI            reduce using rule 37 (comma_import_as_name_list_opt -> comma_import_as_name_list .)
    NEWLINE         reduce using rule 37 (comma_import_as_name_list_opt -> comma_import_as_name_list .)
    RPAREN          reduce using rule 37 (comma_import_as_name_list_opt -> comma_import_as_name_list .)
    COMMA           shift and go to state 847

  ! COMMA           [ reduce using rule 37 (comma_import_as_name_list_opt -> comma_import_as_name_list .) ]

    comma_import_as_name           shift and go to state 1151
```
d3083f6 works for me.
@melund What do you think?
Edit: Never mind. I'm an idiot. With the above patch you can do
```
from x import y z
from x import (y z)
```

Resolving patch:
diff --git a/xonsh/parsers/base.py b/xonsh/parsers/base.py
--- a/xonsh/parsers/base.py
+++ b/xonsh/parsers/base.py
@@ -1425,7 +1425,7 @@ def p_import_from_post_as(self, p):
         p[0] = p[1]
 
     def p_import_from_post_paren(self, p):
-        """import_from_post : LPAREN import_as_names RPAREN"""
+        """import_from_post : LPAREN import_as_names"""
         p[0] = p[2]
 
     def p_import_from(self, p):
@@ -1459,6 +1459,10 @@ def p_comma_import_as_name(self, p):
         """
         p[0] = [p[2]]
 
+    def p_comma_import_as_name_tail(self, p):
+        """comma_import_as_name : comma_opt RPAREN"""
+        p[0] = list()
+
     def p_dotted_as_name(self, p):
         """dotted_as_name : dotted_name as_name_opt"""
         p0 = ast.alias(name=p[1], asname=p[2])
@@ -1469,8 +1473,7 @@ def p_comma_dotted_as_name(self, p):
         p[0] = [p[2]]
 
     def p_import_as_names(self, p):
-        """import_as_names : import_as_name comma_import_as_name_list_opt comma_opt
-        """
+        """import_as_names : import_as_name comma_import_as_name_list_opt"""
         p1, p2 = p[1], p[2]
         p0 = [p1]
         if p2 is not None:


Test patch:
diff --git a/tests/test_parser.py b/tests/test_parser.py
--- a/tests/test_parser.py
+++ b/tests/test_parser.py
@@ -1486,6 +1486,14 @@ def test_from_x_import_star():
     check_stmts("from x import *", False)
 
 
+def test_from_x_import_group_x_y_z():
+    check_stmts("from x import (x, y, z)", False)
+
+
+def test_from_x_import_group_x_y_z_comma():
+    check_stmts("from x import (x, y, z,)", False)
+
+
 def test_from_x_import_y_as_z():
     check_stmts("from x import y as z", False)