### 18.5a0 (unreleased)
 
-* Slices are now formatted according to PEP 8 (#178)
+* slices are now formatted according to PEP 8 (#178)
 
-* Empty parentheses in a class definition are removed (#145, #180)
+* empty parentheses in a class definition are now removed (#145, #180)
+
+* fixed an invalid trailing comma sometimes left in imports (#185)
+
+* fixed non-deterministic formatting when multiple pairs of removable parentheses
+  were used (#183)
 
 
 ### 18.4a4
 
     for child in list(node.children):
         if check_lpar:
             if child.type == syms.atom:
-                if not (
-                    is_empty_tuple(child)
-                    or is_one_tuple(child)
-                    or max_delimiter_priority_in_atom(child) >= COMMA_PRIORITY
-                ):
-                    first = child.children[0]
-                    last = child.children[-1]
-                    if first.type == token.LPAR and last.type == token.RPAR:
-                        # make parentheses invisible
-                        first.value = ""  # type: ignore
-                        last.value = ""  # type: ignore
+                maybe_make_parens_invisible_in_atom(child)
             elif is_one_tuple(child):
                 # wrap child in visible parentheses
                 lpar = Leaf(token.LPAR, "(")
         check_lpar = isinstance(child, Leaf) and child.value in parens_after
 
 
+def maybe_make_parens_invisible_in_atom(node: LN) -> bool:
+    """If it's safe, make the parens in the atom `node` invisible, recusively."""
+    if (
+        node.type != syms.atom
+        or is_empty_tuple(node)
+        or is_one_tuple(node)
+        or max_delimiter_priority_in_atom(node) >= COMMA_PRIORITY
+    ):
+        return False
+
+    first = node.children[0]
+    last = node.children[-1]
+    if first.type == token.LPAR and last.type == token.RPAR:
+        # make parentheses invisible
+        first.value = ""  # type: ignore
+        last.value = ""  # type: ignore
+        if len(node.children) > 1:
+            maybe_make_parens_invisible_in_atom(node.children[1])
+        return True
+
+    return False
+
+
 def is_empty_tuple(node: LN) -> bool:
     """Return True if `node` holds an empty tuple."""
     return (
 
 
 .. autofunction:: black.make_comment
 
+.. autofunction:: black.maybe_make_parens_invisible_in_atom
+
 .. autofunction:: black.max_delimiter_priority_in_atom
 
 .. autofunction:: black.normalize_prefix
 
  ]
  slice[0]
  slice[0:1]
-@@ -123,88 +145,114 @@
+@@ -123,91 +145,119 @@
  numpy[-(c + 1) :, d]
  numpy[:, l[-2]]
  numpy[:, ::-1]
 +print(*[] or [1])
  print(**{1: 3} if False else {x: x for x in range(3)})
 -print(* lambda x: x)
+-assert(not Test),("Short message")
+-assert this is ComplexTest and not requirements.fit_in_a_single_line(force=False), "Short message"
+-assert(((parens is TooMany)))
 -for x, in (1,), (2,), (3,): ...
 -for y in (): ...
 -for z in (i for i in (1, 2, 3)): ...
 -    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa /
 -    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 +print(*lambda x: x)
++assert not Test, "Short message"
++assert (
++    this is ComplexTest and not requirements.fit_in_a_single_line(force=False)
++), "Short message"
++assert parens is TooMany
 +for (x,) in (1,), (2,), (3,):
 +    ...
 +for y in ():
 
 print(* [] or [1])
 print(**{1: 3} if False else {x: x for x in range(3)})
 print(* lambda x: x)
+assert(not Test),("Short message")
+assert this is ComplexTest and not requirements.fit_in_a_single_line(force=False), "Short message"
+assert(((parens is TooMany)))
 for x, in (1,), (2,), (3,): ...
 for y in (): ...
 for z in (i for i in (1, 2, 3)): ...
 print(*[] or [1])
 print(**{1: 3} if False else {x: x for x in range(3)})
 print(*lambda x: x)
+assert not Test, "Short message"
+assert (
+    this is ComplexTest and not requirements.fit_in_a_single_line(force=False)
+), "Short message"
+assert parens is TooMany
 for (x,) in (1,), (2,), (3,):
     ...
 for y in ():