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 |
205 def read_keyval(path): | 243 def read_keyval(path): |
206 """ | 244 """ |
207 Read a key-value pair format file into a dictionary, and return it. | 245 Read a key-value pair format file into a dictionary, and return it. |
208 Takes either a filename or directory name as input. If it's a | 246 Takes either a filename or directory name as input. If it's a |
209 directory name, we assume you want the file to be called keyval. | 247 directory name, we assume you want the file to be called keyval. |
210 """ | 248 """ |
211 if os.path.isdir(path): | 249 if os.path.isdir(path): |
212 path = os.path.join(path, 'keyval') | 250 path = os.path.join(path, 'keyval') |
213 keyval = {} | 251 keyval = {} |
214 if os.path.exists(path): | 252 if os.path.exists(path): |
(...skipping 1008 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1223 arg_re = re.compile(r'(\w+)[:=](.*)$') | 1261 arg_re = re.compile(r'(\w+)[:=](.*)$') |
1224 dict = {} | 1262 dict = {} |
1225 for arg in args: | 1263 for arg in args: |
1226 match = arg_re.match(arg) | 1264 match = arg_re.match(arg) |
1227 if match: | 1265 if match: |
1228 dict[match.group(1).lower()] = match.group(2) | 1266 dict[match.group(1).lower()] = match.group(2) |
1229 else: | 1267 else: |
1230 logging.warning("args_to_dict: argument '%s' doesn't match " | 1268 logging.warning("args_to_dict: argument '%s' doesn't match " |
1231 "'%s' pattern. Ignored." % (arg, arg_re.pattern)) | 1269 "'%s' pattern. Ignored." % (arg, arg_re.pattern)) |
1232 return dict | 1270 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 |