Update year to 2009 in various places
[zeroinstall/zeroinstall-rsl.git] / zeroinstall / support / __init__.py
blobd766a23e96cde7283e085dc4ce3a5db1aaa0e454
1 """
2 Useful support routines (for internal use).
4 These functions aren't really Zero Install specific; they're things we might
5 wish were in the standard library.
7 @since: 0.27
8 """
10 # Copyright (C) 2009, Thomas Leonard
11 # See the README file for details, or visit http://0install.net.
13 import os, logging
15 def find_in_path(prog):
16 """Search $PATH for prog.
17 If prog is an absolute path, return it unmodified.
18 @param prog: name of executable to find
19 @return: the full path of prog, or None if not found
20 @since: 0.27
21 """
22 if os.path.isabs(prog): return prog
23 for d in os.environ.get('PATH', '/bin:/usr/bin').split(':'):
24 path = os.path.join(d, prog)
25 if os.path.isfile(path):
26 return path
27 return None
29 def read_bytes(fd, nbytes, null_ok = False):
30 """Read exactly nbytes from fd.
31 @param fd: file descriptor to read from
32 @param nbytes: number of bytes to read
33 @param null_ok: if True, it's OK to receive EOF immediately (we then return None)
34 @return: the bytes read
35 @raise Exception: if we received less than nbytes of data
36 """
37 data = ''
38 while nbytes:
39 got = os.read(fd, nbytes)
40 if not got:
41 if null_ok and not data:
42 return None
43 raise Exception("Unexpected end-of-stream. Data so far %s; expecting %d bytes more."
44 % (repr(data), nbytes))
45 data += got
46 nbytes -= len(got)
47 logging.debug("Message received: %s" % repr(data))
48 return data
50 def pretty_size(size):
51 """Format a size for printing.
52 @param size: the size in bytes
53 @type size: int (or None)
54 @return: the formatted size
55 @rtype: str
56 @since: 0.27"""
57 if size is None:
58 return '?'
59 if size < 2048:
60 return '%d bytes' % size
61 size = float(size)
62 for unit in ('KB', 'MB', 'GB', 'TB'):
63 size /= 1024
64 if size < 2048:
65 break
66 return '%.1f %s' % (size, unit)
68 def ro_rmtree(root):
69 """Like shutil.rmtree, except that we also delete read-only items.
70 @param root: the root of the subtree to remove
71 @type root: str
72 @since: 0.28"""
73 import shutil
74 for main, dirs, files in os.walk(root):
75 os.chmod(main, 0700)
76 shutil.rmtree(root)