Welcome, guest | Sign In | My Account | Store | Cart

This recipe, taken a class definition (see the docstring for further explain), generate the class code, evaluate it and return an instance of the constructed class.

Python, 60 lines
 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
def generate_dispatcher(method_handler, parent_class=None):
    """
    Create a dispatcher class and return an instance of it from a dispatcher
    definition.
    The definition is a class with the following attributes:
    _ EXPORTED_METHOD: dictionary where keys are method names and values
      class attribute names of the attributes holding references to an object
      implementing the method 
    _ attributes defined in EXPORTED_METHODS values. They must contain an
      object instance which implements the respective methods (EXPORTED_METHODS
      keys)

    Ex:
    class TestDispatchHandler:
        EXPORTED_METHODS = {'method1': 'attr1',
                            'method2': 'attr1',
                            'method3': 'attr2'}
        attr1 = Object1()
        attr2 = Object2()

    where Object1 is a class which provides method1 and method2 and Object2 a
    class which provides method3

    obj_inst = generate_dispatcher(TestDispatchHandler)

    will affect in 'obj_inst' a class instance which provide method1, method2
    and method3 by delegate it to the correct object
    """
    # class definition
    if parent_class:
        class_str = 'class Dispatcher(%s):\n' % parent_class
        statements = '  %s.__init__(self)\n' % parent_class
    else:
        class_str = 'class Dispatcher:\n'
        statements = ''

    # methods definition
    registered = []
    for method, objname in method_handler.EXPORTED_METHODS.items():
        if not objname in registered:
            registered.append(objname)
        class_str = '%s def %s(self, *attrs):\n  return self.%s.%s(*attrs)\n'%\
                    (class_str, method, objname, method)

    # constructor definition
    attrs = ''
    for objname in registered:
        attrs = '%s, %s' % (attrs, objname)
        statements = '%s  self.%s=%s\n' % (statements, objname, objname)
        # retrieve object reference in current context
        exec '%s=getattr(method_handler, "%s")'%(objname, objname)

    # assemble all parts
    class_str = '%s def __init__(self%s):\n%s' % (class_str, attrs, statements)

    # now we can eval the full class
    exec class_str

    # return an instance of constructed class
    return eval('Dispatcher(%s)'%attrs[2:]) # attrs[2:] for removing ', '

This code have been written for use with PYRO (Python Remote Objects) which doesn't seem to like dynamic class using __dict__ and __getattr__ facilities.

Created by Sylvain Thenault on Mon, 22 Oct 2001 (PSF)
Python recipes (4591)
Sylvain Thenault's recipes (2)

Required Modules

  • (none specified)

Other Information and Tasks