简体   繁体   English

如何向RepoSurgeon添加新功能(就像dsc或amp或min一样)

[英]How to add a new function to RepoSurgeon (just like dsc or amp or min)

This is a specialized version of: How to replace existing Python class methods of (or otherwise extend) RepoSurgeon by means of 'exec' and 'eval'? 这是以下内容的专门版本: 如何通过exec和eval替换RepoSurgeon的现有Python类方法(或以其他方式扩展)?

How can one add a new function to RepoSurgeon using the exec facility (ie without editing the upstream code) to add a new function, augmenting existing functionality. 如何使用exec工具(即,无需编辑上游代码)向RepoSurgeon添加新功能来添加新功能,从而增强现有功能。

Problem: if you are using RepoSurgeon and you call a function from your script or on the command line and the function throws an exception, this will throw off nested function calls. 问题:如果您正在使用RepoSurgeon,并且从脚本或在命令行上调用函数,并且该函数引发异常,则将引发嵌套函数调用。

Example: you want to find all fossils on a branch by branch name in a single function. 示例:您要在单个函数中按分支名称查找分支上的所有化石。 The following compound command will do the job for a branch named BRANCH : 以下复合命令将对名为BRANCH的分支执行此工作:

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

This works fine if BRANCH exists. 如果BRANCH存在,则可以正常工作。 But what if it doesn't? 但是,如果没有呢? In such a case RepoSurgeon will get quite angry with us and throw an exception: 在这种情况下,RepoSurgeon会很生我们的气,并抛出异常:

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

The problem is that this means that your whole lift script will get derailed. 问题是这意味着您的整个举升脚本将脱轨。

What to do? 该怎么办?

Perhaps one of the easiest solutions is to write your own function and bundle the call sequence of @dsc(@min(...)) while guarding against exceptions. 也许最简单的解决方案之一是编写自己的函数并捆绑@dsc(@min(...))的调用序列,同时防止出现异常。

Assuming you have a lift script, embed the following here-doc as argument to exec into it: 假设您有一个提升脚本,请将以下here-doc作为自变量嵌入到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

This implants the local function brpdsc_handler as class member of the same name of class RepoSurgeon and makes a function @brpdsc immediately available to scripts or the command prompt. brpdsc_handler本地函数brpdsc_handler植入为与brpdsc_handler类同名的class RepoSurgeon ,并使函数@brpdsc立即可用于脚本或命令提示符。

The factory function exists to carry over the name for Recoverable which is an exception class defined in the reposurgeon script but not available to our code anymore after the exec has finished. 存在工厂函数以保留Recoverable的名称,该名称是reposurgeon脚本中定义的异常类,但在exec完成后不再可用于我们的代码。 Other symbols can be carried over the same way. 其他符号可以相同的方式携带。

Now all that can happen is that we receive: 现在所有可能发生的就是我们收到:

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

from RepoSurgeon after attempting to run @brpdsc/NO_SUCH_BRANCH/) list . 尝试运行@brpdsc/NO_SUCH_BRANCH/) list后从RepoSurgeon @brpdsc/NO_SUCH_BRANCH/) list

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM