File: PmwUtils.py.html

package info (click to toggle)
python-pmw 0.6.2-0.1
  • links: PTS
  • area: main
  • in suites: hamm
  • size: 1,652 kB
  • ctags: 2,716
  • sloc: python: 10,720; makefile: 44; sh: 24
file content (153 lines) | stat: -rw-r--r-- 7,434 bytes parent folder | download
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
<!DOCTYPE HTML PUBLIC "-//Netscape_Microsoft//DTD HTML 3.0//EN">
<HTML>

<!-- This file generated using the Python HTMLgen module. -->
<HEAD>
  <META NAME="GENERATOR" CONTENT="HTMLgen 1.1">
        <TITLE>PmwUtils.py</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF">
<PRE>
import types

<FONT COLOR="#DD0000"># Fill in a flattened method resolution dictionary for a class (attributes are </FONT>
<FONT COLOR="#DD0000"># filtered out). Flattening honours the MI method resolution rules </FONT>
<FONT COLOR="#DD0000"># (depth-first search of bases in order). The dictionary has method names</FONT>
<FONT COLOR="#DD0000"># for keys and functions for values.</FONT>
<STRONG>def __methodDict</STRONG>(cls, dict):

    <FONT COLOR="#DD0000"># the strategy is to traverse the class in the _reverse_ of the normal</FONT>
    <FONT COLOR="#DD0000"># order, and overwrite any duplicates.</FONT>
    baseList = list(cls.__bases__)
    baseList.reverse()
    
    <FONT COLOR="#DD0000"># do bases in reverse order, so first base overrides last base</FONT>
    for super in baseList:
	__methodDict(super, dict)

    <FONT COLOR="#DD0000"># do my methods last to override base classes</FONT>
    for key, value in cls.__dict__.items():
	<FONT COLOR="#DD0000"># ignore class attributes</FONT>
	if type(value) == types.FunctionType:
	    dict[key] = value

<STRONG>def __methods</STRONG>(cls):
    <FONT COLOR="#DD0000"># Return all method names for a class.</FONT>

    <FONT COLOR="#DD0000"># Return all method names for a class (attributes are filtered</FONT>
    <FONT COLOR="#DD0000"># out).  Base classes are searched recursively.</FONT>

    dict = {}
    __methodDict(cls, dict)
    return dict.keys()
	
<FONT COLOR="#DD0000"># Function body to resolve a forwarding given the target method name and the </FONT>
<FONT COLOR="#DD0000"># attribute name. The resulting lambda requires only self, but will forward </FONT>
<FONT COLOR="#DD0000"># any other parameters.</FONT>
__stringBody = (
    <FONT COLOR="#009900">'def %(method)s(this, *args, **kw): return '</FONT> +
    <FONT COLOR="#009900">'apply(this.%(attribute)s.%(method)s, args, kw)'</FONT>)

<FONT COLOR="#DD0000"># Get a unique id</FONT>
__counter = 0
<STRONG>def __unique</STRONG>():
  global __counter
  __counter = __counter + 1
  return str(__counter)

<FONT COLOR="#DD0000"># Function body to resolve a forwarding given the target method name and the</FONT>
<FONT COLOR="#DD0000"># index of the resolution function. The resulting lambda requires only self, </FONT>
<FONT COLOR="#DD0000"># but will forward any other parameters. The target instance is identified </FONT>
<FONT COLOR="#DD0000"># by invoking the resolution function.</FONT>
__funcBody = (
    <FONT COLOR="#009900">'def %(method)s(this, *args, **kw): return '</FONT> +
    <FONT COLOR="#009900">'apply(this.%(forwardFunc)s().%(method)s, args, kw)'</FONT>)

