1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
|
import os, subprocess, sys
from hglib import error
try:
from io import BytesIO
except ImportError:
from cStringIO import StringIO as BytesIO
if sys.version_info[0] > 2:
izip = zip
integertypes = (int,)
def b(s):
"""Encode the string as bytes."""
return s.encode('latin-1')
else:
from itertools import izip
integertypes = (long, int)
bytes = str # Defined in Python 2.6/2.7, but to the same value.
def b(s):
"""Encode the string as bytes."""
return s
def strtobytes(s):
"""Return the bytes of the string representation of an object."""
return str(s).encode('latin-1')
def grouper(n, iterable):
''' list(grouper(2, range(4))) -> [(0, 1), (2, 3)] '''
args = [iter(iterable)] * n
return izip(*args)
def eatlines(s, n):
"""
>>> eatlines(b("1\\n2"), 1) == b('2')
True
>>> eatlines(b("1\\n2"), 2) == b('')
True
>>> eatlines(b("1\\n2"), 3) == b('')
True
>>> eatlines(b("1\\n2\\n3"), 1) == b('2\\n3')
True
"""
cs = BytesIO(s)
for line in cs:
n -= 1
if n == 0:
return cs.read()
return b('')
def skiplines(s, prefix):
"""
Skip lines starting with prefix in s
>>> skiplines(b('a\\nb\\na\\n'), b('a')) == b('b\\na\\n')
True
>>> skiplines(b('a\\na\\n'), b('a')) == b('')
True
>>> skiplines(b(''), b('a')) == b('')
True
>>> skiplines(b('a\\nb'), b('b')) == b('a\\nb')
True
"""
cs = BytesIO(s)
for line in cs:
if not line.startswith(prefix):
return line + cs.read()
return b('')
def _cmdval(val):
if isinstance(val, bytes):
return val
else:
return strtobytes(val)
def cmdbuilder(name, *args, **kwargs):
"""
A helper for building the command arguments
args are the positional arguments
kwargs are the options
keys that are single lettered are prepended with '-', others with '--',
underscores are replaced with dashes
keys with False boolean values are ignored, lists add the key multiple times
None arguments are skipped
>>> cmdbuilder(b('cmd'), a=True, b=False, c=None) == [b('cmd'), b('-a')]
True
>>> cmdbuilder(b('cmd'), long=True) == [b('cmd'), b('--long')]
True
>>> cmdbuilder(b('cmd'), str=b('s')) == [b('cmd'), b('--str'), b('s')]
True
>>> cmdbuilder(b('cmd'), d_ash=True) == [b('cmd'), b('--d-ash')]
True
>>> cmdbuilder(b('cmd'), _=True) == [b('cmd'), b('-')]
True
>>> expect = [b('cmd'), b('--list'), b('1'), b('--list'), b('2')]
>>> cmdbuilder(b('cmd'), list=[1, 2]) == expect
True
>>> cmdbuilder(b('cmd'), None) == [b('cmd')]
True
"""
cmd = [name]
for arg, val in kwargs.items():
if val is None:
continue
arg = arg.encode('latin-1').replace(b('_'), b('-'))
if arg != b('-'):
if len(arg) == 1:
arg = b('-') + arg
else:
arg = b('--') + arg
if isinstance(val, bool):
if val:
cmd.append(arg)
elif isinstance(val, list):
for v in val:
cmd.append(arg)
cmd.append(_cmdval(v))
else:
cmd.append(arg)
cmd.append(_cmdval(val))
for a in args:
if a is not None:
cmd.append(a)
return cmd
class reterrorhandler(object):
"""This class is meant to be used with rawcommand() error handler
argument. It remembers the return value the command returned if
it's one of allowed values, which is only 1 if none are given.
Otherwise it raises a CommandError.
>>> e = reterrorhandler('')
>>> bool(e)
True
>>> e(1, 'a', '')
'a'
>>> bool(e)
False
"""
def __init__(self, args, allowed=None):
self.args = args
self.ret = 0
if allowed is None:
self.allowed = [1]
else:
self.allowed = allowed
def __call__(self, ret, out, err):
self.ret = ret
if ret not in self.allowed:
raise error.CommandError(self.args, ret, out, err)
return out
def __nonzero__(self):
""" Returns True if the return code was 0, False otherwise """
return self.ret == 0
def __bool__(self):
return self.__nonzero__()
class propertycache(object):
"""
Decorator that remembers the return value of a function call.
>>> execcount = 0
>>> class obj(object):
... def func(self):
... global execcount
... execcount += 1
... return []
... func = propertycache(func)
>>> o = obj()
>>> o.func
[]
>>> execcount
1
>>> o.func
[]
>>> execcount
1
"""
def __init__(self, func):
self.func = func
self.name = func.__name__
def __get__(self, obj, type=None):
result = self.func(obj)
setattr(obj, self.name, result)
return result
close_fds = os.name == 'posix'
startupinfo = None
if os.name == 'nt':
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
def popen(args, env=None):
environ = None
if env:
environ = dict(os.environ)
environ.update(env)
return subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, close_fds=close_fds,
startupinfo=startupinfo, env=environ)
|