unparser: Don't omit parenthesis when unparsing a slice
Backport of
  c102a14825
Includes support for Python 2.
			
			
This commit is contained in:
		 Todd Gamblin
					Todd Gamblin
				
			
				
					committed by
					
						 Greg Becker
						Greg Becker
					
				
			
			
				
	
			
			
			 Greg Becker
						Greg Becker
					
				
			
						parent
						
							0776c3b4d6
						
					
				
				
					commit
					39afe946a0
				
			| @@ -65,6 +65,22 @@ def interleave(inter, f, seq): | ||||
|             f(x) | ||||
| 
 | ||||
| 
 | ||||
| def is_simple_tuple(slice_value): | ||||
|     # when unparsing a non-empty tuple, the parantheses can be safely | ||||
|     # omitted if there aren't any elements that explicitly requires | ||||
|     # parantheses (such as starred expressions). | ||||
|     return ( | ||||
|         isinstance(slice_value, ast.Tuple) | ||||
|         and slice_value.elts | ||||
|         and ( | ||||
|             # Python 2 doesn't allow starred elements in tuples like Python 3 | ||||
|             six.PY2 or not any( | ||||
|                 isinstance(elt, ast.Starred) for elt in slice_value.elts | ||||
|             ) | ||||
|         ) | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
| class Unparser: | ||||
|     """Methods in this class recursively traverse an AST and | ||||
|     output source code for the abstract syntax; original formatting | ||||
| @@ -103,6 +119,16 @@ def __init__(self, py_ver_consistent=False): | ||||
|         self._py_ver_consistent = py_ver_consistent | ||||
|         self._precedences = {} | ||||
| 
 | ||||
|     def items_view(self, traverser, items): | ||||
|         """Traverse and separate the given *items* with a comma and append it to | ||||
|         the buffer. If *items* is a single item sequence, a trailing comma | ||||
|         will be added.""" | ||||
|         if len(items) == 1: | ||||
|             traverser(items[0]) | ||||
|             self.write(",") | ||||
|         else: | ||||
|             interleave(lambda: self.write(", "), traverser, items) | ||||
| 
 | ||||
|     def visit(self, tree, output_file): | ||||
|         """Traverse tree and write source code to output_file.""" | ||||
|         self.f = output_file | ||||
| @@ -657,11 +683,7 @@ def _Constant(self, t): | ||||
|         value = t.value | ||||
|         if isinstance(value, tuple): | ||||
|             with self.delimit("(", ")"): | ||||
|                 if len(value) == 1: | ||||
|                     self._write_constant(value[0]) | ||||
|                     self.write(",") | ||||
|                 else: | ||||
|                     interleave(lambda: self.write(", "), self._write_constant, value) | ||||
|                 self.items_view(self._write_constant, value) | ||||
|         elif value is Ellipsis:  # instead of `...` for Py2 compatibility | ||||
|             self.write("...") | ||||
|         else: | ||||
| @@ -762,12 +784,7 @@ def write_item(item): | ||||
| 
 | ||||
|     def _Tuple(self, t): | ||||
|         with self.delimit("(", ")"): | ||||
|             if len(t.elts) == 1: | ||||
|                 elt = t.elts[0] | ||||
|                 self.dispatch(elt) | ||||
|                 self.write(",") | ||||
|             else: | ||||
|                 interleave(lambda: self.write(", "), self.dispatch, t.elts) | ||||
|             self.items_view(self.dispatch, t.elts) | ||||
| 
 | ||||
|     unop = { | ||||
|         "Invert": "~", | ||||
| @@ -974,7 +991,10 @@ def _Subscript(self, t): | ||||
|         self.set_precedence(_Precedence.ATOM, t.value) | ||||
|         self.dispatch(t.value) | ||||
|         with self.delimit("[", "]"): | ||||
|             self.dispatch(t.slice) | ||||
|             if is_simple_tuple(t.slice): | ||||
|                 self.items_view(self.dispatch, t.slice.elts) | ||||
|             else: | ||||
|                 self.dispatch(t.slice) | ||||
| 
 | ||||
|     def _Starred(self, t): | ||||
|         self.write("*") | ||||
| @@ -985,9 +1005,14 @@ def _Starred(self, t): | ||||
|     def _Ellipsis(self, t): | ||||
|         self.write("...") | ||||
| 
 | ||||
|     # used in Python <= 3.8 -- see _Subscript for 3.9+ | ||||
|     def _Index(self, t): | ||||
|         self.set_precedence(_Precedence.TUPLE, t.value) | ||||
|         self.dispatch(t.value) | ||||
|         if is_simple_tuple(t.value): | ||||
|             self.set_precedence(_Precedence.ATOM, t.value) | ||||
|             self.items_view(self.dispatch, t.value.elts) | ||||
|         else: | ||||
|             self.set_precedence(_Precedence.TUPLE, t.value) | ||||
|             self.dispatch(t.value) | ||||
| 
 | ||||
|     def _Slice(self, t): | ||||
|         if t.lower: | ||||
|   | ||||
		Reference in New Issue
	
	Block a user