##// END OF EJS Templates
pycompat: export a handle on concurrent.futures...
Gregory Szorc -
r37646:8da30cea default
parent child Browse files
Show More
@@ -1,380 +1,383 b''
1 # pycompat.py - portability shim for python 3
1 # pycompat.py - portability shim for python 3
2 #
2 #
3 # This software may be used and distributed according to the terms of the
3 # This software may be used and distributed according to the terms of the
4 # GNU General Public License version 2 or any later version.
4 # GNU General Public License version 2 or any later version.
5
5
6 """Mercurial portability shim for python 3.
6 """Mercurial portability shim for python 3.
7
7
8 This contains aliases to hide python version-specific details from the core.
8 This contains aliases to hide python version-specific details from the core.
9 """
9 """
10
10
11 from __future__ import absolute_import
11 from __future__ import absolute_import
12
12
13 import getopt
13 import getopt
14 import inspect
14 import inspect
15 import os
15 import os
16 import shlex
16 import shlex
17 import sys
17 import sys
18
18
19 ispy3 = (sys.version_info[0] >= 3)
19 ispy3 = (sys.version_info[0] >= 3)
20 ispypy = (r'__pypy__' in sys.builtin_module_names)
20 ispypy = (r'__pypy__' in sys.builtin_module_names)
21
21
22 if not ispy3:
22 if not ispy3:
23 import cookielib
23 import cookielib
24 import cPickle as pickle
24 import cPickle as pickle
25 import httplib
25 import httplib
26 import Queue as _queue
26 import Queue as _queue
27 import SocketServer as socketserver
27 import SocketServer as socketserver
28 import xmlrpclib
28 import xmlrpclib
29
30 from .thirdparty.concurrent import futures
29 else:
31 else:
32 import concurrent.futures as futures
30 import http.cookiejar as cookielib
33 import http.cookiejar as cookielib
31 import http.client as httplib
34 import http.client as httplib
32 import pickle
35 import pickle
33 import queue as _queue
36 import queue as _queue
34 import socketserver
37 import socketserver
35 import xmlrpc.client as xmlrpclib
38 import xmlrpc.client as xmlrpclib
36
39
37 empty = _queue.Empty
40 empty = _queue.Empty
38 queue = _queue.Queue
41 queue = _queue.Queue
39
42
40 def identity(a):
43 def identity(a):
41 return a
44 return a
42
45
43 if ispy3:
46 if ispy3:
44 import builtins
47 import builtins
45 import functools
48 import functools
46 import io
49 import io
47 import struct
50 import struct
48
51
49 fsencode = os.fsencode
52 fsencode = os.fsencode
50 fsdecode = os.fsdecode
53 fsdecode = os.fsdecode
51 oscurdir = os.curdir.encode('ascii')
54 oscurdir = os.curdir.encode('ascii')
52 oslinesep = os.linesep.encode('ascii')
55 oslinesep = os.linesep.encode('ascii')
53 osname = os.name.encode('ascii')
56 osname = os.name.encode('ascii')
54 ospathsep = os.pathsep.encode('ascii')
57 ospathsep = os.pathsep.encode('ascii')
55 ospardir = os.pardir.encode('ascii')
58 ospardir = os.pardir.encode('ascii')
56 ossep = os.sep.encode('ascii')
59 ossep = os.sep.encode('ascii')
57 osaltsep = os.altsep
60 osaltsep = os.altsep
58 if osaltsep:
61 if osaltsep:
59 osaltsep = osaltsep.encode('ascii')
62 osaltsep = osaltsep.encode('ascii')
60 # os.getcwd() on Python 3 returns string, but it has os.getcwdb() which
63 # os.getcwd() on Python 3 returns string, but it has os.getcwdb() which
61 # returns bytes.
64 # returns bytes.
62 getcwd = os.getcwdb
65 getcwd = os.getcwdb
63 sysplatform = sys.platform.encode('ascii')
66 sysplatform = sys.platform.encode('ascii')
64 sysexecutable = sys.executable
67 sysexecutable = sys.executable
65 if sysexecutable:
68 if sysexecutable:
66 sysexecutable = os.fsencode(sysexecutable)
69 sysexecutable = os.fsencode(sysexecutable)
67 bytesio = io.BytesIO
70 bytesio = io.BytesIO
68 # TODO deprecate stringio name, as it is a lie on Python 3.
71 # TODO deprecate stringio name, as it is a lie on Python 3.
69 stringio = bytesio
72 stringio = bytesio
70
73
71 def maplist(*args):
74 def maplist(*args):
72 return list(map(*args))
75 return list(map(*args))
73
76
74 def rangelist(*args):
77 def rangelist(*args):
75 return list(range(*args))
78 return list(range(*args))
76
79
77 def ziplist(*args):
80 def ziplist(*args):
78 return list(zip(*args))
81 return list(zip(*args))
79
82
80 rawinput = input
83 rawinput = input
81 getargspec = inspect.getfullargspec
84 getargspec = inspect.getfullargspec
82
85
83 # TODO: .buffer might not exist if std streams were replaced; we'll need
86 # TODO: .buffer might not exist if std streams were replaced; we'll need
84 # a silly wrapper to make a bytes stream backed by a unicode one.
87 # a silly wrapper to make a bytes stream backed by a unicode one.
85 stdin = sys.stdin.buffer
88 stdin = sys.stdin.buffer
86 stdout = sys.stdout.buffer
89 stdout = sys.stdout.buffer
87 stderr = sys.stderr.buffer
90 stderr = sys.stderr.buffer
88
91
89 # Since Python 3 converts argv to wchar_t type by Py_DecodeLocale() on Unix,
92 # Since Python 3 converts argv to wchar_t type by Py_DecodeLocale() on Unix,
90 # we can use os.fsencode() to get back bytes argv.
93 # we can use os.fsencode() to get back bytes argv.
91 #
94 #
92 # https://hg.python.org/cpython/file/v3.5.1/Programs/python.c#l55
95 # https://hg.python.org/cpython/file/v3.5.1/Programs/python.c#l55
93 #
96 #
94 # TODO: On Windows, the native argv is wchar_t, so we'll need a different
97 # TODO: On Windows, the native argv is wchar_t, so we'll need a different
95 # workaround to simulate the Python 2 (i.e. ANSI Win32 API) behavior.
98 # workaround to simulate the Python 2 (i.e. ANSI Win32 API) behavior.
96 if getattr(sys, 'argv', None) is not None:
99 if getattr(sys, 'argv', None) is not None:
97 sysargv = list(map(os.fsencode, sys.argv))
100 sysargv = list(map(os.fsencode, sys.argv))
98
101
99 bytechr = struct.Struct('>B').pack
102 bytechr = struct.Struct('>B').pack
100 byterepr = b'%r'.__mod__
103 byterepr = b'%r'.__mod__
101
104
102 class bytestr(bytes):
105 class bytestr(bytes):
103 """A bytes which mostly acts as a Python 2 str
106 """A bytes which mostly acts as a Python 2 str
104
107
105 >>> bytestr(), bytestr(bytearray(b'foo')), bytestr(u'ascii'), bytestr(1)
108 >>> bytestr(), bytestr(bytearray(b'foo')), bytestr(u'ascii'), bytestr(1)
106 ('', 'foo', 'ascii', '1')
109 ('', 'foo', 'ascii', '1')
107 >>> s = bytestr(b'foo')
110 >>> s = bytestr(b'foo')
108 >>> assert s is bytestr(s)
111 >>> assert s is bytestr(s)
109
112
110 __bytes__() should be called if provided:
113 __bytes__() should be called if provided:
111
114
112 >>> class bytesable(object):
115 >>> class bytesable(object):
113 ... def __bytes__(self):
116 ... def __bytes__(self):
114 ... return b'bytes'
117 ... return b'bytes'
115 >>> bytestr(bytesable())
118 >>> bytestr(bytesable())
116 'bytes'
119 'bytes'
117
120
118 There's no implicit conversion from non-ascii str as its encoding is
121 There's no implicit conversion from non-ascii str as its encoding is
119 unknown:
122 unknown:
120
123
121 >>> bytestr(chr(0x80)) # doctest: +ELLIPSIS
124 >>> bytestr(chr(0x80)) # doctest: +ELLIPSIS
122 Traceback (most recent call last):
125 Traceback (most recent call last):
123 ...
126 ...
124 UnicodeEncodeError: ...
127 UnicodeEncodeError: ...
125
128
126 Comparison between bytestr and bytes should work:
129 Comparison between bytestr and bytes should work:
127
130
128 >>> assert bytestr(b'foo') == b'foo'
131 >>> assert bytestr(b'foo') == b'foo'
129 >>> assert b'foo' == bytestr(b'foo')
132 >>> assert b'foo' == bytestr(b'foo')
130 >>> assert b'f' in bytestr(b'foo')
133 >>> assert b'f' in bytestr(b'foo')
131 >>> assert bytestr(b'f') in b'foo'
134 >>> assert bytestr(b'f') in b'foo'
132
135
133 Sliced elements should be bytes, not integer:
136 Sliced elements should be bytes, not integer:
134
137
135 >>> s[1], s[:2]
138 >>> s[1], s[:2]
136 (b'o', b'fo')
139 (b'o', b'fo')
137 >>> list(s), list(reversed(s))
140 >>> list(s), list(reversed(s))
138 ([b'f', b'o', b'o'], [b'o', b'o', b'f'])
141 ([b'f', b'o', b'o'], [b'o', b'o', b'f'])
139
142
140 As bytestr type isn't propagated across operations, you need to cast
143 As bytestr type isn't propagated across operations, you need to cast
141 bytes to bytestr explicitly:
144 bytes to bytestr explicitly:
142
145
143 >>> s = bytestr(b'foo').upper()
146 >>> s = bytestr(b'foo').upper()
144 >>> t = bytestr(s)
147 >>> t = bytestr(s)
145 >>> s[0], t[0]
148 >>> s[0], t[0]
146 (70, b'F')
149 (70, b'F')
147
150
148 Be careful to not pass a bytestr object to a function which expects
151 Be careful to not pass a bytestr object to a function which expects
149 bytearray-like behavior.
152 bytearray-like behavior.
150
153
151 >>> t = bytes(t) # cast to bytes
154 >>> t = bytes(t) # cast to bytes
152 >>> assert type(t) is bytes
155 >>> assert type(t) is bytes
153 """
156 """
154
157
155 def __new__(cls, s=b''):
158 def __new__(cls, s=b''):
156 if isinstance(s, bytestr):
159 if isinstance(s, bytestr):
157 return s
160 return s
158 if (not isinstance(s, (bytes, bytearray))
161 if (not isinstance(s, (bytes, bytearray))
159 and not hasattr(s, u'__bytes__')): # hasattr-py3-only
162 and not hasattr(s, u'__bytes__')): # hasattr-py3-only
160 s = str(s).encode(u'ascii')
163 s = str(s).encode(u'ascii')
161 return bytes.__new__(cls, s)
164 return bytes.__new__(cls, s)
162
165
163 def __getitem__(self, key):
166 def __getitem__(self, key):
164 s = bytes.__getitem__(self, key)
167 s = bytes.__getitem__(self, key)
165 if not isinstance(s, bytes):
168 if not isinstance(s, bytes):
166 s = bytechr(s)
169 s = bytechr(s)
167 return s
170 return s
168
171
169 def __iter__(self):
172 def __iter__(self):
170 return iterbytestr(bytes.__iter__(self))
173 return iterbytestr(bytes.__iter__(self))
171
174
172 def __repr__(self):
175 def __repr__(self):
173 return bytes.__repr__(self)[1:] # drop b''
176 return bytes.__repr__(self)[1:] # drop b''
174
177
175 def iterbytestr(s):
178 def iterbytestr(s):
176 """Iterate bytes as if it were a str object of Python 2"""
179 """Iterate bytes as if it were a str object of Python 2"""
177 return map(bytechr, s)
180 return map(bytechr, s)
178
181
179 def maybebytestr(s):
182 def maybebytestr(s):
180 """Promote bytes to bytestr"""
183 """Promote bytes to bytestr"""
181 if isinstance(s, bytes):
184 if isinstance(s, bytes):
182 return bytestr(s)
185 return bytestr(s)
183 return s
186 return s
184
187
185 def sysbytes(s):
188 def sysbytes(s):
186 """Convert an internal str (e.g. keyword, __doc__) back to bytes
189 """Convert an internal str (e.g. keyword, __doc__) back to bytes
187
190
188 This never raises UnicodeEncodeError, but only ASCII characters
191 This never raises UnicodeEncodeError, but only ASCII characters
189 can be round-trip by sysstr(sysbytes(s)).
192 can be round-trip by sysstr(sysbytes(s)).
190 """
193 """
191 return s.encode(u'utf-8')
194 return s.encode(u'utf-8')
192
195
193 def sysstr(s):
196 def sysstr(s):
194 """Return a keyword str to be passed to Python functions such as
197 """Return a keyword str to be passed to Python functions such as
195 getattr() and str.encode()
198 getattr() and str.encode()
196
199
197 This never raises UnicodeDecodeError. Non-ascii characters are
200 This never raises UnicodeDecodeError. Non-ascii characters are
198 considered invalid and mapped to arbitrary but unique code points
201 considered invalid and mapped to arbitrary but unique code points
199 such that 'sysstr(a) != sysstr(b)' for all 'a != b'.
202 such that 'sysstr(a) != sysstr(b)' for all 'a != b'.
200 """
203 """
201 if isinstance(s, builtins.str):
204 if isinstance(s, builtins.str):
202 return s
205 return s
203 return s.decode(u'latin-1')
206 return s.decode(u'latin-1')
204
207
205 def strurl(url):
208 def strurl(url):
206 """Converts a bytes url back to str"""
209 """Converts a bytes url back to str"""
207 if isinstance(url, bytes):
210 if isinstance(url, bytes):
208 return url.decode(u'ascii')
211 return url.decode(u'ascii')
209 return url
212 return url
210
213
211 def bytesurl(url):
214 def bytesurl(url):
212 """Converts a str url to bytes by encoding in ascii"""
215 """Converts a str url to bytes by encoding in ascii"""
213 if isinstance(url, str):
216 if isinstance(url, str):
214 return url.encode(u'ascii')
217 return url.encode(u'ascii')
215 return url
218 return url
216
219
217 def raisewithtb(exc, tb):
220 def raisewithtb(exc, tb):
218 """Raise exception with the given traceback"""
221 """Raise exception with the given traceback"""
219 raise exc.with_traceback(tb)
222 raise exc.with_traceback(tb)
220
223
221 def getdoc(obj):
224 def getdoc(obj):
222 """Get docstring as bytes; may be None so gettext() won't confuse it
225 """Get docstring as bytes; may be None so gettext() won't confuse it
223 with _('')"""
226 with _('')"""
224 doc = getattr(obj, u'__doc__', None)
227 doc = getattr(obj, u'__doc__', None)
225 if doc is None:
228 if doc is None:
226 return doc
229 return doc
227 return sysbytes(doc)
230 return sysbytes(doc)
228
231
229 def _wrapattrfunc(f):
232 def _wrapattrfunc(f):
230 @functools.wraps(f)
233 @functools.wraps(f)
231 def w(object, name, *args):
234 def w(object, name, *args):
232 return f(object, sysstr(name), *args)
235 return f(object, sysstr(name), *args)
233 return w
236 return w
234
237
235 # these wrappers are automagically imported by hgloader
238 # these wrappers are automagically imported by hgloader
236 delattr = _wrapattrfunc(builtins.delattr)
239 delattr = _wrapattrfunc(builtins.delattr)
237 getattr = _wrapattrfunc(builtins.getattr)
240 getattr = _wrapattrfunc(builtins.getattr)
238 hasattr = _wrapattrfunc(builtins.hasattr)
241 hasattr = _wrapattrfunc(builtins.hasattr)
239 setattr = _wrapattrfunc(builtins.setattr)
242 setattr = _wrapattrfunc(builtins.setattr)
240 xrange = builtins.range
243 xrange = builtins.range
241 unicode = str
244 unicode = str
242
245
243 def open(name, mode='r', buffering=-1, encoding=None):
246 def open(name, mode='r', buffering=-1, encoding=None):
244 return builtins.open(name, sysstr(mode), buffering, encoding)
247 return builtins.open(name, sysstr(mode), buffering, encoding)
245
248
246 safehasattr = _wrapattrfunc(builtins.hasattr)
249 safehasattr = _wrapattrfunc(builtins.hasattr)
247
250
248 def _getoptbwrapper(orig, args, shortlist, namelist):
251 def _getoptbwrapper(orig, args, shortlist, namelist):
249 """
252 """
250 Takes bytes arguments, converts them to unicode, pass them to
253 Takes bytes arguments, converts them to unicode, pass them to
251 getopt.getopt(), convert the returned values back to bytes and then
254 getopt.getopt(), convert the returned values back to bytes and then
252 return them for Python 3 compatibility as getopt.getopt() don't accepts
255 return them for Python 3 compatibility as getopt.getopt() don't accepts
253 bytes on Python 3.
256 bytes on Python 3.
254 """
257 """
255 args = [a.decode('latin-1') for a in args]
258 args = [a.decode('latin-1') for a in args]
256 shortlist = shortlist.decode('latin-1')
259 shortlist = shortlist.decode('latin-1')
257 namelist = [a.decode('latin-1') for a in namelist]
260 namelist = [a.decode('latin-1') for a in namelist]
258 opts, args = orig(args, shortlist, namelist)
261 opts, args = orig(args, shortlist, namelist)
259 opts = [(a[0].encode('latin-1'), a[1].encode('latin-1'))
262 opts = [(a[0].encode('latin-1'), a[1].encode('latin-1'))
260 for a in opts]
263 for a in opts]
261 args = [a.encode('latin-1') for a in args]
264 args = [a.encode('latin-1') for a in args]
262 return opts, args
265 return opts, args
263
266
264 def strkwargs(dic):
267 def strkwargs(dic):
265 """
268 """
266 Converts the keys of a python dictonary to str i.e. unicodes so that
269 Converts the keys of a python dictonary to str i.e. unicodes so that
267 they can be passed as keyword arguments as dictonaries with bytes keys
270 they can be passed as keyword arguments as dictonaries with bytes keys
268 can't be passed as keyword arguments to functions on Python 3.
271 can't be passed as keyword arguments to functions on Python 3.
269 """
272 """
270 dic = dict((k.decode('latin-1'), v) for k, v in dic.iteritems())
273 dic = dict((k.decode('latin-1'), v) for k, v in dic.iteritems())
271 return dic
274 return dic
272
275
273 def byteskwargs(dic):
276 def byteskwargs(dic):
274 """
277 """
275 Converts keys of python dictonaries to bytes as they were converted to
278 Converts keys of python dictonaries to bytes as they were converted to
276 str to pass that dictonary as a keyword argument on Python 3.
279 str to pass that dictonary as a keyword argument on Python 3.
277 """
280 """
278 dic = dict((k.encode('latin-1'), v) for k, v in dic.iteritems())
281 dic = dict((k.encode('latin-1'), v) for k, v in dic.iteritems())
279 return dic
282 return dic
280
283
281 # TODO: handle shlex.shlex().
284 # TODO: handle shlex.shlex().
282 def shlexsplit(s, comments=False, posix=True):
285 def shlexsplit(s, comments=False, posix=True):
283 """
286 """
284 Takes bytes argument, convert it to str i.e. unicodes, pass that into
287 Takes bytes argument, convert it to str i.e. unicodes, pass that into
285 shlex.split(), convert the returned value to bytes and return that for
288 shlex.split(), convert the returned value to bytes and return that for
286 Python 3 compatibility as shelx.split() don't accept bytes on Python 3.
289 Python 3 compatibility as shelx.split() don't accept bytes on Python 3.
287 """
290 """
288 ret = shlex.split(s.decode('latin-1'), comments, posix)
291 ret = shlex.split(s.decode('latin-1'), comments, posix)
289 return [a.encode('latin-1') for a in ret]
292 return [a.encode('latin-1') for a in ret]
290
293
291 def emailparser(*args, **kwargs):
294 def emailparser(*args, **kwargs):
292 import email.parser
295 import email.parser
293 return email.parser.BytesParser(*args, **kwargs)
296 return email.parser.BytesParser(*args, **kwargs)
294
297
295 else:
298 else:
296 import cStringIO
299 import cStringIO
297
300
298 bytechr = chr
301 bytechr = chr
299 byterepr = repr
302 byterepr = repr
300 bytestr = str
303 bytestr = str
301 iterbytestr = iter
304 iterbytestr = iter
302 maybebytestr = identity
305 maybebytestr = identity
303 sysbytes = identity
306 sysbytes = identity
304 sysstr = identity
307 sysstr = identity
305 strurl = identity
308 strurl = identity
306 bytesurl = identity
309 bytesurl = identity
307
310
308 # this can't be parsed on Python 3
311 # this can't be parsed on Python 3
309 exec('def raisewithtb(exc, tb):\n'
312 exec('def raisewithtb(exc, tb):\n'
310 ' raise exc, None, tb\n')
313 ' raise exc, None, tb\n')
311
314
312 def fsencode(filename):
315 def fsencode(filename):
313 """
316 """
314 Partial backport from os.py in Python 3, which only accepts bytes.
317 Partial backport from os.py in Python 3, which only accepts bytes.
315 In Python 2, our paths should only ever be bytes, a unicode path
318 In Python 2, our paths should only ever be bytes, a unicode path
316 indicates a bug.
319 indicates a bug.
317 """
320 """
318 if isinstance(filename, str):
321 if isinstance(filename, str):
319 return filename
322 return filename
320 else:
323 else:
321 raise TypeError(
324 raise TypeError(
322 "expect str, not %s" % type(filename).__name__)
325 "expect str, not %s" % type(filename).__name__)
323
326
324 # In Python 2, fsdecode() has a very chance to receive bytes. So it's
327 # In Python 2, fsdecode() has a very chance to receive bytes. So it's
325 # better not to touch Python 2 part as it's already working fine.
328 # better not to touch Python 2 part as it's already working fine.
326 fsdecode = identity
329 fsdecode = identity
327
330
328 def getdoc(obj):
331 def getdoc(obj):
329 return getattr(obj, '__doc__', None)
332 return getattr(obj, '__doc__', None)
330
333
331 _notset = object()
334 _notset = object()
332
335
333 def safehasattr(thing, attr):
336 def safehasattr(thing, attr):
334 return getattr(thing, attr, _notset) is not _notset
337 return getattr(thing, attr, _notset) is not _notset
335
338
336 def _getoptbwrapper(orig, args, shortlist, namelist):
339 def _getoptbwrapper(orig, args, shortlist, namelist):
337 return orig(args, shortlist, namelist)
340 return orig(args, shortlist, namelist)
338
341
339 strkwargs = identity
342 strkwargs = identity
340 byteskwargs = identity
343 byteskwargs = identity
341
344
342 oscurdir = os.curdir
345 oscurdir = os.curdir
343 oslinesep = os.linesep
346 oslinesep = os.linesep
344 osname = os.name
347 osname = os.name
345 ospathsep = os.pathsep
348 ospathsep = os.pathsep
346 ospardir = os.pardir
349 ospardir = os.pardir
347 ossep = os.sep
350 ossep = os.sep
348 osaltsep = os.altsep
351 osaltsep = os.altsep
349 stdin = sys.stdin
352 stdin = sys.stdin
350 stdout = sys.stdout
353 stdout = sys.stdout
351 stderr = sys.stderr
354 stderr = sys.stderr
352 if getattr(sys, 'argv', None) is not None:
355 if getattr(sys, 'argv', None) is not None:
353 sysargv = sys.argv
356 sysargv = sys.argv
354 sysplatform = sys.platform
357 sysplatform = sys.platform
355 getcwd = os.getcwd
358 getcwd = os.getcwd
356 sysexecutable = sys.executable
359 sysexecutable = sys.executable
357 shlexsplit = shlex.split
360 shlexsplit = shlex.split
358 bytesio = cStringIO.StringIO
361 bytesio = cStringIO.StringIO
359 stringio = bytesio
362 stringio = bytesio
360 maplist = map
363 maplist = map
361 rangelist = range
364 rangelist = range
362 ziplist = zip
365 ziplist = zip
363 rawinput = raw_input
366 rawinput = raw_input
364 getargspec = inspect.getargspec
367 getargspec = inspect.getargspec
365
368
366 def emailparser(*args, **kwargs):
369 def emailparser(*args, **kwargs):
367 import email.parser
370 import email.parser
368 return email.parser.Parser(*args, **kwargs)
371 return email.parser.Parser(*args, **kwargs)
369
372
370 isjython = sysplatform.startswith('java')
373 isjython = sysplatform.startswith('java')
371
374
372 isdarwin = sysplatform == 'darwin'
375 isdarwin = sysplatform == 'darwin'
373 isposix = osname == 'posix'
376 isposix = osname == 'posix'
374 iswindows = osname == 'nt'
377 iswindows = osname == 'nt'
375
378
376 def getoptb(args, shortlist, namelist):
379 def getoptb(args, shortlist, namelist):
377 return _getoptbwrapper(getopt.getopt, args, shortlist, namelist)
380 return _getoptbwrapper(getopt.getopt, args, shortlist, namelist)
378
381
379 def gnugetoptb(args, shortlist, namelist):
382 def gnugetoptb(args, shortlist, namelist):
380 return _getoptbwrapper(getopt.gnu_getopt, args, shortlist, namelist)
383 return _getoptbwrapper(getopt.gnu_getopt, args, shortlist, namelist)
General Comments 0
You need to be logged in to leave comments. Login now