From: Martin v. Löwis Date: Fri, 2 May 2008 21:30:20 +0000 (+0000) Subject: Merged revisions 62263-62646 via svnmerge from X-Git-Tag: v2.6a3~55 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6780a9dd9f8e8c79b9215e1f6e98cb5f711561bc;p=python Merged revisions 62263-62646 via svnmerge from svn+ssh://pythondev@svn.python.org/sandbox/trunk/2to3/lib2to3 ........ r62470 | david.wolever | 2008-04-24 02:11:07 +0200 (Do, 24 Apr 2008) | 3 lines Fixed up and applied the patch for #2431 -- speeding up 2to3 with a lookup table. ........ r62646 | martin.v.loewis | 2008-05-02 23:29:27 +0200 (Fr, 02 Mai 2008) | 2 lines Fix whitespace. ........ --- diff --git a/Lib/lib2to3/refactor.py b/Lib/lib2to3/refactor.py index 74a40539c0..6057caf79a 100755 --- a/Lib/lib2to3/refactor.py +++ b/Lib/lib2to3/refactor.py @@ -18,6 +18,8 @@ import sys import difflib import optparse import logging +from collections import defaultdict +from itertools import chain # Local imports from .pgen2 import driver @@ -96,6 +98,43 @@ def get_all_fix_names(): fix_names.sort() return fix_names +def get_head_types(pat): + """ Accepts a pytree Pattern Node and returns a set + of the pattern types which will match first. """ + + if isinstance(pat, (pytree.NodePattern, pytree.LeafPattern)): + # NodePatters must either have no type and no content + # or a type and content -- so they don't get any farther + # Always return leafs + return set([pat.type]) + + if isinstance(pat, pytree.NegatedPattern): + if pat.content: + return get_head_types(pat.content) + return set([None]) # Negated Patterns don't have a type + + if isinstance(pat, pytree.WildcardPattern): + # Recurse on each node in content + r = set() + for p in pat.content: + for x in p: + r.update(get_head_types(x)) + return r + + raise Exception("Oh no! I don't understand pattern %s" %(pat)) + +def get_headnode_dict(fixer_list): + """ Accepts a list of fixers and returns a dictionary + of head node type --> fixer list. """ + head_nodes = defaultdict(list) + for fixer in fixer_list: + if not fixer.pattern: + head_nodes[None].append(fixer) + continue + for t in get_head_types(fixer.pattern): + head_nodes[t].append(fixer) + return head_nodes + class RefactoringTool(object): @@ -114,6 +153,10 @@ class RefactoringTool(object): convert=pytree.convert, logger=self.logger) self.pre_order, self.post_order = self.get_fixers() + + self.pre_order = get_headnode_dict(self.pre_order) + self.post_order = get_headnode_dict(self.post_order) + self.files = [] # List of files that were or should be modified def get_fixers(self): @@ -286,7 +329,11 @@ class RefactoringTool(object): Returns: True if the tree was modified, False otherwise. """ - all_fixers = self.pre_order + self.post_order + # Two calls to chain are required because pre_order.values() + # will be a list of lists of fixers: + # [[, ], []] + all_fixers = chain(chain(*self.pre_order.values()),\ + chain(*self.post_order.values())) for fixer in all_fixers: fixer.start_tree(tree, name) @@ -312,7 +359,7 @@ class RefactoringTool(object): if not fixers: return for node in traversal: - for fixer in fixers: + for fixer in fixers[node.type] + fixers[None]: results = fixer.match(node) if results: new = fixer.transform(node, results) diff --git a/Lib/lib2to3/tests/test_fixers.py b/Lib/lib2to3/tests/test_fixers.py index 20d6008ee5..890ce22ef8 100755 --- a/Lib/lib2to3/tests/test_fixers.py +++ b/Lib/lib2to3/tests/test_fixers.py @@ -33,8 +33,10 @@ class FixerTestCase(support.TestCase): self.fixer_log = [] self.filename = "" - for order in (self.refactor.pre_order, self.refactor.post_order): - for fixer in order: + from itertools import chain + for order in (self.refactor.pre_order.values(),\ + self.refactor.post_order.values()): + for fixer in chain(*order): fixer.log = self.fixer_log def _check(self, before, after):