##// END OF EJS Templates
typing: add type hints to global variables in mercurial/pycompat.py...
Matt Harbison -
r50696:9cd32750 default
parent child Browse files
Show More
@@ -1,425 +1,426 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
11
12 import builtins
12 import builtins
13 import codecs
13 import codecs
14 import concurrent.futures as futures
14 import concurrent.futures as futures
15 import functools
15 import functools
16 import getopt
16 import getopt
17 import http.client as httplib
17 import http.client as httplib
18 import http.cookiejar as cookielib
18 import http.cookiejar as cookielib
19 import inspect
19 import inspect
20 import io
20 import io
21 import json
21 import json
22 import os
22 import os
23 import queue
23 import queue
24 import shlex
24 import shlex
25 import socketserver
25 import socketserver
26 import struct
26 import struct
27 import sys
27 import sys
28 import tempfile
28 import tempfile
29 import xmlrpc.client as xmlrpclib
29 import xmlrpc.client as xmlrpclib
30
30
31 from typing import (
32 List,
33 Optional,
34 )
31
35
32 ispy3 = sys.version_info[0] >= 3
36 ispy3 = sys.version_info[0] >= 3
33 ispypy = '__pypy__' in sys.builtin_module_names
37 ispypy = '__pypy__' in sys.builtin_module_names
34 TYPE_CHECKING = False
38 TYPE_CHECKING = False
35
39
36 if not globals(): # hide this from non-pytype users
40 if not globals(): # hide this from non-pytype users
37 import typing
41 import typing
38
42
39 TYPE_CHECKING = typing.TYPE_CHECKING
43 TYPE_CHECKING = typing.TYPE_CHECKING
40
44
41
45
42 def future_set_exception_info(f, exc_info):
46 def future_set_exception_info(f, exc_info):
43 f.set_exception(exc_info[0])
47 f.set_exception(exc_info[0])
44
48
45
49
46 FileNotFoundError = builtins.FileNotFoundError
50 FileNotFoundError = builtins.FileNotFoundError
47
51
48
52
49 def identity(a):
53 def identity(a):
50 return a
54 return a
51
55
52
56
53 def _rapply(f, xs):
57 def _rapply(f, xs):
54 if xs is None:
58 if xs is None:
55 # assume None means non-value of optional data
59 # assume None means non-value of optional data
56 return xs
60 return xs
57 if isinstance(xs, (list, set, tuple)):
61 if isinstance(xs, (list, set, tuple)):
58 return type(xs)(_rapply(f, x) for x in xs)
62 return type(xs)(_rapply(f, x) for x in xs)
59 if isinstance(xs, dict):
63 if isinstance(xs, dict):
60 return type(xs)((_rapply(f, k), _rapply(f, v)) for k, v in xs.items())
64 return type(xs)((_rapply(f, k), _rapply(f, v)) for k, v in xs.items())
61 return f(xs)
65 return f(xs)
62
66
63
67
64 def rapply(f, xs):
68 def rapply(f, xs):
65 """Apply function recursively to every item preserving the data structure
69 """Apply function recursively to every item preserving the data structure
66
70
67 >>> def f(x):
71 >>> def f(x):
68 ... return 'f(%s)' % x
72 ... return 'f(%s)' % x
69 >>> rapply(f, None) is None
73 >>> rapply(f, None) is None
70 True
74 True
71 >>> rapply(f, 'a')
75 >>> rapply(f, 'a')
72 'f(a)'
76 'f(a)'
73 >>> rapply(f, {'a'}) == {'f(a)'}
77 >>> rapply(f, {'a'}) == {'f(a)'}
74 True
78 True
75 >>> rapply(f, ['a', 'b', None, {'c': 'd'}, []])
79 >>> rapply(f, ['a', 'b', None, {'c': 'd'}, []])
76 ['f(a)', 'f(b)', None, {'f(c)': 'f(d)'}, []]
80 ['f(a)', 'f(b)', None, {'f(c)': 'f(d)'}, []]
77
81
78 >>> xs = [object()]
82 >>> xs = [object()]
79 >>> rapply(identity, xs) is xs
83 >>> rapply(identity, xs) is xs
80 True
84 True
81 """
85 """
82 if f is identity:
86 if f is identity:
83 # fast path mainly for py2
87 # fast path mainly for py2
84 return xs
88 return xs
85 return _rapply(f, xs)
89 return _rapply(f, xs)
86
90
87
91
88 if os.name == r'nt':
92 if os.name == r'nt':
89 # MBCS (or ANSI) filesystem encoding must be used as before.
93 # MBCS (or ANSI) filesystem encoding must be used as before.
90 # Otherwise non-ASCII filenames in existing repositories would be
94 # Otherwise non-ASCII filenames in existing repositories would be
91 # corrupted.
95 # corrupted.
92 # This must be set once prior to any fsencode/fsdecode calls.
96 # This must be set once prior to any fsencode/fsdecode calls.
93 sys._enablelegacywindowsfsencoding() # pytype: disable=module-attr
97 sys._enablelegacywindowsfsencoding() # pytype: disable=module-attr
94
98
95 fsencode = os.fsencode
99 fsencode = os.fsencode
96 fsdecode = os.fsdecode
100 fsdecode = os.fsdecode
97 oscurdir = os.curdir.encode('ascii')
101 oscurdir: bytes = os.curdir.encode('ascii')
98 oslinesep = os.linesep.encode('ascii')
102 oslinesep: bytes = os.linesep.encode('ascii')
99 osname = os.name.encode('ascii')
103 osname: bytes = os.name.encode('ascii')
100 ospathsep = os.pathsep.encode('ascii')
104 ospathsep: bytes = os.pathsep.encode('ascii')
101 ospardir = os.pardir.encode('ascii')
105 ospardir: bytes = os.pardir.encode('ascii')
102 ossep = os.sep.encode('ascii')
106 ossep: bytes = os.sep.encode('ascii')
103 osaltsep = os.altsep
107 osaltsep: Optional[bytes] = os.altsep.encode('ascii') if os.altsep else None
104 if osaltsep:
108 osdevnull: bytes = os.devnull.encode('ascii')
105 osaltsep = osaltsep.encode('ascii')
106 osdevnull = os.devnull.encode('ascii')
107
109
108 sysplatform = sys.platform.encode('ascii')
110 sysplatform: bytes = sys.platform.encode('ascii')
109 sysexecutable = sys.executable
111 sysexecutable: bytes = os.fsencode(sys.executable) if sys.executable else b''
110 if sysexecutable:
111 sysexecutable = os.fsencode(sysexecutable)
112
112
113
113
114 def maplist(*args):
114 def maplist(*args):
115 return list(map(*args))
115 return list(map(*args))
116
116
117
117
118 def rangelist(*args):
118 def rangelist(*args):
119 return list(range(*args))
119 return list(range(*args))
120
120
121
121
122 def ziplist(*args):
122 def ziplist(*args):
123 return list(zip(*args))
123 return list(zip(*args))
124
124
125
125
126 rawinput = input
126 rawinput = input
127 getargspec = inspect.getfullargspec
127 getargspec = inspect.getfullargspec
128
128
129 long = int
129 long = int
130
130
131 if getattr(sys, 'argv', None) is not None:
131 if getattr(sys, 'argv', None) is not None:
132 # On POSIX, the char** argv array is converted to Python str using
132 # On POSIX, the char** argv array is converted to Python str using
133 # Py_DecodeLocale(). The inverse of this is Py_EncodeLocale(), which
133 # Py_DecodeLocale(). The inverse of this is Py_EncodeLocale(), which
134 # isn't directly callable from Python code. In practice, os.fsencode()
134 # isn't directly callable from Python code. In practice, os.fsencode()
135 # can be used instead (this is recommended by Python's documentation
135 # can be used instead (this is recommended by Python's documentation
136 # for sys.argv).
136 # for sys.argv).
137 #
137 #
138 # On Windows, the wchar_t **argv is passed into the interpreter as-is.
138 # On Windows, the wchar_t **argv is passed into the interpreter as-is.
139 # Like POSIX, we need to emulate what Py_EncodeLocale() would do. But
139 # Like POSIX, we need to emulate what Py_EncodeLocale() would do. But
140 # there's an additional wrinkle. What we really want to access is the
140 # there's an additional wrinkle. What we really want to access is the
141 # ANSI codepage representation of the arguments, as this is what
141 # ANSI codepage representation of the arguments, as this is what
142 # `int main()` would receive if Python 3 didn't define `int wmain()`
142 # `int main()` would receive if Python 3 didn't define `int wmain()`
143 # (this is how Python 2 worked). To get that, we encode with the mbcs
143 # (this is how Python 2 worked). To get that, we encode with the mbcs
144 # encoding, which will pass CP_ACP to the underlying Windows API to
144 # encoding, which will pass CP_ACP to the underlying Windows API to
145 # produce bytes.
145 # produce bytes.
146 sysargv: List[bytes] = []
146 if os.name == r'nt':
147 if os.name == r'nt':
147 sysargv = [a.encode("mbcs", "ignore") for a in sys.argv]
148 sysargv = [a.encode("mbcs", "ignore") for a in sys.argv]
148 else:
149 else:
149 sysargv = [fsencode(a) for a in sys.argv]
150 sysargv = [fsencode(a) for a in sys.argv]
150
151
151 bytechr = struct.Struct('>B').pack
152 bytechr = struct.Struct('>B').pack
152 byterepr = b'%r'.__mod__
153 byterepr = b'%r'.__mod__
153
154
154
155
155 class bytestr(bytes):
156 class bytestr(bytes):
156 """A bytes which mostly acts as a Python 2 str
157 """A bytes which mostly acts as a Python 2 str
157
158
158 >>> bytestr(), bytestr(bytearray(b'foo')), bytestr(u'ascii'), bytestr(1)
159 >>> bytestr(), bytestr(bytearray(b'foo')), bytestr(u'ascii'), bytestr(1)
159 ('', 'foo', 'ascii', '1')
160 ('', 'foo', 'ascii', '1')
160 >>> s = bytestr(b'foo')
161 >>> s = bytestr(b'foo')
161 >>> assert s is bytestr(s)
162 >>> assert s is bytestr(s)
162
163
163 __bytes__() should be called if provided:
164 __bytes__() should be called if provided:
164
165
165 >>> class bytesable:
166 >>> class bytesable:
166 ... def __bytes__(self):
167 ... def __bytes__(self):
167 ... return b'bytes'
168 ... return b'bytes'
168 >>> bytestr(bytesable())
169 >>> bytestr(bytesable())
169 'bytes'
170 'bytes'
170
171
171 There's no implicit conversion from non-ascii str as its encoding is
172 There's no implicit conversion from non-ascii str as its encoding is
172 unknown:
173 unknown:
173
174
174 >>> bytestr(chr(0x80)) # doctest: +ELLIPSIS
175 >>> bytestr(chr(0x80)) # doctest: +ELLIPSIS
175 Traceback (most recent call last):
176 Traceback (most recent call last):
176 ...
177 ...
177 UnicodeEncodeError: ...
178 UnicodeEncodeError: ...
178
179
179 Comparison between bytestr and bytes should work:
180 Comparison between bytestr and bytes should work:
180
181
181 >>> assert bytestr(b'foo') == b'foo'
182 >>> assert bytestr(b'foo') == b'foo'
182 >>> assert b'foo' == bytestr(b'foo')
183 >>> assert b'foo' == bytestr(b'foo')
183 >>> assert b'f' in bytestr(b'foo')
184 >>> assert b'f' in bytestr(b'foo')
184 >>> assert bytestr(b'f') in b'foo'
185 >>> assert bytestr(b'f') in b'foo'
185
186
186 Sliced elements should be bytes, not integer:
187 Sliced elements should be bytes, not integer:
187
188
188 >>> s[1], s[:2]
189 >>> s[1], s[:2]
189 (b'o', b'fo')
190 (b'o', b'fo')
190 >>> list(s), list(reversed(s))
191 >>> list(s), list(reversed(s))
191 ([b'f', b'o', b'o'], [b'o', b'o', b'f'])
192 ([b'f', b'o', b'o'], [b'o', b'o', b'f'])
192
193
193 As bytestr type isn't propagated across operations, you need to cast
194 As bytestr type isn't propagated across operations, you need to cast
194 bytes to bytestr explicitly:
195 bytes to bytestr explicitly:
195
196
196 >>> s = bytestr(b'foo').upper()
197 >>> s = bytestr(b'foo').upper()
197 >>> t = bytestr(s)
198 >>> t = bytestr(s)
198 >>> s[0], t[0]
199 >>> s[0], t[0]
199 (70, b'F')
200 (70, b'F')
200
201
201 Be careful to not pass a bytestr object to a function which expects
202 Be careful to not pass a bytestr object to a function which expects
202 bytearray-like behavior.
203 bytearray-like behavior.
203
204
204 >>> t = bytes(t) # cast to bytes
205 >>> t = bytes(t) # cast to bytes
205 >>> assert type(t) is bytes
206 >>> assert type(t) is bytes
206 """
207 """
207
208
208 # Trick pytype into not demanding Iterable[int] be passed to __new__(),
209 # Trick pytype into not demanding Iterable[int] be passed to __new__(),
209 # since the appropriate bytes format is done internally.
210 # since the appropriate bytes format is done internally.
210 #
211 #
211 # https://github.com/google/pytype/issues/500
212 # https://github.com/google/pytype/issues/500
212 if TYPE_CHECKING:
213 if TYPE_CHECKING:
213
214
214 def __init__(self, s=b''):
215 def __init__(self, s=b''):
215 pass
216 pass
216
217
217 def __new__(cls, s=b''):
218 def __new__(cls, s=b''):
218 if isinstance(s, bytestr):
219 if isinstance(s, bytestr):
219 return s
220 return s
220 if not isinstance(
221 if not isinstance(
221 s, (bytes, bytearray)
222 s, (bytes, bytearray)
222 ) and not hasattr( # hasattr-py3-only
223 ) and not hasattr( # hasattr-py3-only
223 s, u'__bytes__'
224 s, u'__bytes__'
224 ):
225 ):
225 s = str(s).encode('ascii')
226 s = str(s).encode('ascii')
226 return bytes.__new__(cls, s)
227 return bytes.__new__(cls, s)
227
228
228 def __getitem__(self, key):
229 def __getitem__(self, key):
229 s = bytes.__getitem__(self, key)
230 s = bytes.__getitem__(self, key)
230 if not isinstance(s, bytes):
231 if not isinstance(s, bytes):
231 s = bytechr(s)
232 s = bytechr(s)
232 return s
233 return s
233
234
234 def __iter__(self):
235 def __iter__(self):
235 return iterbytestr(bytes.__iter__(self))
236 return iterbytestr(bytes.__iter__(self))
236
237
237 def __repr__(self):
238 def __repr__(self):
238 return bytes.__repr__(self)[1:] # drop b''
239 return bytes.__repr__(self)[1:] # drop b''
239
240
240
241
241 def iterbytestr(s):
242 def iterbytestr(s):
242 """Iterate bytes as if it were a str object of Python 2"""
243 """Iterate bytes as if it were a str object of Python 2"""
243 return map(bytechr, s)
244 return map(bytechr, s)
244
245
245
246
246 def maybebytestr(s):
247 def maybebytestr(s):
247 """Promote bytes to bytestr"""
248 """Promote bytes to bytestr"""
248 if isinstance(s, bytes):
249 if isinstance(s, bytes):
249 return bytestr(s)
250 return bytestr(s)
250 return s
251 return s
251
252
252
253
253 def sysbytes(s):
254 def sysbytes(s):
254 """Convert an internal str (e.g. keyword, __doc__) back to bytes
255 """Convert an internal str (e.g. keyword, __doc__) back to bytes
255
256
256 This never raises UnicodeEncodeError, but only ASCII characters
257 This never raises UnicodeEncodeError, but only ASCII characters
257 can be round-trip by sysstr(sysbytes(s)).
258 can be round-trip by sysstr(sysbytes(s)).
258 """
259 """
259 if isinstance(s, bytes):
260 if isinstance(s, bytes):
260 return s
261 return s
261 return s.encode('utf-8')
262 return s.encode('utf-8')
262
263
263
264
264 def sysstr(s):
265 def sysstr(s):
265 """Return a keyword str to be passed to Python functions such as
266 """Return a keyword str to be passed to Python functions such as
266 getattr() and str.encode()
267 getattr() and str.encode()
267
268
268 This never raises UnicodeDecodeError. Non-ascii characters are
269 This never raises UnicodeDecodeError. Non-ascii characters are
269 considered invalid and mapped to arbitrary but unique code points
270 considered invalid and mapped to arbitrary but unique code points
270 such that 'sysstr(a) != sysstr(b)' for all 'a != b'.
271 such that 'sysstr(a) != sysstr(b)' for all 'a != b'.
271 """
272 """
272 if isinstance(s, builtins.str):
273 if isinstance(s, builtins.str):
273 return s
274 return s
274 return s.decode('latin-1')
275 return s.decode('latin-1')
275
276
276
277
277 def strurl(url):
278 def strurl(url):
278 """Converts a bytes url back to str"""
279 """Converts a bytes url back to str"""
279 if isinstance(url, bytes):
280 if isinstance(url, bytes):
280 return url.decode('ascii')
281 return url.decode('ascii')
281 return url
282 return url
282
283
283
284
284 def bytesurl(url):
285 def bytesurl(url):
285 """Converts a str url to bytes by encoding in ascii"""
286 """Converts a str url to bytes by encoding in ascii"""
286 if isinstance(url, str):
287 if isinstance(url, str):
287 return url.encode('ascii')
288 return url.encode('ascii')
288 return url
289 return url
289
290
290
291
291 def raisewithtb(exc, tb):
292 def raisewithtb(exc, tb):
292 """Raise exception with the given traceback"""
293 """Raise exception with the given traceback"""
293 raise exc.with_traceback(tb)
294 raise exc.with_traceback(tb)
294
295
295
296
296 def getdoc(obj):
297 def getdoc(obj):
297 """Get docstring as bytes; may be None so gettext() won't confuse it
298 """Get docstring as bytes; may be None so gettext() won't confuse it
298 with _('')"""
299 with _('')"""
299 doc = getattr(obj, '__doc__', None)
300 doc = getattr(obj, '__doc__', None)
300 if doc is None:
301 if doc is None:
301 return doc
302 return doc
302 return sysbytes(doc)
303 return sysbytes(doc)
303
304
304
305
305 def _wrapattrfunc(f):
306 def _wrapattrfunc(f):
306 @functools.wraps(f)
307 @functools.wraps(f)
307 def w(object, name, *args):
308 def w(object, name, *args):
308 return f(object, sysstr(name), *args)
309 return f(object, sysstr(name), *args)
309
310
310 return w
311 return w
311
312
312
313
313 # these wrappers are automagically imported by hgloader
314 # these wrappers are automagically imported by hgloader
314 delattr = _wrapattrfunc(builtins.delattr)
315 delattr = _wrapattrfunc(builtins.delattr)
315 getattr = _wrapattrfunc(builtins.getattr)
316 getattr = _wrapattrfunc(builtins.getattr)
316 hasattr = _wrapattrfunc(builtins.hasattr)
317 hasattr = _wrapattrfunc(builtins.hasattr)
317 setattr = _wrapattrfunc(builtins.setattr)
318 setattr = _wrapattrfunc(builtins.setattr)
318 xrange = builtins.range
319 xrange = builtins.range
319 unicode = str
320 unicode = str
320
321
321
322
322 def open(name, mode=b'r', buffering=-1, encoding=None):
323 def open(name, mode=b'r', buffering=-1, encoding=None):
323 return builtins.open(name, sysstr(mode), buffering, encoding)
324 return builtins.open(name, sysstr(mode), buffering, encoding)
324
325
325
326
326 safehasattr = _wrapattrfunc(builtins.hasattr)
327 safehasattr = _wrapattrfunc(builtins.hasattr)
327
328
328
329
329 def _getoptbwrapper(orig, args, shortlist, namelist):
330 def _getoptbwrapper(orig, args, shortlist, namelist):
330 """
331 """
331 Takes bytes arguments, converts them to unicode, pass them to
332 Takes bytes arguments, converts them to unicode, pass them to
332 getopt.getopt(), convert the returned values back to bytes and then
333 getopt.getopt(), convert the returned values back to bytes and then
333 return them for Python 3 compatibility as getopt.getopt() don't accepts
334 return them for Python 3 compatibility as getopt.getopt() don't accepts
334 bytes on Python 3.
335 bytes on Python 3.
335 """
336 """
336 args = [a.decode('latin-1') for a in args]
337 args = [a.decode('latin-1') for a in args]
337 shortlist = shortlist.decode('latin-1')
338 shortlist = shortlist.decode('latin-1')
338 namelist = [a.decode('latin-1') for a in namelist]
339 namelist = [a.decode('latin-1') for a in namelist]
339 opts, args = orig(args, shortlist, namelist)
340 opts, args = orig(args, shortlist, namelist)
340 opts = [(a[0].encode('latin-1'), a[1].encode('latin-1')) for a in opts]
341 opts = [(a[0].encode('latin-1'), a[1].encode('latin-1')) for a in opts]
341 args = [a.encode('latin-1') for a in args]
342 args = [a.encode('latin-1') for a in args]
342 return opts, args
343 return opts, args
343
344
344
345
345 def strkwargs(dic):
346 def strkwargs(dic):
346 """
347 """
347 Converts the keys of a python dictonary to str i.e. unicodes so that
348 Converts the keys of a python dictonary to str i.e. unicodes so that
348 they can be passed as keyword arguments as dictionaries with bytes keys
349 they can be passed as keyword arguments as dictionaries with bytes keys
349 can't be passed as keyword arguments to functions on Python 3.
350 can't be passed as keyword arguments to functions on Python 3.
350 """
351 """
351 dic = {k.decode('latin-1'): v for k, v in dic.items()}
352 dic = {k.decode('latin-1'): v for k, v in dic.items()}
352 return dic
353 return dic
353
354
354
355
355 def byteskwargs(dic):
356 def byteskwargs(dic):
356 """
357 """
357 Converts keys of python dictionaries to bytes as they were converted to
358 Converts keys of python dictionaries to bytes as they were converted to
358 str to pass that dictonary as a keyword argument on Python 3.
359 str to pass that dictonary as a keyword argument on Python 3.
359 """
360 """
360 dic = {k.encode('latin-1'): v for k, v in dic.items()}
361 dic = {k.encode('latin-1'): v for k, v in dic.items()}
361 return dic
362 return dic
362
363
363
364
364 # TODO: handle shlex.shlex().
365 # TODO: handle shlex.shlex().
365 def shlexsplit(s, comments=False, posix=True):
366 def shlexsplit(s, comments=False, posix=True):
366 """
367 """
367 Takes bytes argument, convert it to str i.e. unicodes, pass that into
368 Takes bytes argument, convert it to str i.e. unicodes, pass that into
368 shlex.split(), convert the returned value to bytes and return that for
369 shlex.split(), convert the returned value to bytes and return that for
369 Python 3 compatibility as shelx.split() don't accept bytes on Python 3.
370 Python 3 compatibility as shelx.split() don't accept bytes on Python 3.
370 """
371 """
371 ret = shlex.split(s.decode('latin-1'), comments, posix)
372 ret = shlex.split(s.decode('latin-1'), comments, posix)
372 return [a.encode('latin-1') for a in ret]
373 return [a.encode('latin-1') for a in ret]
373
374
374
375
375 iteritems = lambda x: x.items()
376 iteritems = lambda x: x.items()
376 itervalues = lambda x: x.values()
377 itervalues = lambda x: x.values()
377
378
378 json_loads = json.loads
379 json_loads = json.loads
379
380
380 isjython = sysplatform.startswith(b'java')
381 isjython: bool = sysplatform.startswith(b'java')
381
382
382 isdarwin = sysplatform.startswith(b'darwin')
383 isdarwin: bool = sysplatform.startswith(b'darwin')
383 islinux = sysplatform.startswith(b'linux')
384 islinux: bool = sysplatform.startswith(b'linux')
384 isposix = osname == b'posix'
385 isposix: bool = osname == b'posix'
385 iswindows = osname == b'nt'
386 iswindows: bool = osname == b'nt'
386
387
387
388
388 def getoptb(args, shortlist, namelist):
389 def getoptb(args, shortlist, namelist):
389 return _getoptbwrapper(getopt.getopt, args, shortlist, namelist)
390 return _getoptbwrapper(getopt.getopt, args, shortlist, namelist)
390
391
391
392
392 def gnugetoptb(args, shortlist, namelist):
393 def gnugetoptb(args, shortlist, namelist):
393 return _getoptbwrapper(getopt.gnu_getopt, args, shortlist, namelist)
394 return _getoptbwrapper(getopt.gnu_getopt, args, shortlist, namelist)
394
395
395
396
396 def mkdtemp(suffix=b'', prefix=b'tmp', dir=None):
397 def mkdtemp(suffix=b'', prefix=b'tmp', dir=None):
397 return tempfile.mkdtemp(suffix, prefix, dir)
398 return tempfile.mkdtemp(suffix, prefix, dir)
398
399
399
400
400 # text=True is not supported; use util.from/tonativeeol() instead
401 # text=True is not supported; use util.from/tonativeeol() instead
401 def mkstemp(suffix=b'', prefix=b'tmp', dir=None):
402 def mkstemp(suffix=b'', prefix=b'tmp', dir=None):
402 return tempfile.mkstemp(suffix, prefix, dir)
403 return tempfile.mkstemp(suffix, prefix, dir)
403
404
404
405
405 # TemporaryFile does not support an "encoding=" argument on python2.
406 # TemporaryFile does not support an "encoding=" argument on python2.
406 # This wrapper file are always open in byte mode.
407 # This wrapper file are always open in byte mode.
407 def unnamedtempfile(mode=None, *args, **kwargs):
408 def unnamedtempfile(mode=None, *args, **kwargs):
408 if mode is None:
409 if mode is None:
409 mode = 'w+b'
410 mode = 'w+b'
410 else:
411 else:
411 mode = sysstr(mode)
412 mode = sysstr(mode)
412 assert 'b' in mode
413 assert 'b' in mode
413 return tempfile.TemporaryFile(mode, *args, **kwargs)
414 return tempfile.TemporaryFile(mode, *args, **kwargs)
414
415
415
416
416 # NamedTemporaryFile does not support an "encoding=" argument on python2.
417 # NamedTemporaryFile does not support an "encoding=" argument on python2.
417 # This wrapper file are always open in byte mode.
418 # This wrapper file are always open in byte mode.
418 def namedtempfile(
419 def namedtempfile(
419 mode=b'w+b', bufsize=-1, suffix=b'', prefix=b'tmp', dir=None, delete=True
420 mode=b'w+b', bufsize=-1, suffix=b'', prefix=b'tmp', dir=None, delete=True
420 ):
421 ):
421 mode = sysstr(mode)
422 mode = sysstr(mode)
422 assert 'b' in mode
423 assert 'b' in mode
423 return tempfile.NamedTemporaryFile(
424 return tempfile.NamedTemporaryFile(
424 mode, bufsize, suffix=suffix, prefix=prefix, dir=dir, delete=delete
425 mode, bufsize, suffix=suffix, prefix=prefix, dir=dir, delete=delete
425 )
426 )
General Comments 0
You need to be logged in to leave comments. Login now