OLD | NEW |
1 # | 1 # |
2 # Copyright 2008 Google Inc. Released under the GPL v2 | 2 # Copyright 2008 Google Inc. Released under the GPL v2 |
3 | 3 |
4 import os, pickle, random, re, resource, select, shutil, signal, StringIO | 4 import os, pickle, random, re, resource, select, shutil, signal, StringIO |
5 import socket, struct, subprocess, sys, time, textwrap, urlparse | 5 import socket, struct, subprocess, sys, time, textwrap, urlparse |
6 import warnings, smtplib, logging, urllib2 | 6 import warnings, smtplib, logging, urllib2 |
7 try: | 7 try: |
8 import hashlib | 8 import hashlib |
9 except ImportError: | 9 except ImportError: |
10 import md5, sha | 10 import md5, sha |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
195 | 195 |
196 | 196 |
197 def open_write_close(filename, data): | 197 def open_write_close(filename, data): |
198 f = open(filename, 'w') | 198 f = open(filename, 'w') |
199 try: | 199 try: |
200 f.write(data) | 200 f.write(data) |
201 finally: | 201 finally: |
202 f.close() | 202 f.close() |
203 | 203 |
204 | 204 |
205 def matrix_to_string(matrix, header=None): | |
206 """ | |
207 Return a pretty, aligned string representation of a nxm matrix. | |
208 | |
209 This representation can be used to print any tabular data, such as | |
210 database results. It works by scanning the lengths of each element | |
211 in each column, and determining the format string dynamically. | |
212 | |
213 @param matrix: Matrix representation (list with n rows of m elements). | |
214 @param header: Optional tuple with header elements to be displayed. | |
215 """ | |
216 lengths = [] | |
217 for row in matrix: | |
218 for column in row: | |
219 i = row.index(column) | |
220 cl = len(column) | |
221 try: | |
222 ml = lengths[i] | |
223 if cl > ml: | |
224 lengths[i] = cl | |
225 except IndexError: | |
226 lengths.append(cl) | |
227 | |
228 lengths = tuple(lengths) | |
229 format_string = "" | |
230 for length in lengths: | |
231 format_string += "%-" + str(length) + "s " | |
232 format_string += "\n" | |
233 | |
234 matrix_str = "" | |
235 if header: | |
236 matrix_str += format_string % header | |
237 for row in matrix: | |
238 matrix_str += format_string % tuple(row) | |
239 | |
240 return matrix_str | |
241 | |
242 | |
243 def read_keyval(path): | 205 def read_keyval(path): |
244 """ | 206 """ |
245 Read a key-value pair format file into a dictionary, and return it. | 207 Read a key-value pair format file into a dictionary, and return it. |
246 Takes either a filename or directory name as input. If it's a | 208 Takes either a filename or directory name as input. If it's a |
247 directory name, we assume you want the file to be called keyval. | 209 directory name, we assume you want the file to be called keyval. |
248 """ | 210 """ |
249 if os.path.isdir(path): | 211 if os.path.isdir(path): |
250 path = os.path.join(path, 'keyval') | 212 path = os.path.join(path, 'keyval') |
251 keyval = {} | 213 keyval = {} |
252 if os.path.exists(path): | 214 if os.path.exists(path): |
(...skipping 1008 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1261 arg_re = re.compile(r'(\w+)[:=](.*)$') | 1223 arg_re = re.compile(r'(\w+)[:=](.*)$') |
1262 dict = {} | 1224 dict = {} |
1263 for arg in args: | 1225 for arg in args: |
1264 match = arg_re.match(arg) | 1226 match = arg_re.match(arg) |
1265 if match: | 1227 if match: |
1266 dict[match.group(1).lower()] = match.group(2) | 1228 dict[match.group(1).lower()] = match.group(2) |
1267 else: | 1229 else: |
1268 logging.warning("args_to_dict: argument '%s' doesn't match " | 1230 logging.warning("args_to_dict: argument '%s' doesn't match " |
1269 "'%s' pattern. Ignored." % (arg, arg_re.pattern)) | 1231 "'%s' pattern. Ignored." % (arg, arg_re.pattern)) |
1270 return dict | 1232 return dict |
1271 | |
1272 | |
1273 def get_unused_port(): | |
1274 """ | |
1275 Finds a semi-random available port. A race condition is still | |
1276 possible after the port number is returned, if another process | |
1277 happens to bind it. | |
1278 | |
1279 Returns: | |
1280 A port number that is unused on both TCP and UDP. | |
1281 """ | |
1282 | |
1283 def try_bind(port, socket_type, socket_proto): | |
1284 s = socket.socket(socket.AF_INET, socket_type, socket_proto) | |
1285 try: | |
1286 try: | |
1287 s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) | |
1288 s.bind(('', port)) | |
1289 return s.getsockname()[1] | |
1290 except socket.error: | |
1291 return None | |
1292 finally: | |
1293 s.close() | |
1294 | |
1295 # On the 2.6 kernel, calling try_bind() on UDP socket returns the | |
1296 # same port over and over. So always try TCP first. | |
1297 while True: | |
1298 # Ask the OS for an unused port. | |
1299 port = try_bind(0, socket.SOCK_STREAM, socket.IPPROTO_TCP) | |
1300 # Check if this port is unused on the other protocol. | |
1301 if port and try_bind(port, socket.SOCK_DGRAM, socket.IPPROTO_UDP): | |
1302 return port | |
OLD | NEW |