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