comparison flax/TLUtility.py @ 0:45b12307c695

Initial revision
author drewp
date Wed, 03 Jul 2002 09:37:57 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:45b12307c695
1 """Collected utility functions, many are taken from Drew's utils.py in
2 Cuisine CVS and Hiss's Utility.py."""
3
4 from __future__ import generators
5 import sys
6
7 __author__ = "David McClosky <dmcc@bigasterisk.com>, " + \
8 "Drew Perttula <drewp@bigasterisk.com>"
9 __cvsid__ = "$Id: TLUtility.py,v 1.1 2003/05/25 08:25:35 dmcc Exp $"
10 __version__ = "$Revision: 1.1 $"[11:-2]
11
12 def make_attributes_from_args(*argnames):
13 """
14 This function simulates the effect of running
15 self.foo=foo
16 for each of the given argument names ('foo' in the example just
17 now). Now you can write:
18 def __init__(self,foo,bar,baz):
19 copy_to_attributes('foo','bar','baz')
20 ...
21 instead of:
22 def __init__(self,foo,bar,baz):
23 self.foo=foo
24 self.bar=bar
25 self.baz=baz
26 ...
27 """
28
29 callerlocals=sys._getframe(1).f_locals
30 callerself=callerlocals['self']
31 for a in argnames:
32 try:
33 setattr(callerself,a,callerlocals[a])
34 except KeyError:
35 raise KeyError, "Function has no argument '%s'" % a
36
37 def enumerate(*collections):
38 """Generates an indexed series: (0,coll[0]), (1,coll[1]) ...
39
40 this is a multi-list version of the code from the PEP:
41 enumerate(a,b) gives (0,a[0],b[0]), (1,a[1],b[1]) ...
42 """
43 i = 0
44 iters = [iter(collection) for collection in collections]
45 while 1:
46 yield [i,] + [iterator.next() for iterator in iters]
47 i += 1
48
49 def dumpobj(o):
50 """Prints all the object's non-callable attributes"""
51 print repr(o)
52 for a in [x for x in dir(o) if not callable(getattr(o, x))]:
53 try:
54 print " %20s: %s " % (a, getattr(o, a))
55 except:
56 pass
57 print ""
58
59 def dict_filter_update(d, **newitems):
60 """Adds a set of new keys and values to dictionary 'd' if the values are
61 true:
62
63 >>> some_dict = {}
64 >>> dict_filter_update(some_dict, a=None, b=0, c=1, e={}, s='hello')
65 >>> some_dict
66 {'c': 1, 's': 'hello'}
67 """
68 for k, v in newitems.items():
69 if v: d[k] = v
70
71 def try_get_logger(channel):
72 """Tries to get a logger with the channel 'channel'. Will return a
73 silent DummyClass if logging is not available."""
74 try:
75 import logging
76 log = logging.getLogger(channel)
77 except ImportError:
78 log = DummyClass()
79 return log
80
81 class DummyClass:
82 """A class that can be instantiated but never used. It is intended to
83 be replaced when information is available.
84
85 Usage:
86 >>> d = DummyClass(1, 2, x="xyzzy")
87 >>> d.someattr
88 Traceback (most recent call last):
89 File "<stdin>", line 1, in ?
90 File "Utility.py", line 33, in __getattr__
91 raise AttributeError, "Attempted usage of a DummyClass: %s" % key
92 AttributeError: Attempted usage of a DummyClass: someattr
93 >>> d.somefunction()
94 Traceback (most recent call last):
95 File "<stdin>", line 1, in ?
96 File "Utility.py", line 33, in __getattr__
97 raise AttributeError, "Attempted usage of a DummyClass: %s" % key
98 AttributeError: Attempted usage of a DummyClass: somefunction"""
99 def __init__(self, use_warnings=1, raise_exceptions=0, **kw):
100 """Constructs a DummyClass"""
101 make_attributes_from_args('use_warnings', 'raise_exceptions')
102 def __getattr__(self, key):
103 """Raises an exception to warn the user that a Dummy is not being
104 replaced in time."""
105 if key == "__del__":
106 return
107 msg = "Attempted usage of '%s' on a DummyClass" % key
108 if self.use_warnings:
109 import warnings
110 warnings.warn(msg)
111 if self.raise_exceptions:
112 raise AttributeError, msg
113 return lambda *args, **kw: self.bogus_function()
114 def bogus_function(self):
115 pass
116
117 class ClassyDict(dict):
118 """A dict that accepts attribute-style access as well (for keys
119 that are legal names, obviously). I used to call this Struct, but
120 chose the more colorful name to avoid confusion with the struct
121 module."""
122 def __getattr__(self, a):
123 return self[a]
124 def __setattr__(self, a, v):
125 self[a] = v
126 def __delattr__(self, a):
127 del self[a]
128
129 def trace(func):
130 """Good old fashioned Lisp-style tracing. Example usage:
131
132 >>> def f(a, b, c=3):
133 >>> print a, b, c
134 >>> return a + b
135 >>>
136 >>>
137 >>> f = trace(f)
138 >>> f(1, 2)
139 |>> f called args: [1, 2]
140 1 2 3
141 <<| f returned 3
142 3
143
144 TODO: print out default keywords (maybe)
145 indent for recursive call like the lisp version (possible use of
146 generators?)"""
147 name = func.func_name
148 def tracer(*args, **kw):
149 s = '|>> %s called' % name
150 if args:
151 s += ' args: %r' % list(args)
152 if kw:
153 s += ' kw: %r' % kw
154 print s
155 ret = func(*args, **kw)
156 print '<<| %s returned %s' % (name, ret)
157 return ret
158 return tracer
159
160 # these functions taken from old light8 code
161 def dict_max(*dicts):
162 """
163 ({'a' : 5, 'b' : 9}, {'a' : 10, 'b' : 4})
164 returns ==> {'a' : 10, 'b' : 9}
165 """
166 newdict = {}
167 for d in dicts:
168 for k,v in d.items():
169 newdict[k] = max(v, newdict.get(k, 0))
170 return newdict
171
172 def dict_scale(d,scl):
173 """scales all values in dict and returns a new dict"""
174 return dict([(k,v*scl) for k,v in d.items()])
175
176 def dict_subset(d, dkeys, default=0):
177 """Subset of dictionary d: only the keys in dkeys. If you plan on omitting
178 keys, make sure you like the default."""
179 newd = {} # dirty variables!
180 for k in dkeys:
181 newd[k] = d.get(k, default)
182 return newd
183
184 # functions specific to Timeline
185 # TBD
186 def last_less_than(array, x):
187 """array must be sorted"""
188 best = None
189 for elt in array:
190 if elt <= x:
191 best = elt
192 elif best is not None:
193 return best
194 return best
195
196 # TBD
197 def first_greater_than(array, x):
198 """array must be sorted"""
199 array_rev = array[:]
200 array_rev.reverse()
201 best = None
202 for elt in array_rev:
203 if elt >= x:
204 best = elt
205 elif best is not None:
206 return best
207 return best
208
209