##// END OF EJS Templates
pycompat: when setting attrs, ensure we use sysstr...
Augie Fackler -
r30086:f3a10896 default
parent child Browse files
Show More
@@ -1,182 +1,184 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 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
37
38 def sysstr(s):
38 def sysstr(s):
39 """Return a keyword str to be passed to Python functions such as
39 """Return a keyword str to be passed to Python functions such as
40 getattr() and str.encode()
40 getattr() and str.encode()
41
41
42 This never raises UnicodeDecodeError. Non-ascii characters are
42 This never raises UnicodeDecodeError. Non-ascii characters are
43 considered invalid and mapped to arbitrary but unique code points
43 considered invalid and mapped to arbitrary but unique code points
44 such that 'sysstr(a) != sysstr(b)' for all 'a != b'.
44 such that 'sysstr(a) != sysstr(b)' for all 'a != b'.
45 """
45 """
46 if isinstance(s, builtins.str):
46 if isinstance(s, builtins.str):
47 return s
47 return s
48 return s.decode(u'latin-1')
48 return s.decode(u'latin-1')
49
49
50 def _wrapattrfunc(f):
50 def _wrapattrfunc(f):
51 @functools.wraps(f)
51 @functools.wraps(f)
52 def w(object, name, *args):
52 def w(object, name, *args):
53 return f(object, sysstr(name), *args)
53 return f(object, sysstr(name), *args)
54 return w
54 return w
55
55
56 # these wrappers are automagically imported by hgloader
56 # these wrappers are automagically imported by hgloader
57 delattr = _wrapattrfunc(builtins.delattr)
57 delattr = _wrapattrfunc(builtins.delattr)
58 getattr = _wrapattrfunc(builtins.getattr)
58 getattr = _wrapattrfunc(builtins.getattr)
59 hasattr = _wrapattrfunc(builtins.hasattr)
59 hasattr = _wrapattrfunc(builtins.hasattr)
60 setattr = _wrapattrfunc(builtins.setattr)
60 setattr = _wrapattrfunc(builtins.setattr)
61 xrange = builtins.range
61 xrange = builtins.range
62
62
63 else:
63 else:
64 def sysstr(s):
64 def sysstr(s):
65 return s
65 return s
66
66
67 stringio = io.StringIO
67 stringio = io.StringIO
68 empty = _queue.Empty
68 empty = _queue.Empty
69 queue = _queue.Queue
69 queue = _queue.Queue
70
70
71 class _pycompatstub(object):
71 class _pycompatstub(object):
72 def __init__(self):
72 def __init__(self):
73 self._aliases = {}
73 self._aliases = {}
74
74
75 def _registeraliases(self, origin, items):
75 def _registeraliases(self, origin, items):
76 """Add items that will be populated at the first access"""
76 """Add items that will be populated at the first access"""
77 self._aliases.update((item.replace('_', '').lower(), (origin, item))
77 items = map(sysstr, items)
78 for item in items)
78 self._aliases.update(
79 (item.replace(sysstr('_'), sysstr('')).lower(), (origin, item))
80 for item in items)
79
81
80 def __getattr__(self, name):
82 def __getattr__(self, name):
81 try:
83 try:
82 origin, item = self._aliases[name]
84 origin, item = self._aliases[name]
83 except KeyError:
85 except KeyError:
84 raise AttributeError(name)
86 raise AttributeError(name)
85 self.__dict__[name] = obj = getattr(origin, item)
87 self.__dict__[name] = obj = getattr(origin, item)
86 return obj
88 return obj
87
89
88 httpserver = _pycompatstub()
90 httpserver = _pycompatstub()
89 urlreq = _pycompatstub()
91 urlreq = _pycompatstub()
90 urlerr = _pycompatstub()
92 urlerr = _pycompatstub()
91 if not ispy3:
93 if not ispy3:
92 import BaseHTTPServer
94 import BaseHTTPServer
93 import CGIHTTPServer
95 import CGIHTTPServer
94 import SimpleHTTPServer
96 import SimpleHTTPServer
95 import urllib2
97 import urllib2
96 import urllib
98 import urllib
97 urlreq._registeraliases(urllib, (
99 urlreq._registeraliases(urllib, (
98 "addclosehook",
100 "addclosehook",
99 "addinfourl",
101 "addinfourl",
100 "ftpwrapper",
102 "ftpwrapper",
101 "pathname2url",
103 "pathname2url",
102 "quote",
104 "quote",
103 "splitattr",
105 "splitattr",
104 "splitpasswd",
106 "splitpasswd",
105 "splitport",
107 "splitport",
106 "splituser",
108 "splituser",
107 "unquote",
109 "unquote",
108 "url2pathname",
110 "url2pathname",
109 "urlencode",
111 "urlencode",
110 ))
112 ))
111 urlreq._registeraliases(urllib2, (
113 urlreq._registeraliases(urllib2, (
112 "AbstractHTTPHandler",
114 "AbstractHTTPHandler",
113 "BaseHandler",
115 "BaseHandler",
114 "build_opener",
116 "build_opener",
115 "FileHandler",
117 "FileHandler",
116 "FTPHandler",
118 "FTPHandler",
117 "HTTPBasicAuthHandler",
119 "HTTPBasicAuthHandler",
118 "HTTPDigestAuthHandler",
120 "HTTPDigestAuthHandler",
119 "HTTPHandler",
121 "HTTPHandler",
120 "HTTPPasswordMgrWithDefaultRealm",
122 "HTTPPasswordMgrWithDefaultRealm",
121 "HTTPSHandler",
123 "HTTPSHandler",
122 "install_opener",
124 "install_opener",
123 "ProxyHandler",
125 "ProxyHandler",
124 "Request",
126 "Request",
125 "urlopen",
127 "urlopen",
126 ))
128 ))
127 urlerr._registeraliases(urllib2, (
129 urlerr._registeraliases(urllib2, (
128 "HTTPError",
130 "HTTPError",
129 "URLError",
131 "URLError",
130 ))
132 ))
131 httpserver._registeraliases(BaseHTTPServer, (
133 httpserver._registeraliases(BaseHTTPServer, (
132 "HTTPServer",
134 "HTTPServer",
133 "BaseHTTPRequestHandler",
135 "BaseHTTPRequestHandler",
134 ))
136 ))
135 httpserver._registeraliases(SimpleHTTPServer, (
137 httpserver._registeraliases(SimpleHTTPServer, (
136 "SimpleHTTPRequestHandler",
138 "SimpleHTTPRequestHandler",
137 ))
139 ))
138 httpserver._registeraliases(CGIHTTPServer, (
140 httpserver._registeraliases(CGIHTTPServer, (
139 "CGIHTTPRequestHandler",
141 "CGIHTTPRequestHandler",
140 ))
142 ))
141
143
142 else:
144 else:
143 import urllib.request
145 import urllib.request
144 urlreq._registeraliases(urllib.request, (
146 urlreq._registeraliases(urllib.request, (
145 "AbstractHTTPHandler",
147 "AbstractHTTPHandler",
146 "addclosehook",
148 "addclosehook",
147 "addinfourl",
149 "addinfourl",
148 "BaseHandler",
150 "BaseHandler",
149 "build_opener",
151 "build_opener",
150 "FileHandler",
152 "FileHandler",
151 "FTPHandler",
153 "FTPHandler",
152 "ftpwrapper",
154 "ftpwrapper",
153 "HTTPHandler",
155 "HTTPHandler",
154 "HTTPSHandler",
156 "HTTPSHandler",
155 "install_opener",
157 "install_opener",
156 "pathname2url",
158 "pathname2url",
157 "HTTPBasicAuthHandler",
159 "HTTPBasicAuthHandler",
158 "HTTPDigestAuthHandler",
160 "HTTPDigestAuthHandler",
159 "HTTPPasswordMgrWithDefaultRealm",
161 "HTTPPasswordMgrWithDefaultRealm",
160 "ProxyHandler",
162 "ProxyHandler",
161 "quote",
163 "quote",
162 "Request",
164 "Request",
163 "splitattr",
165 "splitattr",
164 "splitpasswd",
166 "splitpasswd",
165 "splitport",
167 "splitport",
166 "splituser",
168 "splituser",
167 "unquote",
169 "unquote",
168 "url2pathname",
170 "url2pathname",
169 "urlopen",
171 "urlopen",
170 ))
172 ))
171 import urllib.error
173 import urllib.error
172 urlerr._registeraliases(urllib.error, (
174 urlerr._registeraliases(urllib.error, (
173 "HTTPError",
175 "HTTPError",
174 "URLError",
176 "URLError",
175 ))
177 ))
176 import http.server
178 import http.server
177 httpserver._registeraliases(http.server, (
179 httpserver._registeraliases(http.server, (
178 "HTTPServer",
180 "HTTPServer",
179 "BaseHTTPRequestHandler",
181 "BaseHTTPRequestHandler",
180 "SimpleHTTPRequestHandler",
182 "SimpleHTTPRequestHandler",
181 "CGIHTTPRequestHandler",
183 "CGIHTTPRequestHandler",
182 ))
184 ))
General Comments 0
You need to be logged in to leave comments. Login now