【问题标题】:Python EBNF Syntax to Match a Decorator匹配装饰器的 Python EBNF 语法
【发布时间】:2020-12-13 16:17:33
【问题描述】:

我有一个非常大的项目,我需要将一些模块从 bar 移动到 foo.bar,然后更新所有函数调用以反映新位置。

这对函数调用很有效,但我在构建匹配装饰器的模式时遇到问题。

我喜欢匹配的代码是::

  from unittest.mock import patch

  @patch('bar')
  def func(self, patcher):
      ...

我想把上面的补丁改成@patch('foo.bar')

我当前的模式在函数调用时匹配patch,但在用作装饰器时不匹配::

class FixRenameMockPatch(fixer_base.BaseFix):

    PATTERN = """
    power<
        'patch' args=trailer< '(' [any] ')' >
    >
    """

    def transform(self, node, results):
        ...

我真的很难理解https://docs.python.org/3.8/reference/grammar.html 的语法,所以我的修复程序主要基于lib2to3 的源代码。

如何编写上面的模式以匹配patch 的所有用途,包括装饰器和上下文管理器?以及一个完全合格的补丁使用,例如mock.patchunittest.mock.patch

【问题讨论】:

    标签: python ebnf lib2to3


    【解决方案1】:

    你可以试试这个

    PATTERN = "decorator< '@' 'patch' '(' [any] ')' any* >"
    

    或者

    PATTERN = """
        decorator< '@' 'patch' '(' [any] ')' any* >
        | decorator< '@' dotted_name< 'mock' '.' 'patch' > '(' [any] ')' any* >
        """
    

    如果你也想匹配@mock.patch

    a script(用 Python2 编写,Py3 version here)来解析您的文件并显示解析后的模式,我觉得这很有用。例如,您将test.py 创建为

    from unittest.mock import patch
    
    @patch('bar')
    def func(self, patcher):
        print('foo')
    

    然后运行find_pattern.py,回车直到显示出你要解析的行,然后输入一些字符(下例为y),回车显示解析结果:

    $ python find_pattern.py -f test.py
    ' unittest.mock'
    
    'from unittest.mock import patch'
    
    'from unittest.mock import patch\n'
    
    "\n@patch('bar')\n"
    y
    decorator< '@' 'patch' '(' "'bar'" ')' '\n' >
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-17
    • 2015-12-10
    • 1970-01-01
    • 1970-01-01
    • 2012-08-31
    • 2012-02-09
    • 2021-06-30
    • 1970-01-01
    相关资源
    最近更新 更多