Как добавить новую функцию в RepoSurgeon (точно так же, как dsc или amp или min)

Это специализированная версия: Как заменить существующие методы класса Python (или иным образом расширить) RepoSurgeon с помощью "exec" и "eval"?

Как добавить новую функцию в RepoSurgeon, используя exec возможность (т.е. без редактирования вышестоящего кода) добавить новую функцию, дополняя существующую функциональность.

Проблема: если вы используете RepoSurgeon и вызываете функцию из своего скрипта или из командной строки, и функция выдает исключение, это отбросит вызовы вложенных функций.

Пример: вы хотите найти все окаменелости на ветке по имени ветки в одной функции. Следующая составная команда выполнит работу для ветви с именем BRANCH:

@dsc(@min(/BRANCH/)) list

Это работает нормально, если BRANCH существует. Но что, если это не так? В таком случае RepoSurgeon рассердится на нас и выдаст исключение:

@dsc(@min(/NO_SUCH_BRANCH/)) list
[...]
ValueError: min() arg is an empty sequence

Проблема в том, что это означает, что весь ваш скрипт лифта будет сорван.

Что делать?

1 ответ

Возможно, одно из самых простых решений - написать собственную функцию и связать последовательность вызовов @dsc(@min(...)) при защите от исключений.

Предполагая, что у вас есть скрипт лифта, вставьте следующий документ здесь в качестве аргумента exec внутрь:

exec <<EOF
    if self:
        def brpdsc_factory(recov):
            Recoverable = recov
            def brpdsc_handler(self, subarg):
                if not subarg:
                    raise Recoverable("function @brpdsc() called with selection that resolves to empty set")
                minset =      set([])
                descendants = set([])
                try:
                    minset = self.min_handler(subarg)
                except ValueError as e:
                    raise Recoverable("invalid value passed to function @min()")
                try:
                    descendants = self.dsc_handler(minset)
                except:
                    raise Recoverable("the implicit call to @dsc() failed")
                return descendants
            return brpdsc_handler
        brpdsc_handler = brpdsc_factory(Recoverable)
        setattr(self, 'brpdsc_handler', brpdsc_handler.__get__(self, self.__class__))
EOF

Это имплантирует локальную функцию brpdsc_handler как ученик с тем же именем class RepoSurgeon и делает функцию @brpdsc немедленно доступны для сценариев или командной строки.

Заводская функция существует для переноса имени для Recoverable который является классом исключения, определенным в reposurgeon сценарий, но больше не доступен для нашего кода после exec закончил Другие символы могут быть перенесены таким же образом.

Теперь все, что может произойти, это то, что мы получаем:

reposurgeon: function @brpdsc() called with selection that resolves to empty set

от RepoSurgeon после попытки запуска @brpdsc/NO_SUCH_BRANCH/) list,

Другие вопросы по тегам