匹配lib2to3的1or2arg函数调用的模式

2024-04-26 00:51:17 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个脚本,可以重写Python模块,以便所有出现的func(a)都转换为func2(a is None)。我现在还想支持func(a, 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()

对于在test_script字符串中找到的每个func,我应该会看到一个“找到它”,因此总共3个,但我只看到2个打印出来,这意味着模式匹配器找不到{}。我基于lib2to3.fixes中可用的修复程序来构建模式,但我肯定遗漏了一个微妙之处。有人知道谁来修复模式“一个”或“两个”参数,以便找到所有3个函数?在

我知道我可以创建一个单独的fixer实例,但是使用该模式可以节省我编写大量代码的时间(我有几十个这样的fixer,那么总数将是24!)。在


Tags: testselflogdef模式scriptanymsg
1条回答
网友
1楼 · 发布于 2024-04-26 00:51:17

找到了:

PATTERN_ONE_OR_TWO_ARGS = """
    power< 'func' trailer< '('
        ( not(arglist | argument<any '=' any>) obj1=any
        | arglist< obj1=any ',' obj2=any > )
    ')' > >
    """

如果transform()是:

^{pr2}$

然后是为了

test_script = """
    log.print("hi")
    func(a, "12345")
    func(a, msg="12345")
    func(a)
    func(k=a)
    """

输出是

found 2 a  "12345"
found 2 a  msg="12345"
found 1 a

我还发现了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 >              ')' > >"""

相关问题 更多 >

    热门问题