diff --git a/Lib/lib2to3/fixer_util.py b/Lib/lib2to3/fixer_util.py index 2b5bb1dfd27..60d219f5770 100644 --- a/Lib/lib2to3/fixer_util.py +++ b/Lib/lib2to3/fixer_util.py @@ -165,7 +165,7 @@ def parenthesize(node): consuming_calls = set(["sorted", "list", "set", "any", "all", "tuple", "sum", - "min", "max"]) + "min", "max", "enumerate"]) def attr_chain(obj, attr): """Follow an attribute chain. @@ -192,14 +192,14 @@ p0 = """for_stmt< 'for' any 'in' node=any ':' any* > p1 = """ power< ( 'iter' | 'list' | 'tuple' | 'sorted' | 'set' | 'sum' | - 'any' | 'all' | (any* trailer< '.' 'join' >) ) + 'any' | 'all' | 'enumerate' | (any* trailer< '.' 'join' >) ) trailer< '(' node=any ')' > any* > """ p2 = """ power< - 'sorted' + ( 'sorted' | 'enumerate' ) trailer< '(' arglist ')' > any* > @@ -207,14 +207,14 @@ power< pats_built = False def in_special_context(node): """ Returns true if node is in an environment where all that is required - of it is being itterable (ie, it doesn't matter if it returns a list - or an itterator). + of it is being iterable (ie, it doesn't matter if it returns a list + or an iterator). See test_map_nochange in test_fixers.py for some examples and tests. """ global p0, p1, p2, pats_built if not pats_built: - p1 = patcomp.compile_pattern(p1) p0 = patcomp.compile_pattern(p0) + p1 = patcomp.compile_pattern(p1) p2 = patcomp.compile_pattern(p2) pats_built = True patterns = [p0, p1, p2] diff --git a/Lib/lib2to3/tests/test_fixers.py b/Lib/lib2to3/tests/test_fixers.py index 43184e11ed8..914b3bf9287 100644 --- a/Lib/lib2to3/tests/test_fixers.py +++ b/Lib/lib2to3/tests/test_fixers.py @@ -2981,6 +2981,10 @@ class Test_filter(FixerTestCase): self.unchanged(a) a = """sorted(filter(f, 'abc'), key=blah)[0]""" self.unchanged(a) + a = """enumerate(filter(f, 'abc'))""" + self.unchanged(a) + a = """enumerate(filter(f, 'abc'), start=1)""" + self.unchanged(a) a = """for i in filter(f, 'abc'): pass""" self.unchanged(a) a = """[x for x in filter(f, 'abc')]""" @@ -3089,6 +3093,10 @@ class Test_map(FixerTestCase): self.unchanged(a) a = """sorted(map(f, 'abc'), key=blah)[0]""" self.unchanged(a) + a = """enumerate(map(f, 'abc'))""" + self.unchanged(a) + a = """enumerate(map(f, 'abc'), start=1)""" + self.unchanged(a) a = """for i in map(f, 'abc'): pass""" self.unchanged(a) a = """[x for x in map(f, 'abc')]""" @@ -3152,6 +3160,10 @@ class Test_zip(FixerTestCase): self.unchanged(a) a = """sorted(zip(a, b), key=blah)[0]""" self.unchanged(a) + a = """enumerate(zip(a, b))""" + self.unchanged(a) + a = """enumerate(zip(a, b), start=1)""" + self.unchanged(a) a = """for i in zip(a, b): pass""" self.unchanged(a) a = """[x for x in zip(a, b)]""" diff --git a/Misc/NEWS b/Misc/NEWS index 7fd47395c68..5fe7d1d18f0 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -143,6 +143,10 @@ Library - Issue #16333: use (",", ": ") as default separator when indent is specified to avoid trailing whitespace. Patch by Serhiy Storchaka. +- Issue #16573: In 2to3, treat enumerate() like a consuming call, so superfluous + list() calls aren't added to filter(), map(), and zip() which are directly + passed enumerate(). + - Issue #16549: Make json.tool work again on Python 3 and add tests. Initial patch by Berker Peksag and Serhiy Storchaka.