Mercurial > python-hglib
annotate hglib/util.py @ 62:d1f57f162274
closefds on posix when using subprocess
see added test for a clarification on why this is needed
author | Idan Kamara <idankk86@gmail.com> |
---|---|
date | Fri, 19 Aug 2011 22:24:14 +0300 |
parents | 3d7e0325ba1c |
children | 15485fa4b35e |
rev | line source |
---|---|
62
d1f57f162274
closefds on posix when using subprocess
Idan Kamara <idankk86@gmail.com>
parents:
49
diff
changeset
|
1 import itertools, cStringIO, error, os |
d1f57f162274
closefds on posix when using subprocess
Idan Kamara <idankk86@gmail.com>
parents:
49
diff
changeset
|
2 |
d1f57f162274
closefds on posix when using subprocess
Idan Kamara <idankk86@gmail.com>
parents:
49
diff
changeset
|
3 closefds = os.name == 'posix' |
0 | 4 |
5 def grouper(n, iterable): | |
6 ''' list(grouper(2, range(4))) -> [(0, 1), (2, 3)] ''' | |
7 args = [iter(iterable)] * n | |
8 return itertools.izip(*args) | |
3
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
9 |
8
3ac38d500d68
move hgclient._eatlines to util
Idan Kamara <idankk86@gmail.com>
parents:
3
diff
changeset
|
10 def eatlines(s, n): |
9
5882a698ad5c
util: rewrite eatlines (faster and simpler version)
Idan Kamara <idankk86@gmail.com>
parents:
8
diff
changeset
|
11 """ |
5882a698ad5c
util: rewrite eatlines (faster and simpler version)
Idan Kamara <idankk86@gmail.com>
parents:
8
diff
changeset
|
12 >>> eatlines("1\\n2", 1) |
5882a698ad5c
util: rewrite eatlines (faster and simpler version)
Idan Kamara <idankk86@gmail.com>
parents:
8
diff
changeset
|
13 '2' |
5882a698ad5c
util: rewrite eatlines (faster and simpler version)
Idan Kamara <idankk86@gmail.com>
parents:
8
diff
changeset
|
14 >>> eatlines("1\\n2", 2) |
5882a698ad5c
util: rewrite eatlines (faster and simpler version)
Idan Kamara <idankk86@gmail.com>
parents:
8
diff
changeset
|
15 '' |
5882a698ad5c
util: rewrite eatlines (faster and simpler version)
Idan Kamara <idankk86@gmail.com>
parents:
8
diff
changeset
|
16 >>> eatlines("1\\n2", 3) |
5882a698ad5c
util: rewrite eatlines (faster and simpler version)
Idan Kamara <idankk86@gmail.com>
parents:
8
diff
changeset
|
17 '' |
5882a698ad5c
util: rewrite eatlines (faster and simpler version)
Idan Kamara <idankk86@gmail.com>
parents:
8
diff
changeset
|
18 >>> eatlines("1\\n2\\n3", 1) |
5882a698ad5c
util: rewrite eatlines (faster and simpler version)
Idan Kamara <idankk86@gmail.com>
parents:
8
diff
changeset
|
19 '2\\n3' |
5882a698ad5c
util: rewrite eatlines (faster and simpler version)
Idan Kamara <idankk86@gmail.com>
parents:
8
diff
changeset
|
20 """ |
5882a698ad5c
util: rewrite eatlines (faster and simpler version)
Idan Kamara <idankk86@gmail.com>
parents:
8
diff
changeset
|
21 cs = cStringIO.StringIO(s) |
8
3ac38d500d68
move hgclient._eatlines to util
Idan Kamara <idankk86@gmail.com>
parents:
3
diff
changeset
|
22 |
9
5882a698ad5c
util: rewrite eatlines (faster and simpler version)
Idan Kamara <idankk86@gmail.com>
parents:
8
diff
changeset
|
23 for line in cs: |
5882a698ad5c
util: rewrite eatlines (faster and simpler version)
Idan Kamara <idankk86@gmail.com>
parents:
8
diff
changeset
|
24 n -= 1 |
5882a698ad5c
util: rewrite eatlines (faster and simpler version)
Idan Kamara <idankk86@gmail.com>
parents:
8
diff
changeset
|
25 if n == 0: |
5882a698ad5c
util: rewrite eatlines (faster and simpler version)
Idan Kamara <idankk86@gmail.com>
parents:
8
diff
changeset
|
26 return cs.read() |
5882a698ad5c
util: rewrite eatlines (faster and simpler version)
Idan Kamara <idankk86@gmail.com>
parents:
8
diff
changeset
|
27 return '' |
8
3ac38d500d68
move hgclient._eatlines to util
Idan Kamara <idankk86@gmail.com>
parents:
3
diff
changeset
|
28 |
19 | 29 def skiplines(s, prefix): |
30 """ | |
31 Skip lines starting with prefix in s | |
32 | |
33 >>> skiplines('a\\nb\\na\\n', 'a') | |
34 'b\\na\\n' | |
35 >>> skiplines('a\\na\\n', 'a') | |
36 '' | |
37 >>> skiplines('', 'a') | |
38 '' | |
39 >>> skiplines('a\\nb', 'b') | |
40 'a\\nb' | |
41 """ | |
42 cs = cStringIO.StringIO(s) | |
43 | |
44 for line in cs: | |
45 if not line.startswith(prefix): | |
46 return line + cs.read() | |
47 | |
48 return '' | |
49 | |
3
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
50 def cmdbuilder(name, *args, **kwargs): |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
51 """ |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
52 A helper for building the command arguments |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
53 |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
54 args are the positional arguments |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
55 |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
56 kwargs are the options |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
57 keys that are single lettered are prepended with '-', others with '--', |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
58 underscores are replaced with dashes |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
59 |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
60 keys with False boolean values are ignored, lists add the key multiple times |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
61 |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
62 None arguments are skipped |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
63 |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
64 >>> cmdbuilder('cmd', a=True, b=False, c=None) |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
65 ['cmd', '-a'] |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
66 >>> cmdbuilder('cmd', long=True) |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
67 ['cmd', '--long'] |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
68 >>> cmdbuilder('cmd', str='s') |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
69 ['cmd', '--str', 's'] |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
70 >>> cmdbuilder('cmd', d_ash=True) |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
71 ['cmd', '--d-ash'] |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
72 >>> cmdbuilder('cmd', _=True) |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
73 ['cmd', '-'] |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
74 >>> cmdbuilder('cmd', list=[1, 2]) |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
75 ['cmd', '--list', '1', '--list', '2'] |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
76 >>> cmdbuilder('cmd', None) |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
77 ['cmd'] |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
78 """ |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
79 cmd = [name] |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
80 for arg, val in kwargs.items(): |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
81 if val is None: |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
82 continue |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
83 |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
84 arg = arg.replace('_', '-') |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
85 if arg != '-': |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
86 arg = '-' + arg if len(arg) == 1 else '--' + arg |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
87 if isinstance(val, bool): |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
88 if val: |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
89 cmd.append(arg) |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
90 elif isinstance(val, list): |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
91 for v in val: |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
92 cmd.append(arg) |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
93 cmd.append(str(v)) |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
94 else: |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
95 cmd.append(arg) |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
96 cmd.append(str(val)) |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
97 |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
98 for a in args: |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
99 if a is not None: |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
100 cmd.append(a) |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
101 |
d7903b923217
util: add cmdbuilder, a helper function to generate the command to run
Idan Kamara <idankk86@gmail.com>
parents:
0
diff
changeset
|
102 return cmd |
49
3d7e0325ba1c
util: introduce a generic error handler that is aware of return codes
Idan Kamara <idankk86@gmail.com>
parents:
19
diff
changeset
|
103 |
3d7e0325ba1c
util: introduce a generic error handler that is aware of return codes
Idan Kamara <idankk86@gmail.com>
parents:
19
diff
changeset
|
104 class reterrorhandler(object): |
3d7e0325ba1c
util: introduce a generic error handler that is aware of return codes
Idan Kamara <idankk86@gmail.com>
parents:
19
diff
changeset
|
105 """ |
3d7e0325ba1c
util: introduce a generic error handler that is aware of return codes
Idan Kamara <idankk86@gmail.com>
parents:
19
diff
changeset
|
106 This class is meant to be used with rawcommand() error handler argument. |
3d7e0325ba1c
util: introduce a generic error handler that is aware of return codes
Idan Kamara <idankk86@gmail.com>
parents:
19
diff
changeset
|
107 It remembers the return value the command returned if it's one of allowed |
3d7e0325ba1c
util: introduce a generic error handler that is aware of return codes
Idan Kamara <idankk86@gmail.com>
parents:
19
diff
changeset
|
108 values, which is only 1 if none are given. Otherwise it raises a CommandError. |
3d7e0325ba1c
util: introduce a generic error handler that is aware of return codes
Idan Kamara <idankk86@gmail.com>
parents:
19
diff
changeset
|
109 |
3d7e0325ba1c
util: introduce a generic error handler that is aware of return codes
Idan Kamara <idankk86@gmail.com>
parents:
19
diff
changeset
|
110 >>> e = reterrorhandler('') |
3d7e0325ba1c
util: introduce a generic error handler that is aware of return codes
Idan Kamara <idankk86@gmail.com>
parents:
19
diff
changeset
|
111 >>> bool(e) |
3d7e0325ba1c
util: introduce a generic error handler that is aware of return codes
Idan Kamara <idankk86@gmail.com>
parents:
19
diff
changeset
|
112 True |
3d7e0325ba1c
util: introduce a generic error handler that is aware of return codes
Idan Kamara <idankk86@gmail.com>
parents:
19
diff
changeset
|
113 >>> e(1, 'a', '') |
3d7e0325ba1c
util: introduce a generic error handler that is aware of return codes
Idan Kamara <idankk86@gmail.com>
parents:
19
diff
changeset
|
114 'a' |
3d7e0325ba1c
util: introduce a generic error handler that is aware of return codes
Idan Kamara <idankk86@gmail.com>
parents:
19
diff
changeset
|
115 >>> bool(e) |
3d7e0325ba1c
util: introduce a generic error handler that is aware of return codes
Idan Kamara <idankk86@gmail.com>
parents:
19
diff
changeset
|
116 False |
3d7e0325ba1c
util: introduce a generic error handler that is aware of return codes
Idan Kamara <idankk86@gmail.com>
parents:
19
diff
changeset
|
117 """ |
3d7e0325ba1c
util: introduce a generic error handler that is aware of return codes
Idan Kamara <idankk86@gmail.com>
parents:
19
diff
changeset
|
118 def __init__(self, args, allowed=None): |
3d7e0325ba1c
util: introduce a generic error handler that is aware of return codes
Idan Kamara <idankk86@gmail.com>
parents:
19
diff
changeset
|
119 self.args = args |
3d7e0325ba1c
util: introduce a generic error handler that is aware of return codes
Idan Kamara <idankk86@gmail.com>
parents:
19
diff
changeset
|
120 self.ret = 0 |
3d7e0325ba1c
util: introduce a generic error handler that is aware of return codes
Idan Kamara <idankk86@gmail.com>
parents:
19
diff
changeset
|
121 if allowed is None: |
3d7e0325ba1c
util: introduce a generic error handler that is aware of return codes
Idan Kamara <idankk86@gmail.com>
parents:
19
diff
changeset
|
122 self.allowed = [1] |
3d7e0325ba1c
util: introduce a generic error handler that is aware of return codes
Idan Kamara <idankk86@gmail.com>
parents:
19
diff
changeset
|
123 else: |
3d7e0325ba1c
util: introduce a generic error handler that is aware of return codes
Idan Kamara <idankk86@gmail.com>
parents:
19
diff
changeset
|
124 self.allowed = allowed |
3d7e0325ba1c
util: introduce a generic error handler that is aware of return codes
Idan Kamara <idankk86@gmail.com>
parents:
19
diff
changeset
|
125 |
3d7e0325ba1c
util: introduce a generic error handler that is aware of return codes
Idan Kamara <idankk86@gmail.com>
parents:
19
diff
changeset
|
126 def __call__(self, ret, out, err): |
3d7e0325ba1c
util: introduce a generic error handler that is aware of return codes
Idan Kamara <idankk86@gmail.com>
parents:
19
diff
changeset
|
127 self.ret = ret |
3d7e0325ba1c
util: introduce a generic error handler that is aware of return codes
Idan Kamara <idankk86@gmail.com>
parents:
19
diff
changeset
|
128 if ret not in self.allowed: |
3d7e0325ba1c
util: introduce a generic error handler that is aware of return codes
Idan Kamara <idankk86@gmail.com>
parents:
19
diff
changeset
|
129 raise error.CommandError(self.args, ret, out, err) |
3d7e0325ba1c
util: introduce a generic error handler that is aware of return codes
Idan Kamara <idankk86@gmail.com>
parents:
19
diff
changeset
|
130 return out |
3d7e0325ba1c
util: introduce a generic error handler that is aware of return codes
Idan Kamara <idankk86@gmail.com>
parents:
19
diff
changeset
|
131 |
3d7e0325ba1c
util: introduce a generic error handler that is aware of return codes
Idan Kamara <idankk86@gmail.com>
parents:
19
diff
changeset
|
132 def __nonzero__(self): |
3d7e0325ba1c
util: introduce a generic error handler that is aware of return codes
Idan Kamara <idankk86@gmail.com>
parents:
19
diff
changeset
|
133 """ Returns True if the return code was 0, False otherwise """ |
3d7e0325ba1c
util: introduce a generic error handler that is aware of return codes
Idan Kamara <idankk86@gmail.com>
parents:
19
diff
changeset
|
134 return self.ret == 0 |