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