简体   繁体   中英

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'?

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.

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.

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 :

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

This works fine if BRANCH exists. But what if it doesn't? In such a case RepoSurgeon will get quite angry with us and throw an exception:

@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.

Assuming you have a lift script, embed the following here-doc as argument to exec into it:

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.

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. 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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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