Mercurial > code > home > repos > light9
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 |