Oli*_*ver 5 python pattern-matching python-2to3
我有一个脚本,可以重新编写Python模块,以便将所有出现的func(a)都转换为func2(a is None)。我现在想支持也func(a, msg)成为func2(a is None, msg),但是我找不到能做到这一点的模式。以下显示了我的尝试:
from lib2to3 import refactor, fixer_base
from textwrap import dedent
PATTERN_ONE_ARG = """power< 'func' trailer< '(' arglist< obj1=any > ')' > >"""
PATTERN_ONE_OR_TWO_ARGS = """power< 'func' trailer< '(' arglist< obj1=any [',' obj2=any] > ')' > >"""
class TestFixer(fixer_base.BaseFix):
def __init__(self, options, fixer_log):
# self.PATTERN = PATTERN_ONE_ARG
self.PATTERN = PATTERN_ONE_OR_TWO_ARGS
super().__init__(options, fixer_log)
def transform(self, node, results):
print("found it")
return node
class TestRefactoringTool(refactor.MultiprocessRefactoringTool):
def get_fixers(self):
fixer = TestFixer(self.options, self.fixer_log)
return [fixer], []
def test():
test_script = """
log.print("hi")
func(a, "12345")
func(a, msg="12345")
func(a)
"""
refac.refactor_string(dedent(test_script), 'script')
flags = dict(print_function=True)
refac = TestRefactoringTool([], flags)
test()
Run Code Online (Sandbox Code Playgroud)
对于func在test_script字符串中找到的每个字符串,我应该看到一个“找到它”,因此总共为3个,但是我只看到2个打印出来,这意味着func(a)模式匹配器找不到。我将模式建立在的可用固定器上lib2to3.fixes,但是我一定会漏掉一些细微之处。有人知道谁可以修复PATTERN_ONE_OR_TWO_ARGS,以便找到所有3个功能吗?
我知道我可以创建一个单独的修复程序实例,但是使用该模式可以避免编写大量代码(我有几十个这些修复程序,总共是24个!)。
找到了:
PATTERN_ONE_OR_TWO_ARGS = """
power< 'func' trailer< '('
( not(arglist | argument<any '=' any>) obj1=any
| arglist< obj1=any ',' obj2=any > )
')' > >
"""
Run Code Online (Sandbox Code Playgroud)
如果transform()是:
def transform(self, node, results):
if 'obj2' in results:
print("found 2", results['obj1'], results['obj2'])
else:
print("found 1", results['obj1'])
return node
Run Code Online (Sandbox Code Playgroud)
然后对于
test_script = """
log.print("hi")
func(a, "12345")
func(a, msg="12345")
func(a)
func(k=a)
"""
Run Code Online (Sandbox Code Playgroud)
输出是
found 2 a "12345"
found 2 a msg="12345"
found 1 a
Run Code Online (Sandbox Code Playgroud)
我还发现http://python3porting.com/fixers.html#fixers-chapter这表明我可以覆盖 match() 方法而不是使用模式。四种兴趣模式是:
PATTERN_ONE_ARG_OR_KWARG = """power< 'func' trailer< '(' not(arglist) obj1=any ')' > >"""
PATTERN_ONE_ARG = """power< 'func' trailer< '(' not(arglist | argument<any '=' any>) obj1=any ')' > >"""
PATTERN_ONE_KWARG = """power< 'func' trailer< '(' obj1=argument< any '=' any > ')' > >"""
PATTERN_TWO_ARGS_OR_KWARGS = """power< 'func' trailer< '(' arglist< obj1=any ',' obj2=any > ')' > >"""
Run Code Online (Sandbox Code Playgroud)