1 """
2 Utility Functions
3
4 Part of this code copied from from Listen (c) 2006 Mehdi Abaakouk
5 (http://listengnome.free.fr/)
6
7 Copyright: John Stowers, 2006
8 License: GPLv2
9 """
10 import sys
11 import os.path
12 import socket
13 import datetime
14 import time
15 import re
16 import logging
17 log = logging.getLogger("Utils")
18
20 """
21 Returns proportionally resized co-ordinates for an image
22 """
23
24 if desiredH == -1: desiredH = currentH
25 if desiredW == -1: desiredW = currentW
26
27
28 dw = abs(currentW - desiredW)
29 dh = abs(currentH - desiredH)
30
31 if dh > dw:
32 newHeight = float(desiredH)
33 percentage = newHeight / currentH
34 newWidth = currentW * percentage
35 else:
36 newWidth = float(desiredW)
37 percentage = newWidth / currentW
38 newHeight = currentH * percentage
39
40 return int(newWidth), int(newHeight)
41
43 """
44 Check if the given app is installed.
45 """
46 path = os.environ['PATH']
47 paths = path.split(os.pathsep)
48 for dir in paths:
49 if os.path.isdir(dir):
50 if os.path.isfile(os.path.join(dir,app)):
51 return True
52 return False
53
54
55
56
58 """
59 Returns a new File onject, which has been created in the
60 system temporary directory, and that has been filled with
61 contents
62
63 The file is closed when it is returned
64
65 @param contents: The data to write into the file
66 @param contentsAreText: Indicates to the OS if the file is text (as opposed
67 to a binary type file
68 @param contentsAreText: C{bool}
69 @returns: a L{conduit.datatypes.File}
70 """
71 import conduit.datatypes.File as File
72 return File.TempFile(contents)
73
75 """
76 Creates a new temporary directory
77 """
78 import tempfile
79 return tempfile.mkdtemp("conduit")
80
82 """
83 The fastes way to unique-ify a list while retaining its order, from
84 http://www.peterbe.com/plog/uniqifiers-benchmark
85 """
86 def _f10(listy):
87 seen = set()
88 for x in listy:
89 if x in seen:
90 continue
91 seen.add(x)
92 yield x
93 return list(_f10(seq))
94
96 """
97 returns a random string of length
98 """
99 import random
100 s = ""
101 for i in range(0,length):
102 s += str(random.randint(0,10))
103 return s
104
106 """
107 Adds directory to the python search path.
108
109 From within a dataprovider (FooModule.py)
110 call with Utils.dataprovider_add_dir_to_path(__file__, some_dir):
111 """
112 path = os.path.join(dataproviderfile, "..", directory)
113 path = os.path.abspath(path)
114 sys.path.insert(0,path)
115
124
126 """
127 Runs a given dialog, and makes it transient for
128 the given window if any
129 @param dialog: dialog
130 @param window: gtk window
131 @returns: True if the user clicked OK to exit the dialog
132 """
133 import gtk
134
135 if window:
136 dialog.set_transient_for(window)
137
138 return dialog.run() == gtk.RESPONSE_OK
139
141 """
142 Runs a given dialog, and makes it transient for
143 the given window if any
144 @param dialog: dialog
145 @param window: gtk window
146 @returns: True if the user clicked OK to exit the dialog
147 """
148 import gtk.gdk
149
150 dialog.connect("response", resp_cb)
151 dialog.connect("response", lambda dlg, resp: dlg.destroy())
152
153 if window:
154 dialog.set_transient_for(window)
155
156
157
158
159
160
161
162
163
164
165
166 dialog.show()
167
169 """
170 Sets the dialog to display the busy cursor
171 """
172 import gtk.gdk
173 dlg.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
174
176 """
177 Resets the dialog to display the plain Gtk cursor
178 """
179 dlg.window.set_cursor(None)
180
182 """
183 Returns the md5 of the supplied string in readable hexdigest string format
184 """
185 import md5
186 return md5.new(string).hexdigest()
187
189 """
190 Returns a uuid string
191 """
192 try:
193 import uuid
194 return uuid.uuid4().hex
195 except ImportError:
196 import random, md5, socket
197 t = long( time.time() * 1000 )
198 r = long( random.random()*100000000000000000L )
199 try:
200 a = socket.gethostbyname( socket.gethostname() )
201 except:
202 a = random.random()*100000000000000000L
203 data = str(t)+' '+str(r)+' '+str(a)
204 data = md5.md5(data).hexdigest()
205 return data
206
208 """
209 Checks if a dbus service is available on the given bus
210 @param interface: The interface to look for
211 @param bus: The bus to look on (optional)
212 """
213 try:
214 import dbus
215 except:
216 return False
217
218 if bus == None:
219 bus = dbus.SessionBus()
220
221 obj = bus.get_object('org.freedesktop.DBus', '/org/freedesktop/DBus')
222 dbus_iface = dbus.Interface(obj, 'org.freedesktop.DBus')
223 avail = dbus_iface.ListNames()
224 return interface in avail
225
227 """
228 Makes a user and machine dependant string in the form
229 username@hostname
230 """
231 hostname = socket.gethostname()
232 username = os.environ.get("USER","")
233 return "%s@%s" % (username, hostname)
234
236 """
237 Makes a datetime object from a unix timestamp.
238
239 Note: For the sake of consistancy always drop the
240 fractional (microsecond) part of the timestamp
241 """
242 if type(t) not in [long, int, float]:
243 raise Exception("Timestamp must be a number")
244
245 if t < 0:
246 raise Exception("Timestamps before 1970 are not valid")
247
248 return datetime.datetime.fromtimestamp(long(t))
249
251 """
252 Returns the unix timestamp for a datetime
253
254 Note: For the sake of consistancy always drop the
255 fractional (microsecond) part of the timestamp
256 """
257 if type(d) != datetime.datetime:
258 raise Exception("Must supply a datetime")
259
260 f = time.mktime(d.timetuple())
261 if f < 0:
262 raise Exception("Timestamps before 1970 are not valid")
263
264 return long(f)
265
267 """
268 encodes an args dictionary to a url string in the form
269 param=value¶m2=val2
270 """
271 import urllib
272 return urllib.urlencode(args)
273
275 """
276 FIXME: dont import cgi for just one function. Also it doesnt
277 even handle lists
278 """
279 import cgi
280 args = {}
281 for key,val in cgi.parse_qsl(argString):
282 args[key] = val
283 return args
284
286 """
287 A decorator that prints debug message showing the function name and
288 argument types to the supplied logger instance.
289
290 Adapted from the accepts/returns decorators at
291 http://wiki.python.org/moin/PythonDecoratorLibrary
292 """
293 def decorator(f):
294 def newf(*args):
295
296 argtypes = map(str,map(type, args))
297 argnames = map(str,f.func_code.co_varnames[:f.func_code.co_argcount])
298 argnamesandtypes = ["%s:%s" % (i,j) for i,j in zip(argnames,argtypes)]
299 msg = "Method Call %s(%s)" % (
300 f.__name__,
301 ', '.join(argnamesandtypes)
302 )
303 log.debug(msg)
304 return f(*args)
305
306 newf.__name__ = f.__name__
307 newf.__doc__ = f.__doc__
308 newf.__dict__.update(f.__dict__)
309 return newf
310 return decorator
311
313 """
314 Returns the contents of the xml tag or None. Uses a simple regex.
315
316 Taken from:
317 http://immike.net/blog/2007/04/06/5-regular-expressions-every-web-programmer-should-know/
318 """
319 ans = re.compile("<%(tag)s[^>]*>(.*?)</%(tag)s>" % {"tag":tag}).findall(text)
320 if ans:
321 return ans[0]
322 else:
323 return None
324
341