У меня есть очень большой проект, в котором мне нужно переместить некоторые модули из 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.patch
или unittest.mock.patch
?
Вы можете попробовать это
PATTERN = "decorator< '@' 'patch' '(' [any] ')' any* >"
или альтернативно
PATTERN = """
decorator< '@' 'patch' '(' [any] ')' any* >
| decorator< '@' dotted_name< 'mock' '.' 'patch' > '(' [any] ')' any* >
"""
если вы тоже хотите соответствовать @mock.patch
.
Существует скрипт (написанный на Python2, версия Py3 здесь) для разбора вашего файла и отображения проанализированного шаблона, который я считаю полезным. Например, вы создаете test.py
как
from unittest.mock import patch
@patch('bar')
def func(self, patcher):
print('foo')
Затем запустите find_pattern.py
, нажмите Enter, пока не отобразится строка, которую вы хотите проанализировать, затем введите какой-нибудь символ (y в случае ниже) и нажмите Enter, чтобы показать результат анализа:
$ 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' >
Рад слышать, что это было полезно 👍 Я также добавил ссылку на вашу суть в ответ.
спасатель. вот суть для python3: gist.github.com/mahmoudimus/459a5f434832290f92cbe00292e1f638