Сделать это непросто, потому что блок with
не является самостоятельным объектом, как модуль или функция. Однако, хотя у меня нет полной реализации, у меня есть несколько предложений, из которых вы сможете что-то собрать:
- В функции
__enter__()
диспетчера контекста print_source
, используйте inspect.stack()
, чтобы получить текущие кадры в стеке. Верхний фрейм - это метод __enter__
, а следующий внизу - функция, в которой находится блок with
. Я назову его «функциональным фреймом». - Информация о функциональном фрейме включает номер строки в строке
with print_source
. Это вам понадобится в ближайшее время. - Передайте кадр из информации о кадре функции в
inspect.getsourcelines()
, чтобы получить все исходные строки из функции (как написано на банке). Эта функция также определяет номер строки строки def foo():
. - Используя номер строки строки
with ...
, смещенный на номер строки строки def ...
, вы можете определить уровень отступа блок with
. Перебирайте исходные строки функции, начиная со строки после блока with
, пока не дойдете до другой строки с таким же (или меньшим) отступом, что и строка with ...
. Теперь вы определили весь источник в блоке with
.
Вещи, которые я не разрешил (но должны быть возможны), включают:
- строк комментариев внутри блок
with
, имеющий меньший отступ, чем остальная часть блока (должно быть легко просто проверить, является ли строка комментарием, и проигнорировать ее для проверки конца блока). Вероятно, вы также захотите обработать случай, когда блок with
является последним кодом в файле, но за ним следуют комментарии с меньшим отступом. Сделайте что-нибудь вроде отслеживания номера строки последнего кода с правильным отступом. - объединение нескольких диспетчеров контекста, например
with cm1(), cm2(), cm3():
. Я не проверял, как это выглядит в стеке - , когда оператор
with
разбросан по нескольким строкам. Я не проверил, в какой строке фрейм сообщает об утверждении, но у меня есть сильное подозрение, что это строка с :
Надежда дает достаточно, чтобы что-то работало!