##// END OF EJS Templates
pycompat: only accept a bytestring filepath in Python 2
Martijn Pieters -
r30133:f6dcda75 default
parent child Browse files
Show More
@@ -1,214 +1,196 b''
1 1 # pycompat.py - portability shim for python 3
2 2 #
3 3 # This software may be used and distributed according to the terms of the
4 4 # GNU General Public License version 2 or any later version.
5 5
6 6 """Mercurial portability shim for python 3.
7 7
8 8 This contains aliases to hide python version-specific details from the core.
9 9 """
10 10
11 11 from __future__ import absolute_import
12 12
13 13 import sys
14 14
15 15 ispy3 = (sys.version_info[0] >= 3)
16 16
17 17 if not ispy3:
18 18 import cPickle as pickle
19 19 import cStringIO as io
20 20 import httplib
21 21 import Queue as _queue
22 22 import SocketServer as socketserver
23 23 import urlparse
24 24 import xmlrpclib
25 25 else:
26 26 import http.client as httplib
27 27 import io
28 28 import pickle
29 29 import queue as _queue
30 30 import socketserver
31 31 import urllib.parse as urlparse
32 32 import xmlrpc.client as xmlrpclib
33 33
34 34 if ispy3:
35 35 import builtins
36 36 import functools
37 37 import os
38 38 fsencode = os.fsencode
39 39
40 40 def sysstr(s):
41 41 """Return a keyword str to be passed to Python functions such as
42 42 getattr() and str.encode()
43 43
44 44 This never raises UnicodeDecodeError. Non-ascii characters are
45 45 considered invalid and mapped to arbitrary but unique code points
46 46 such that 'sysstr(a) != sysstr(b)' for all 'a != b'.
47 47 """
48 48 if isinstance(s, builtins.str):
49 49 return s
50 50 return s.decode(u'latin-1')
51 51
52 52 def _wrapattrfunc(f):
53 53 @functools.wraps(f)
54 54 def w(object, name, *args):
55 55 return f(object, sysstr(name), *args)
56 56 return w
57 57
58 58 # these wrappers are automagically imported by hgloader
59 59 delattr = _wrapattrfunc(builtins.delattr)
60 60 getattr = _wrapattrfunc(builtins.getattr)
61 61 hasattr = _wrapattrfunc(builtins.hasattr)
62 62 setattr = _wrapattrfunc(builtins.setattr)
63 63 xrange = builtins.range
64 64
65 65 else:
66 66 def sysstr(s):
67 67 return s
68 68
69 # Partial backport from os.py in Python 3
70 def _fscodec():
71 encoding = sys.getfilesystemencoding()
72 if encoding == 'mbcs':
73 errors = 'strict'
69 # Partial backport from os.py in Python 3, which only accepts bytes.
70 # In Python 2, our paths should only ever be bytes, a unicode path
71 # indicates a bug.
72 def fsencode(filename):
73 if isinstance(filename, str):
74 return filename
74 75 else:
75 errors = 'surrogateescape'
76
77 def fsencode(filename):
78 """
79 Encode filename to the filesystem encoding with 'surrogateescape'
80 error handler, return bytes unchanged. On Windows, use 'strict'
81 error handler if the file system encoding is 'mbcs' (which is the
82 default encoding).
83 """
84 if isinstance(filename, str):
85 return filename
86 elif isinstance(filename, unicode):
87 return filename.encode(encoding, errors)
88 else:
89 raise TypeError(
90 "expect str or unicode, not %s" % type(filename).__name__)
91
92 return fsencode
93
94 fsencode = _fscodec()
95 del _fscodec
76 raise TypeError(
77 "expect str, not %s" % type(filename).__name__)
96 78
97 79 stringio = io.StringIO
98 80 empty = _queue.Empty
99 81 queue = _queue.Queue
100 82
101 83 class _pycompatstub(object):
102 84 def __init__(self):
103 85 self._aliases = {}
104 86
105 87 def _registeraliases(self, origin, items):
106 88 """Add items that will be populated at the first access"""
107 89 items = map(sysstr, items)
108 90 self._aliases.update(
109 91 (item.replace(sysstr('_'), sysstr('')).lower(), (origin, item))
110 92 for item in items)
111 93
112 94 def __getattr__(self, name):
113 95 try:
114 96 origin, item = self._aliases[name]
115 97 except KeyError:
116 98 raise AttributeError(name)
117 99 self.__dict__[name] = obj = getattr(origin, item)
118 100 return obj
119 101
120 102 httpserver = _pycompatstub()
121 103 urlreq = _pycompatstub()
122 104 urlerr = _pycompatstub()
123 105 if not ispy3:
124 106 import BaseHTTPServer
125 107 import CGIHTTPServer
126 108 import SimpleHTTPServer
127 109 import urllib2
128 110 import urllib
129 111 urlreq._registeraliases(urllib, (
130 112 "addclosehook",
131 113 "addinfourl",
132 114 "ftpwrapper",
133 115 "pathname2url",
134 116 "quote",
135 117 "splitattr",
136 118 "splitpasswd",
137 119 "splitport",
138 120 "splituser",
139 121 "unquote",
140 122 "url2pathname",
141 123 "urlencode",
142 124 ))
143 125 urlreq._registeraliases(urllib2, (
144 126 "AbstractHTTPHandler",
145 127 "BaseHandler",
146 128 "build_opener",
147 129 "FileHandler",
148 130 "FTPHandler",
149 131 "HTTPBasicAuthHandler",
150 132 "HTTPDigestAuthHandler",
151 133 "HTTPHandler",
152 134 "HTTPPasswordMgrWithDefaultRealm",
153 135 "HTTPSHandler",
154 136 "install_opener",
155 137 "ProxyHandler",
156 138 "Request",
157 139 "urlopen",
158 140 ))
159 141 urlerr._registeraliases(urllib2, (
160 142 "HTTPError",
161 143 "URLError",
162 144 ))
163 145 httpserver._registeraliases(BaseHTTPServer, (
164 146 "HTTPServer",
165 147 "BaseHTTPRequestHandler",
166 148 ))
167 149 httpserver._registeraliases(SimpleHTTPServer, (
168 150 "SimpleHTTPRequestHandler",
169 151 ))
170 152 httpserver._registeraliases(CGIHTTPServer, (
171 153 "CGIHTTPRequestHandler",
172 154 ))
173 155
174 156 else:
175 157 import urllib.request
176 158 urlreq._registeraliases(urllib.request, (
177 159 "AbstractHTTPHandler",
178 160 "addclosehook",
179 161 "addinfourl",
180 162 "BaseHandler",
181 163 "build_opener",
182 164 "FileHandler",
183 165 "FTPHandler",
184 166 "ftpwrapper",
185 167 "HTTPHandler",
186 168 "HTTPSHandler",
187 169 "install_opener",
188 170 "pathname2url",
189 171 "HTTPBasicAuthHandler",
190 172 "HTTPDigestAuthHandler",
191 173 "HTTPPasswordMgrWithDefaultRealm",
192 174 "ProxyHandler",
193 175 "quote",
194 176 "Request",
195 177 "splitattr",
196 178 "splitpasswd",
197 179 "splitport",
198 180 "splituser",
199 181 "unquote",
200 182 "url2pathname",
201 183 "urlopen",
202 184 ))
203 185 import urllib.error
204 186 urlerr._registeraliases(urllib.error, (
205 187 "HTTPError",
206 188 "URLError",
207 189 ))
208 190 import http.server
209 191 httpserver._registeraliases(http.server, (
210 192 "HTTPServer",
211 193 "BaseHTTPRequestHandler",
212 194 "SimpleHTTPRequestHandler",
213 195 "CGIHTTPRequestHandler",
214 196 ))
General Comments 0
You need to be logged in to leave comments. Login now