/usr/share/rhn/up2date_client/getMethod.py is in rhn-client-tools 1.8.26-4.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | # Retrieve action method name given queued action information.
#
# Client code for Update Agent
# Copyright (c) 1999--2012 Red Hat, Inc.  Distributed under GPLv2.
#
# An allowable xmlrpc method is retrieved given a base location, a
# hierarchical route to the class/module, and method name.
#
# $Id$
import os
import string
import sys
from types import ClassType
class GetMethodException(Exception):
    """Exception class"""
    pass
def sanity(methodNameComps):
    #"""
    # Verifies if all the components have proper names
    #"""
    # Allowed characters in each string
    alpha = string.ascii_lowercase + string.ascii_uppercase 
    allowedChars = alpha + string.digits + '_'
    for comp in methodNameComps:
        if not len(comp):
            raise GetMethodException("Empty method component")
        for c in comp:
            if c not in allowedChars:
                raise GetMethodException(
                    "Invalid character '%s' in the method name" % c)
        # Can only begin with a letter
        if comp[0] not in alpha:
            raise GetMethodException(
                "Method names should start with an alphabetic character")
def getMethod(methodName, abspath, baseClass):
    #"""
    #Retreive method given methodName, path to base of tree, and class/module
    #route/label.
    #"""
    # First split the method name
    methodNameComps = string.split(baseClass, '.') + string.split(methodName, '.')  
    # Sanity checks
    sanity(methodNameComps)
    # Build the path to the file
    path = abspath
    for index in range(len(methodNameComps)):
        comp = methodNameComps[index]
        path = "%s/%s" % (path, comp)
        # If this is a directory, fine...
        if os.path.isdir(path):
            # Okay, go on
            continue
        # Try to load this as a file
        for extension in ['py', 'pyc', 'pyo']:            
            if os.path.isfile("%s.%s" % (path, extension)):
                # Yes, this is a file
                break
        else:
            # No dir and no file. Die
            raise GetMethodException("Action %s could not be found" % methodName)
        break
    else:
        # Only directories. This can't happen
        raise GetMethodException("Very wrong")
    # The position of the file
    fIndex = index + 1
    # Now build the module name
    modulename = string.join(methodNameComps[:fIndex], '.')
    # And try to import it
    try:
        actions = __import__(modulename)
    except ImportError:
        raise GetMethodException("Could not import module %s" % modulename), None, sys.exc_info()[2]
    className = actions
    # Iterate through the list of components and try to load that specific
    # module/method
    for index in range(1, len(methodNameComps)):
        comp = methodNameComps[index]
        if index < fIndex:
            # This is a directory or a file we have to load
            if not hasattr(className, comp):
                # Hmmm... Not there
                raise GetMethodException("Class %s has no attribute %s" % (
                    string.join(methodNameComps[:index], '.'), comp))
            className = getattr(className, comp)
            #print type(className)
            continue
        # A file or method
        # We look for the special __rhnexport__ array
        if not hasattr(className, '__rhnexport__'):
            raise GetMethodException("Class %s is not RHN-compliant" % \
                string.join(methodNameComps[:index], '.'))
        export = getattr(className, '__rhnexport__')
        if comp not in export:
            raise GetMethodException("Class %s does not export '%s'" % (
                string.join(methodNameComps[:index], '.'), comp))
        className = getattr(className, comp)
        if type(className) is ClassType:
            # Try to instantiate it
            className = className()
        #print type(className)
    return className
#-----------------------------------------------------------------------------
if __name__ == '__main__':
    # Two valid ones and a bogus one
    methods = [
        'a.b.c.d.e.f',
        'a.b.c.d.e.foo.h',
        'a.b.c.d.e.g.h',
        'a.b.d.d.e.g.h',
        'a.b.d.d._e.g.h',
        'a.b.d.d.e_.g.h',
        'a.b.d.d.e-.g.h',
        'a.b.d.d..g.h',
    ]
    for m in methods:
        print "----Running method %s: " % m
        try:
            method = getMethod(m, '.', 'Actions')
        except GetMethodException, e:
            print "Error getting the method %s: %s" % (m, 
                string.join(map(str, e.args)))
        else:
            method()
#-----------------------------------------------------------------------------
 |