<STRONG>def forwardmethods</STRONG>(fromClass, toClass, toPart, exclude = []):
    <FONT COLOR="#DD0000"># Forward all methods from one class to another.</FONT>

    <FONT COLOR="#DD0000"># Forwarders will be created in fromClass to forward method</FONT>
    <FONT COLOR="#DD0000"># invocations to toClass.  The methods to be forwarded are</FONT>
    <FONT COLOR="#DD0000"># identified by flattening the interface of toClass, and excluding</FONT>
    <FONT COLOR="#DD0000"># methods identified in the exclude list.  Methods already defined</FONT>
    <FONT COLOR="#DD0000"># in fromClass, or special methods with one or more leading or</FONT>
    <FONT COLOR="#DD0000"># trailing underscores will not be forwarded.</FONT>

    <FONT COLOR="#DD0000"># For a given object of class fromClass, the corresponding toClass</FONT>
    <FONT COLOR="#DD0000"># object is identified using toPart.  This can either be a String</FONT>
    <FONT COLOR="#DD0000"># denoting an attribute of fromClass objects, or a function taking</FONT>
    <FONT COLOR="#DD0000"># a fromClass object and returning a toClass object.</FONT>

    <FONT COLOR="#DD0000"># Example:</FONT>
    <FONT COLOR="#DD0000">#     class MyClass:</FONT>
    <FONT COLOR="#DD0000">#     ...</FONT>
    <FONT COLOR="#DD0000">#         def __init__(self):</FONT>
    <FONT COLOR="#DD0000">#             ...</FONT>
    <FONT COLOR="#DD0000">#             self.__target = TargetClass()</FONT>
    <FONT COLOR="#DD0000">#             ...</FONT>
    <FONT COLOR="#DD0000">#         def findtarget(self):</FONT>
    <FONT COLOR="#DD0000">#             return self.__target</FONT>
    #     forwardmethods(MyClass, TargetClass, <FONT COLOR="#009900">'__target'</FONT>, [<FONT COLOR="#009900">'dangerous1'</FONT>, <FONT COLOR="#009900">'dangerous2'</FONT>])
    <FONT COLOR="#DD0000">#     # ...or...</FONT>
    <FONT COLOR="#DD0000">#     forwardmethods(MyClass, TargetClass, MyClass.findtarget, </FONT>
    #             [<FONT COLOR="#009900">'dangerous1'</FONT>, <FONT COLOR="#009900">'dangerous2'</FONT>])

    <FONT COLOR="#DD0000"># In both cases, all TargetClass methods will be forwarded from</FONT>
    <FONT COLOR="#DD0000"># MyClass except for dangerous1, dangerous2, special methods like</FONT>
    <FONT COLOR="#DD0000"># __str__, and pre-existing methods like findtarget.</FONT>


    <FONT COLOR="#DD0000"># Allow an attribute name (String) or a function to determine the instance</FONT>
    if type(toPart) != types.StringType:

	<FONT COLOR="#DD0000"># check that it is something like a function</FONT>
	if callable(toPart):

	    <FONT COLOR="#DD0000"># If a method is passed, use the function within it</FONT>
	    if hasattr(toPart, <FONT COLOR="#009900">'im_func'</FONT>):
		toPart = toPart.im_func
		
	    <FONT COLOR="#DD0000"># After this is set up, forwarders in this class will use</FONT>
	    <FONT COLOR="#DD0000"># the forwarding function. The forwarding function name is</FONT>
	    <FONT COLOR="#DD0000"># guaranteed to be unique, so that it can't be hidden by subclasses</FONT>
	    forwardName = <FONT COLOR="#009900">'__fwdfunc__'</FONT> + __unique()
	    fromClass.__dict__[forwardName] = toPart

	<FONT COLOR="#DD0000"># It's not a valid type</FONT>
	else:
	    raise TypeError, <FONT COLOR="#009900">'toPart must be attribute name, function or method'</FONT>

    <FONT COLOR="#DD0000"># get the full set of candidate methods</FONT>
    dict = {}
    __methodDict(toClass, dict)

    <FONT COLOR="#DD0000"># discard special methods</FONT>
    for ex in dict.keys():
	if ex[:1] == <FONT COLOR="#009900">'_'</FONT> or ex[-1:] == <FONT COLOR="#009900">'_'</FONT>:
	    del dict[ex]
    <FONT COLOR="#DD0000"># discard dangerous methods supplied by the caller</FONT>
    for ex in exclude:
	if dict.has_key(ex):
	    del dict[ex]
    <FONT COLOR="#DD0000"># discard methods already defined in fromClass</FONT>
    for ex in __methods(fromClass):
	if dict.has_key(ex):
	    del dict[ex]

    for method, func in dict.items():
	d = {<FONT COLOR="#009900">'method'</FONT>: method, <FONT COLOR="#009900">'func'</FONT>: func}
	if type(toPart) == types.StringType:
	    execString = \
		__stringBody % {<FONT COLOR="#009900">'method'</FONT> : method, <FONT COLOR="#009900">'attribute'</FONT> : toPart}
	else:
	    execString = \
		__funcBody % {<FONT COLOR="#009900">'forwardFunc'</FONT> : forwardName, <FONT COLOR="#009900">'method'</FONT> : method}

	exec execString in d

	<FONT COLOR="#DD0000"># this creates a method</FONT>
	fromClass.__dict__[method] = d[method]

</PRE>

 </BODY> </HTML>