##// END OF EJS Templates
pycompat: move multiline comments above a function to function doc...
Pulkit Goyal -
r32864:f57f1f37 default
parent child Browse files
Show More
@@ -1,450 +1,460 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 os
14 import os
15 import shlex
15 import shlex
16 import sys
16 import sys
17
17
18 ispy3 = (sys.version_info[0] >= 3)
18 ispy3 = (sys.version_info[0] >= 3)
19
19
20 if not ispy3:
20 if not ispy3:
21 import cookielib
21 import cookielib
22 import cPickle as pickle
22 import cPickle as pickle
23 import httplib
23 import httplib
24 import Queue as _queue
24 import Queue as _queue
25 import SocketServer as socketserver
25 import SocketServer as socketserver
26 import xmlrpclib
26 import xmlrpclib
27 else:
27 else:
28 import http.cookiejar as cookielib
28 import http.cookiejar as cookielib
29 import http.client as httplib
29 import http.client as httplib
30 import pickle
30 import pickle
31 import queue as _queue
31 import queue as _queue
32 import socketserver
32 import socketserver
33 import xmlrpc.client as xmlrpclib
33 import xmlrpc.client as xmlrpclib
34
34
35 def identity(a):
35 def identity(a):
36 return a
36 return a
37
37
38 if ispy3:
38 if ispy3:
39 import builtins
39 import builtins
40 import functools
40 import functools
41 import io
41 import io
42 import struct
42 import struct
43
43
44 fsencode = os.fsencode
44 fsencode = os.fsencode
45 fsdecode = os.fsdecode
45 fsdecode = os.fsdecode
46 # A bytes version of os.name.
47 oslinesep = os.linesep.encode('ascii')
46 oslinesep = os.linesep.encode('ascii')
48 osname = os.name.encode('ascii')
47 osname = os.name.encode('ascii')
49 ospathsep = os.pathsep.encode('ascii')
48 ospathsep = os.pathsep.encode('ascii')
50 ossep = os.sep.encode('ascii')
49 ossep = os.sep.encode('ascii')
51 osaltsep = os.altsep
50 osaltsep = os.altsep
52 if osaltsep:
51 if osaltsep:
53 osaltsep = osaltsep.encode('ascii')
52 osaltsep = osaltsep.encode('ascii')
54 # os.getcwd() on Python 3 returns string, but it has os.getcwdb() which
53 # os.getcwd() on Python 3 returns string, but it has os.getcwdb() which
55 # returns bytes.
54 # returns bytes.
56 getcwd = os.getcwdb
55 getcwd = os.getcwdb
57 sysplatform = sys.platform.encode('ascii')
56 sysplatform = sys.platform.encode('ascii')
58 sysexecutable = sys.executable
57 sysexecutable = sys.executable
59 if sysexecutable:
58 if sysexecutable:
60 sysexecutable = os.fsencode(sysexecutable)
59 sysexecutable = os.fsencode(sysexecutable)
61 stringio = io.BytesIO
60 stringio = io.BytesIO
62 maplist = lambda *args: list(map(*args))
61 maplist = lambda *args: list(map(*args))
63
62
64 # TODO: .buffer might not exist if std streams were replaced; we'll need
63 # TODO: .buffer might not exist if std streams were replaced; we'll need
65 # a silly wrapper to make a bytes stream backed by a unicode one.
64 # a silly wrapper to make a bytes stream backed by a unicode one.
66 stdin = sys.stdin.buffer
65 stdin = sys.stdin.buffer
67 stdout = sys.stdout.buffer
66 stdout = sys.stdout.buffer
68 stderr = sys.stderr.buffer
67 stderr = sys.stderr.buffer
69
68
70 # Since Python 3 converts argv to wchar_t type by Py_DecodeLocale() on Unix,
69 # Since Python 3 converts argv to wchar_t type by Py_DecodeLocale() on Unix,
71 # we can use os.fsencode() to get back bytes argv.
70 # we can use os.fsencode() to get back bytes argv.
72 #
71 #
73 # https://hg.python.org/cpython/file/v3.5.1/Programs/python.c#l55
72 # https://hg.python.org/cpython/file/v3.5.1/Programs/python.c#l55
74 #
73 #
75 # TODO: On Windows, the native argv is wchar_t, so we'll need a different
74 # TODO: On Windows, the native argv is wchar_t, so we'll need a different
76 # workaround to simulate the Python 2 (i.e. ANSI Win32 API) behavior.
75 # workaround to simulate the Python 2 (i.e. ANSI Win32 API) behavior.
77 if getattr(sys, 'argv', None) is not None:
76 if getattr(sys, 'argv', None) is not None:
78 sysargv = list(map(os.fsencode, sys.argv))
77 sysargv = list(map(os.fsencode, sys.argv))
79
78
80 bytechr = struct.Struct('>B').pack
79 bytechr = struct.Struct('>B').pack
81
80
82 class bytestr(bytes):
81 class bytestr(bytes):
83 """A bytes which mostly acts as a Python 2 str
82 """A bytes which mostly acts as a Python 2 str
84
83
85 >>> bytestr(), bytestr(bytearray(b'foo')), bytestr(u'ascii'), bytestr(1)
84 >>> bytestr(), bytestr(bytearray(b'foo')), bytestr(u'ascii'), bytestr(1)
86 (b'', b'foo', b'ascii', b'1')
85 (b'', b'foo', b'ascii', b'1')
87 >>> s = bytestr(b'foo')
86 >>> s = bytestr(b'foo')
88 >>> assert s is bytestr(s)
87 >>> assert s is bytestr(s)
89
88
90 __bytes__() should be called if provided:
89 __bytes__() should be called if provided:
91
90
92 >>> class bytesable(object):
91 >>> class bytesable(object):
93 ... def __bytes__(self):
92 ... def __bytes__(self):
94 ... return b'bytes'
93 ... return b'bytes'
95 >>> bytestr(bytesable())
94 >>> bytestr(bytesable())
96 b'bytes'
95 b'bytes'
97
96
98 There's no implicit conversion from non-ascii str as its encoding is
97 There's no implicit conversion from non-ascii str as its encoding is
99 unknown:
98 unknown:
100
99
101 >>> bytestr(chr(0x80)) # doctest: +ELLIPSIS
100 >>> bytestr(chr(0x80)) # doctest: +ELLIPSIS
102 Traceback (most recent call last):
101 Traceback (most recent call last):
103 ...
102 ...
104 UnicodeEncodeError: ...
103 UnicodeEncodeError: ...
105
104
106 Comparison between bytestr and bytes should work:
105 Comparison between bytestr and bytes should work:
107
106
108 >>> assert bytestr(b'foo') == b'foo'
107 >>> assert bytestr(b'foo') == b'foo'
109 >>> assert b'foo' == bytestr(b'foo')
108 >>> assert b'foo' == bytestr(b'foo')
110 >>> assert b'f' in bytestr(b'foo')
109 >>> assert b'f' in bytestr(b'foo')
111 >>> assert bytestr(b'f') in b'foo'
110 >>> assert bytestr(b'f') in b'foo'
112
111
113 Sliced elements should be bytes, not integer:
112 Sliced elements should be bytes, not integer:
114
113
115 >>> s[1], s[:2]
114 >>> s[1], s[:2]
116 (b'o', b'fo')
115 (b'o', b'fo')
117 >>> list(s), list(reversed(s))
116 >>> list(s), list(reversed(s))
118 ([b'f', b'o', b'o'], [b'o', b'o', b'f'])
117 ([b'f', b'o', b'o'], [b'o', b'o', b'f'])
119
118
120 As bytestr type isn't propagated across operations, you need to cast
119 As bytestr type isn't propagated across operations, you need to cast
121 bytes to bytestr explicitly:
120 bytes to bytestr explicitly:
122
121
123 >>> s = bytestr(b'foo').upper()
122 >>> s = bytestr(b'foo').upper()
124 >>> t = bytestr(s)
123 >>> t = bytestr(s)
125 >>> s[0], t[0]
124 >>> s[0], t[0]
126 (70, b'F')
125 (70, b'F')
127
126
128 Be careful to not pass a bytestr object to a function which expects
127 Be careful to not pass a bytestr object to a function which expects
129 bytearray-like behavior.
128 bytearray-like behavior.
130
129
131 >>> t = bytes(t) # cast to bytes
130 >>> t = bytes(t) # cast to bytes
132 >>> assert type(t) is bytes
131 >>> assert type(t) is bytes
133 """
132 """
134
133
135 def __new__(cls, s=b''):
134 def __new__(cls, s=b''):
136 if isinstance(s, bytestr):
135 if isinstance(s, bytestr):
137 return s
136 return s
138 if (not isinstance(s, (bytes, bytearray))
137 if (not isinstance(s, (bytes, bytearray))
139 and not hasattr(s, u'__bytes__')): # hasattr-py3-only
138 and not hasattr(s, u'__bytes__')): # hasattr-py3-only
140 s = str(s).encode(u'ascii')
139 s = str(s).encode(u'ascii')
141 return bytes.__new__(cls, s)
140 return bytes.__new__(cls, s)
142
141
143 def __getitem__(self, key):
142 def __getitem__(self, key):
144 s = bytes.__getitem__(self, key)
143 s = bytes.__getitem__(self, key)
145 if not isinstance(s, bytes):
144 if not isinstance(s, bytes):
146 s = bytechr(s)
145 s = bytechr(s)
147 return s
146 return s
148
147
149 def __iter__(self):
148 def __iter__(self):
150 return iterbytestr(bytes.__iter__(self))
149 return iterbytestr(bytes.__iter__(self))
151
150
152 def iterbytestr(s):
151 def iterbytestr(s):
153 """Iterate bytes as if it were a str object of Python 2"""
152 """Iterate bytes as if it were a str object of Python 2"""
154 return map(bytechr, s)
153 return map(bytechr, s)
155
154
156 def sysbytes(s):
155 def sysbytes(s):
157 """Convert an internal str (e.g. keyword, __doc__) back to bytes
156 """Convert an internal str (e.g. keyword, __doc__) back to bytes
158
157
159 This never raises UnicodeEncodeError, but only ASCII characters
158 This never raises UnicodeEncodeError, but only ASCII characters
160 can be round-trip by sysstr(sysbytes(s)).
159 can be round-trip by sysstr(sysbytes(s)).
161 """
160 """
162 return s.encode(u'utf-8')
161 return s.encode(u'utf-8')
163
162
164 def sysstr(s):
163 def sysstr(s):
165 """Return a keyword str to be passed to Python functions such as
164 """Return a keyword str to be passed to Python functions such as
166 getattr() and str.encode()
165 getattr() and str.encode()
167
166
168 This never raises UnicodeDecodeError. Non-ascii characters are
167 This never raises UnicodeDecodeError. Non-ascii characters are
169 considered invalid and mapped to arbitrary but unique code points
168 considered invalid and mapped to arbitrary but unique code points
170 such that 'sysstr(a) != sysstr(b)' for all 'a != b'.
169 such that 'sysstr(a) != sysstr(b)' for all 'a != b'.
171 """
170 """
172 if isinstance(s, builtins.str):
171 if isinstance(s, builtins.str):
173 return s
172 return s
174 return s.decode(u'latin-1')
173 return s.decode(u'latin-1')
175
174
176 def strurl(url):
175 def strurl(url):
177 """Converts a bytes url back to str"""
176 """Converts a bytes url back to str"""
178 return url.decode(u'ascii')
177 return url.decode(u'ascii')
179
178
180 def bytesurl(url):
179 def bytesurl(url):
181 """Converts a str url to bytes by encoding in ascii"""
180 """Converts a str url to bytes by encoding in ascii"""
182 return url.encode(u'ascii')
181 return url.encode(u'ascii')
183
182
184 def raisewithtb(exc, tb):
183 def raisewithtb(exc, tb):
185 """Raise exception with the given traceback"""
184 """Raise exception with the given traceback"""
186 raise exc.with_traceback(tb)
185 raise exc.with_traceback(tb)
187
186
188 def getdoc(obj):
187 def getdoc(obj):
189 """Get docstring as bytes; may be None so gettext() won't confuse it
188 """Get docstring as bytes; may be None so gettext() won't confuse it
190 with _('')"""
189 with _('')"""
191 doc = getattr(obj, u'__doc__', None)
190 doc = getattr(obj, u'__doc__', None)
192 if doc is None:
191 if doc is None:
193 return doc
192 return doc
194 return sysbytes(doc)
193 return sysbytes(doc)
195
194
196 def _wrapattrfunc(f):
195 def _wrapattrfunc(f):
197 @functools.wraps(f)
196 @functools.wraps(f)
198 def w(object, name, *args):
197 def w(object, name, *args):
199 return f(object, sysstr(name), *args)
198 return f(object, sysstr(name), *args)
200 return w
199 return w
201
200
202 # these wrappers are automagically imported by hgloader
201 # these wrappers are automagically imported by hgloader
203 delattr = _wrapattrfunc(builtins.delattr)
202 delattr = _wrapattrfunc(builtins.delattr)
204 getattr = _wrapattrfunc(builtins.getattr)
203 getattr = _wrapattrfunc(builtins.getattr)
205 hasattr = _wrapattrfunc(builtins.hasattr)
204 hasattr = _wrapattrfunc(builtins.hasattr)
206 setattr = _wrapattrfunc(builtins.setattr)
205 setattr = _wrapattrfunc(builtins.setattr)
207 xrange = builtins.range
206 xrange = builtins.range
208 unicode = str
207 unicode = str
209
208
210 def open(name, mode='r', buffering=-1):
209 def open(name, mode='r', buffering=-1):
211 return builtins.open(name, sysstr(mode), buffering)
210 return builtins.open(name, sysstr(mode), buffering)
212
211
213 # getopt.getopt() on Python 3 deals with unicodes internally so we cannot
214 # pass bytes there. Passing unicodes will result in unicodes as return
215 # values which we need to convert again to bytes.
216 def getoptb(args, shortlist, namelist):
212 def getoptb(args, shortlist, namelist):
213 """
214 Takes bytes arguments, converts them to unicode, pass them to
215 getopt.getopt(), convert the returned values back to bytes and then
216 return them for Python 3 compatibility as getopt.getopt() don't accepts
217 bytes on Python 3.
218 """
217 args = [a.decode('latin-1') for a in args]
219 args = [a.decode('latin-1') for a in args]
218 shortlist = shortlist.decode('latin-1')
220 shortlist = shortlist.decode('latin-1')
219 namelist = [a.decode('latin-1') for a in namelist]
221 namelist = [a.decode('latin-1') for a in namelist]
220 opts, args = getopt.getopt(args, shortlist, namelist)
222 opts, args = getopt.getopt(args, shortlist, namelist)
221 opts = [(a[0].encode('latin-1'), a[1].encode('latin-1'))
223 opts = [(a[0].encode('latin-1'), a[1].encode('latin-1'))
222 for a in opts]
224 for a in opts]
223 args = [a.encode('latin-1') for a in args]
225 args = [a.encode('latin-1') for a in args]
224 return opts, args
226 return opts, args
225
227
226 # keys of keyword arguments in Python need to be strings which are unicodes
227 # Python 3. This function takes keyword arguments, convert the keys to str.
228 def strkwargs(dic):
228 def strkwargs(dic):
229 """
230 Converts the keys of a python dictonary to str i.e. unicodes so that
231 they can be passed as keyword arguments as dictonaries with bytes keys
232 can't be passed as keyword arguments to functions on Python 3.
233 """
229 dic = dict((k.decode('latin-1'), v) for k, v in dic.iteritems())
234 dic = dict((k.decode('latin-1'), v) for k, v in dic.iteritems())
230 return dic
235 return dic
231
236
232 # keys of keyword arguments need to be unicode while passing into
233 # a function. This function helps us to convert those keys back to bytes
234 # again as we need to deal with bytes.
235 def byteskwargs(dic):
237 def byteskwargs(dic):
238 """
239 Converts keys of python dictonaries to bytes as they were converted to
240 str to pass that dictonary as a keyword argument on Python 3.
241 """
236 dic = dict((k.encode('latin-1'), v) for k, v in dic.iteritems())
242 dic = dict((k.encode('latin-1'), v) for k, v in dic.iteritems())
237 return dic
243 return dic
238
244
239 # shlex.split() accepts unicodes on Python 3. This function takes bytes
240 # argument, convert it into unicodes, pass into shlex.split(), convert the
241 # returned value to bytes and return that.
242 # TODO: handle shlex.shlex().
245 # TODO: handle shlex.shlex().
243 def shlexsplit(s):
246 def shlexsplit(s):
247 """
248 Takes bytes argument, convert it to str i.e. unicodes, pass that into
249 shlex.split(), convert the returned value to bytes and return that for
250 Python 3 compatibility as shelx.split() don't accept bytes on Python 3.
251 """
244 ret = shlex.split(s.decode('latin-1'))
252 ret = shlex.split(s.decode('latin-1'))
245 return [a.encode('latin-1') for a in ret]
253 return [a.encode('latin-1') for a in ret]
246
254
247 else:
255 else:
248 import cStringIO
256 import cStringIO
249
257
250 bytechr = chr
258 bytechr = chr
251 bytestr = str
259 bytestr = str
252 iterbytestr = iter
260 iterbytestr = iter
253 sysbytes = identity
261 sysbytes = identity
254 sysstr = identity
262 sysstr = identity
255 strurl = identity
263 strurl = identity
256 bytesurl = identity
264 bytesurl = identity
257
265
258 # this can't be parsed on Python 3
266 # this can't be parsed on Python 3
259 exec('def raisewithtb(exc, tb):\n'
267 exec('def raisewithtb(exc, tb):\n'
260 ' raise exc, None, tb\n')
268 ' raise exc, None, tb\n')
261
269
262 # Partial backport from os.py in Python 3, which only accepts bytes.
263 # In Python 2, our paths should only ever be bytes, a unicode path
264 # indicates a bug.
265 def fsencode(filename):
270 def fsencode(filename):
271 """
272 Partial backport from os.py in Python 3, which only accepts bytes.
273 In Python 2, our paths should only ever be bytes, a unicode path
274 indicates a bug.
275 """
266 if isinstance(filename, str):
276 if isinstance(filename, str):
267 return filename
277 return filename
268 else:
278 else:
269 raise TypeError(
279 raise TypeError(
270 "expect str, not %s" % type(filename).__name__)
280 "expect str, not %s" % type(filename).__name__)
271
281
272 # In Python 2, fsdecode() has a very chance to receive bytes. So it's
282 # In Python 2, fsdecode() has a very chance to receive bytes. So it's
273 # better not to touch Python 2 part as it's already working fine.
283 # better not to touch Python 2 part as it's already working fine.
274 fsdecode = identity
284 fsdecode = identity
275
285
276 def getdoc(obj):
286 def getdoc(obj):
277 return getattr(obj, '__doc__', None)
287 return getattr(obj, '__doc__', None)
278
288
279 def getoptb(args, shortlist, namelist):
289 def getoptb(args, shortlist, namelist):
280 return getopt.getopt(args, shortlist, namelist)
290 return getopt.getopt(args, shortlist, namelist)
281
291
282 strkwargs = identity
292 strkwargs = identity
283 byteskwargs = identity
293 byteskwargs = identity
284
294
285 oslinesep = os.linesep
295 oslinesep = os.linesep
286 osname = os.name
296 osname = os.name
287 ospathsep = os.pathsep
297 ospathsep = os.pathsep
288 ossep = os.sep
298 ossep = os.sep
289 osaltsep = os.altsep
299 osaltsep = os.altsep
290 stdin = sys.stdin
300 stdin = sys.stdin
291 stdout = sys.stdout
301 stdout = sys.stdout
292 stderr = sys.stderr
302 stderr = sys.stderr
293 if getattr(sys, 'argv', None) is not None:
303 if getattr(sys, 'argv', None) is not None:
294 sysargv = sys.argv
304 sysargv = sys.argv
295 sysplatform = sys.platform
305 sysplatform = sys.platform
296 getcwd = os.getcwd
306 getcwd = os.getcwd
297 sysexecutable = sys.executable
307 sysexecutable = sys.executable
298 shlexsplit = shlex.split
308 shlexsplit = shlex.split
299 stringio = cStringIO.StringIO
309 stringio = cStringIO.StringIO
300 maplist = map
310 maplist = map
301
311
302 empty = _queue.Empty
312 empty = _queue.Empty
303 queue = _queue.Queue
313 queue = _queue.Queue
304
314
305 class _pycompatstub(object):
315 class _pycompatstub(object):
306 def __init__(self):
316 def __init__(self):
307 self._aliases = {}
317 self._aliases = {}
308
318
309 def _registeraliases(self, origin, items):
319 def _registeraliases(self, origin, items):
310 """Add items that will be populated at the first access"""
320 """Add items that will be populated at the first access"""
311 items = map(sysstr, items)
321 items = map(sysstr, items)
312 self._aliases.update(
322 self._aliases.update(
313 (item.replace(sysstr('_'), sysstr('')).lower(), (origin, item))
323 (item.replace(sysstr('_'), sysstr('')).lower(), (origin, item))
314 for item in items)
324 for item in items)
315
325
316 def _registeralias(self, origin, attr, name):
326 def _registeralias(self, origin, attr, name):
317 """Alias ``origin``.``attr`` as ``name``"""
327 """Alias ``origin``.``attr`` as ``name``"""
318 self._aliases[sysstr(name)] = (origin, sysstr(attr))
328 self._aliases[sysstr(name)] = (origin, sysstr(attr))
319
329
320 def __getattr__(self, name):
330 def __getattr__(self, name):
321 try:
331 try:
322 origin, item = self._aliases[name]
332 origin, item = self._aliases[name]
323 except KeyError:
333 except KeyError:
324 raise AttributeError(name)
334 raise AttributeError(name)
325 self.__dict__[name] = obj = getattr(origin, item)
335 self.__dict__[name] = obj = getattr(origin, item)
326 return obj
336 return obj
327
337
328 httpserver = _pycompatstub()
338 httpserver = _pycompatstub()
329 urlreq = _pycompatstub()
339 urlreq = _pycompatstub()
330 urlerr = _pycompatstub()
340 urlerr = _pycompatstub()
331 if not ispy3:
341 if not ispy3:
332 import BaseHTTPServer
342 import BaseHTTPServer
333 import CGIHTTPServer
343 import CGIHTTPServer
334 import SimpleHTTPServer
344 import SimpleHTTPServer
335 import urllib2
345 import urllib2
336 import urllib
346 import urllib
337 import urlparse
347 import urlparse
338 urlreq._registeraliases(urllib, (
348 urlreq._registeraliases(urllib, (
339 "addclosehook",
349 "addclosehook",
340 "addinfourl",
350 "addinfourl",
341 "ftpwrapper",
351 "ftpwrapper",
342 "pathname2url",
352 "pathname2url",
343 "quote",
353 "quote",
344 "splitattr",
354 "splitattr",
345 "splitpasswd",
355 "splitpasswd",
346 "splitport",
356 "splitport",
347 "splituser",
357 "splituser",
348 "unquote",
358 "unquote",
349 "url2pathname",
359 "url2pathname",
350 "urlencode",
360 "urlencode",
351 ))
361 ))
352 urlreq._registeraliases(urllib2, (
362 urlreq._registeraliases(urllib2, (
353 "AbstractHTTPHandler",
363 "AbstractHTTPHandler",
354 "BaseHandler",
364 "BaseHandler",
355 "build_opener",
365 "build_opener",
356 "FileHandler",
366 "FileHandler",
357 "FTPHandler",
367 "FTPHandler",
358 "HTTPBasicAuthHandler",
368 "HTTPBasicAuthHandler",
359 "HTTPDigestAuthHandler",
369 "HTTPDigestAuthHandler",
360 "HTTPHandler",
370 "HTTPHandler",
361 "HTTPPasswordMgrWithDefaultRealm",
371 "HTTPPasswordMgrWithDefaultRealm",
362 "HTTPSHandler",
372 "HTTPSHandler",
363 "install_opener",
373 "install_opener",
364 "ProxyHandler",
374 "ProxyHandler",
365 "Request",
375 "Request",
366 "urlopen",
376 "urlopen",
367 ))
377 ))
368 urlreq._registeraliases(urlparse, (
378 urlreq._registeraliases(urlparse, (
369 "urlparse",
379 "urlparse",
370 "urlunparse",
380 "urlunparse",
371 ))
381 ))
372 urlerr._registeraliases(urllib2, (
382 urlerr._registeraliases(urllib2, (
373 "HTTPError",
383 "HTTPError",
374 "URLError",
384 "URLError",
375 ))
385 ))
376 httpserver._registeraliases(BaseHTTPServer, (
386 httpserver._registeraliases(BaseHTTPServer, (
377 "HTTPServer",
387 "HTTPServer",
378 "BaseHTTPRequestHandler",
388 "BaseHTTPRequestHandler",
379 ))
389 ))
380 httpserver._registeraliases(SimpleHTTPServer, (
390 httpserver._registeraliases(SimpleHTTPServer, (
381 "SimpleHTTPRequestHandler",
391 "SimpleHTTPRequestHandler",
382 ))
392 ))
383 httpserver._registeraliases(CGIHTTPServer, (
393 httpserver._registeraliases(CGIHTTPServer, (
384 "CGIHTTPRequestHandler",
394 "CGIHTTPRequestHandler",
385 ))
395 ))
386
396
387 else:
397 else:
388 import urllib.parse
398 import urllib.parse
389 urlreq._registeraliases(urllib.parse, (
399 urlreq._registeraliases(urllib.parse, (
390 "splitattr",
400 "splitattr",
391 "splitpasswd",
401 "splitpasswd",
392 "splitport",
402 "splitport",
393 "splituser",
403 "splituser",
394 "urlparse",
404 "urlparse",
395 "urlunparse",
405 "urlunparse",
396 ))
406 ))
397 urlreq._registeralias(urllib.parse, "unquote_to_bytes", "unquote")
407 urlreq._registeralias(urllib.parse, "unquote_to_bytes", "unquote")
398 import urllib.request
408 import urllib.request
399 urlreq._registeraliases(urllib.request, (
409 urlreq._registeraliases(urllib.request, (
400 "AbstractHTTPHandler",
410 "AbstractHTTPHandler",
401 "BaseHandler",
411 "BaseHandler",
402 "build_opener",
412 "build_opener",
403 "FileHandler",
413 "FileHandler",
404 "FTPHandler",
414 "FTPHandler",
405 "ftpwrapper",
415 "ftpwrapper",
406 "HTTPHandler",
416 "HTTPHandler",
407 "HTTPSHandler",
417 "HTTPSHandler",
408 "install_opener",
418 "install_opener",
409 "pathname2url",
419 "pathname2url",
410 "HTTPBasicAuthHandler",
420 "HTTPBasicAuthHandler",
411 "HTTPDigestAuthHandler",
421 "HTTPDigestAuthHandler",
412 "HTTPPasswordMgrWithDefaultRealm",
422 "HTTPPasswordMgrWithDefaultRealm",
413 "ProxyHandler",
423 "ProxyHandler",
414 "Request",
424 "Request",
415 "url2pathname",
425 "url2pathname",
416 "urlopen",
426 "urlopen",
417 ))
427 ))
418 import urllib.response
428 import urllib.response
419 urlreq._registeraliases(urllib.response, (
429 urlreq._registeraliases(urllib.response, (
420 "addclosehook",
430 "addclosehook",
421 "addinfourl",
431 "addinfourl",
422 ))
432 ))
423 import urllib.error
433 import urllib.error
424 urlerr._registeraliases(urllib.error, (
434 urlerr._registeraliases(urllib.error, (
425 "HTTPError",
435 "HTTPError",
426 "URLError",
436 "URLError",
427 ))
437 ))
428 import http.server
438 import http.server
429 httpserver._registeraliases(http.server, (
439 httpserver._registeraliases(http.server, (
430 "HTTPServer",
440 "HTTPServer",
431 "BaseHTTPRequestHandler",
441 "BaseHTTPRequestHandler",
432 "SimpleHTTPRequestHandler",
442 "SimpleHTTPRequestHandler",
433 "CGIHTTPRequestHandler",
443 "CGIHTTPRequestHandler",
434 ))
444 ))
435
445
436 # urllib.parse.quote() accepts both str and bytes, decodes bytes
446 # urllib.parse.quote() accepts both str and bytes, decodes bytes
437 # (if necessary), and returns str. This is wonky. We provide a custom
447 # (if necessary), and returns str. This is wonky. We provide a custom
438 # implementation that only accepts bytes and emits bytes.
448 # implementation that only accepts bytes and emits bytes.
439 def quote(s, safe=r'/'):
449 def quote(s, safe=r'/'):
440 s = urllib.parse.quote_from_bytes(s, safe=safe)
450 s = urllib.parse.quote_from_bytes(s, safe=safe)
441 return s.encode('ascii', 'strict')
451 return s.encode('ascii', 'strict')
442
452
443 # urllib.parse.urlencode() returns str. We use this function to make
453 # urllib.parse.urlencode() returns str. We use this function to make
444 # sure we return bytes.
454 # sure we return bytes.
445 def urlencode(query, doseq=False):
455 def urlencode(query, doseq=False):
446 s = urllib.parse.urlencode(query, doseq=doseq)
456 s = urllib.parse.urlencode(query, doseq=doseq)
447 return s.encode('ascii')
457 return s.encode('ascii')
448
458
449 urlreq.quote = quote
459 urlreq.quote = quote
450 urlreq.urlencode = urlencode
460 urlreq.urlencode = urlencode
General Comments 0
You need to be logged in to leave comments. Login now