From b87c9a5efbb5b9487f64e31c0598920ab0fd6e53 Mon Sep 17 00:00:00 2001 From: Ashley Whetter Date: Fri, 3 Jul 2020 10:06:40 -0700 Subject: [PATCH] bpo-41110: Fixed lib2to3 reporting some unchanged files as needing modification --- Lib/lib2to3/fixes/fix_dict.py | 2 ++ Lib/lib2to3/fixes/fix_except.py | 5 ++++ Lib/lib2to3/fixes/fix_isinstance.py | 10 +++++-- Lib/lib2to3/fixes/fix_numliterals.py | 23 +++++++++----- Lib/lib2to3/fixes/fix_raise.py | 5 ++++ Lib/lib2to3/fixes/fix_unicode.py | 2 +- Lib/lib2to3/fixes/fix_ws_comma.py | 5 +++- Lib/lib2to3/tests/test_fixers.py | 30 ++++++++++++------- .../2020-07-03-10-45-39.bpo-41110.GId8oe.rst | 1 + 9 files changed, 60 insertions(+), 23 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2020-07-03-10-45-39.bpo-41110.GId8oe.rst diff --git a/Lib/lib2to3/fixes/fix_dict.py b/Lib/lib2to3/fixes/fix_dict.py index d3655c9f1b2d9b..3ee7c81ff25c60 100644 --- a/Lib/lib2to3/fixes/fix_dict.py +++ b/Lib/lib2to3/fixes/fix_dict.py @@ -65,6 +65,8 @@ def transform(self, node, results): head = [n.clone() for n in head] tail = [n.clone() for n in tail] special = not tail and self.in_special_context(node, isiter) + if special and not (isiter or isview): + return None args = head + [pytree.Node(syms.trailer, [Dot(), Name(method_name, diff --git a/Lib/lib2to3/fixes/fix_except.py b/Lib/lib2to3/fixes/fix_except.py index 49bd3d5ab7d6cc..3074a6e3be9e83 100644 --- a/Lib/lib2to3/fixes/fix_except.py +++ b/Lib/lib2to3/fixes/fix_except.py @@ -50,10 +50,12 @@ def transform(self, node, results): tail = [n.clone() for n in results["tail"]] try_cleanup = [ch.clone() for ch in results["cleanup"]] + changed = False for except_clause, e_suite in find_excepts(try_cleanup): if len(except_clause.children) == 4: (E, comma, N) = except_clause.children[1:4] comma.replace(Name("as", prefix=" ")) + changed = True if N.type != token.NAME: # Generate a new N for the except clause @@ -88,6 +90,9 @@ def transform(self, node, results): # not so much. N.prefix = " " + if not changed: + return None + #TODO(cwinter) fix this when children becomes a smart list children = [c.clone() for c in node.children[:3]] + try_cleanup + tail return pytree.Node(node.type, children) diff --git a/Lib/lib2to3/fixes/fix_isinstance.py b/Lib/lib2to3/fixes/fix_isinstance.py index bebb1de120424b..1a06af025759af 100644 --- a/Lib/lib2to3/fixes/fix_isinstance.py +++ b/Lib/lib2to3/fixes/fix_isinstance.py @@ -32,8 +32,10 @@ def transform(self, node, results): args = testlist.children new_args = [] iterator = enumerate(args) + changed = False for idx, arg in iterator: if arg.type == token.NAME and arg.value in names_inserted: + changed = True if idx < len(args) - 1 and args[idx + 1].type == token.COMMA: next(iterator) continue @@ -42,11 +44,13 @@ def transform(self, node, results): if arg.type == token.NAME: names_inserted.add(arg.value) if new_args and new_args[-1].type == token.COMMA: + changed = True del new_args[-1] - if len(new_args) == 1: - atom = testlist.parent + atom = testlist.parent + if len(new_args) == 1 and new_args[0].prefix != atom.prefix: + changed = True new_args[0].prefix = atom.prefix atom.replace(new_args[0]) - else: + if changed: args[:] = new_args node.changed() diff --git a/Lib/lib2to3/fixes/fix_numliterals.py b/Lib/lib2to3/fixes/fix_numliterals.py index 79207d4aa368ae..476191bde4dc1e 100644 --- a/Lib/lib2to3/fixes/fix_numliterals.py +++ b/Lib/lib2to3/fixes/fix_numliterals.py @@ -14,15 +14,24 @@ class FixNumliterals(fixer_base.BaseFix): _accept_type = token.NUMBER + def is_long(self, node): + return node.value[-1] in 'Ll' + + def is_octal(self, node): + return ( + node.value.startswith("0") + and node.value.isdigit() + and len(set(node.value)) > 1 + ) + def match(self, node): # Override - return (node.value.startswith("0") or node.value[-1] in "Ll") + return self.is_long(node) or self.is_octal(node) def transform(self, node, results): - val = node.value - if val[-1] in 'Ll': - val = val[:-1] - elif val.startswith('0') and val.isdigit() and len(set(val)) > 1: - val = "0o" + val[1:] + if self.is_long(node): + return Number(node.value[:-1], prefix=node.prefix) + elif self.is_octal(node): + return Number("0o" + node.value[1:], prefix=node.prefix) - return Number(val, prefix=node.prefix) + return None diff --git a/Lib/lib2to3/fixes/fix_raise.py b/Lib/lib2to3/fixes/fix_raise.py index 05aa21e74a30ff..bd15e626673166 100644 --- a/Lib/lib2to3/fixes/fix_raise.py +++ b/Lib/lib2to3/fixes/fix_raise.py @@ -37,6 +37,7 @@ class FixRaise(fixer_base.BaseFix): def transform(self, node, results): syms = self.syms + changed = False exc = results["exc"].clone() if exc.type == token.STRING: @@ -56,8 +57,12 @@ def transform(self, node, results): # exc.children[1].children[0] is the first element of the tuple exc = exc.children[1].children[0].clone() exc.prefix = " " + changed = True if "val" not in results: + if not changed: + return None + # One-argument raise new = pytree.Node(syms.raise_stmt, [Name("raise"), exc]) new.prefix = node.prefix diff --git a/Lib/lib2to3/fixes/fix_unicode.py b/Lib/lib2to3/fixes/fix_unicode.py index c7982c2b97c3e1..e6a5c66d61d1a6 100644 --- a/Lib/lib2to3/fixes/fix_unicode.py +++ b/Lib/lib2to3/fixes/fix_unicode.py @@ -36,7 +36,7 @@ def transform(self, node, results): if val[0] in 'uU': val = val[1:] if val == node.value: - return node + return new = node.clone() new.value = val return new diff --git a/Lib/lib2to3/fixes/fix_ws_comma.py b/Lib/lib2to3/fixes/fix_ws_comma.py index a54a376c472afb..4e01835c0a2987 100644 --- a/Lib/lib2to3/fixes/fix_ws_comma.py +++ b/Lib/lib2to3/fixes/fix_ws_comma.py @@ -24,16 +24,19 @@ class FixWsComma(fixer_base.BaseFix): def transform(self, node, results): new = node.clone() comma = False + changed = False for child in new.children: if child in self.SEPS: prefix = child.prefix if prefix.isspace() and "\n" not in prefix: child.prefix = "" + changed = True comma = True else: if comma: prefix = child.prefix if not prefix: child.prefix = " " + changed = True comma = False - return new + return new if changed else None diff --git a/Lib/lib2to3/tests/test_fixers.py b/Lib/lib2to3/tests/test_fixers.py index 121ebe68e5402b..c24b2e8eb66712 100644 --- a/Lib/lib2to3/tests/test_fixers.py +++ b/Lib/lib2to3/tests/test_fixers.py @@ -48,7 +48,8 @@ def warns_unchanged(self, before, message): self.warns(before, before, message, unchanged=True) def unchanged(self, before, ignore_warnings=False): - self._check(before, before) + tree = self._check(before, before) + self.assertFalse(tree.was_changed) if not ignore_warnings: self.assertEqual(self.fixer_log, []) @@ -955,6 +956,10 @@ def test_tuple_exc_2(self): a = """raise E1(V)""" self.check(b, a) + def test_unchanged(self): + a = """raise E1(V)""" + self.unchanged(a) + # These should produce a warning def test_string_exc(self): @@ -2776,6 +2781,10 @@ def test_unchanged_int(self): def test_unchanged_float(self): s = """5.0""" self.unchanged(s) + s = """0.1""" + self.unchanged(s) + s = """000""" + self.unchanged(s) def test_unchanged_octal(self): s = """0o755""" @@ -2895,18 +2904,15 @@ def test_native_literal_escape_u(self): a = r"""'\\\\u20ac\\U0001d121\\u20ac'""" self.check(b, a) - b = r"""r'\\\u20ac\U0001d121\\u20ac'""" a = r"""r'\\\u20ac\U0001d121\\u20ac'""" - self.check(b, a) + self.unchanged(a) def test_bytes_literal_escape_u(self): - b = r"""b'\\\u20ac\U0001d121\\u20ac'""" a = r"""b'\\\u20ac\U0001d121\\u20ac'""" - self.check(b, a) + self.unchanged(a) - b = r"""br'\\\u20ac\U0001d121\\u20ac'""" a = r"""br'\\\u20ac\U0001d121\\u20ac'""" - self.check(b, a) + self.unchanged(a) def test_unicode_literal_escape_u(self): b = r"""u'\\\u20ac\U0001d121\\u20ac'""" @@ -2919,13 +2925,15 @@ def test_unicode_literal_escape_u(self): def test_native_unicode_literal_escape_u(self): f = 'from __future__ import unicode_literals\n' - b = f + r"""'\\\u20ac\U0001d121\\u20ac'""" a = f + r"""'\\\u20ac\U0001d121\\u20ac'""" - self.check(b, a) + self.unchanged(a) - b = f + r"""r'\\\u20ac\U0001d121\\u20ac'""" a = f + r"""r'\\\u20ac\U0001d121\\u20ac'""" - self.check(b, a) + self.unchanged(a) + + def test_unchanged(self): + a = """'h'""" + self.unchanged(a) class Test_filter(FixerTestCase): diff --git a/Misc/NEWS.d/next/Library/2020-07-03-10-45-39.bpo-41110.GId8oe.rst b/Misc/NEWS.d/next/Library/2020-07-03-10-45-39.bpo-41110.GId8oe.rst new file mode 100644 index 00000000000000..2dc953c81f73dc --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-07-03-10-45-39.bpo-41110.GId8oe.rst @@ -0,0 +1 @@ +Fixed lib2to3 reporting some unchanged files as needing modification.