##// END OF EJS Templates
encoding: use absolute_import
Gregory Szorc -
r27355:b479fc42 default
parent child Browse files
Show More
@@ -1,525 +1,532 b''
1 # encoding.py - character transcoding support for Mercurial
1 # encoding.py - character transcoding support for Mercurial
2 #
2 #
3 # Copyright 2005-2009 Matt Mackall <mpm@selenic.com> and others
3 # Copyright 2005-2009 Matt Mackall <mpm@selenic.com> and others
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 import error
8 from __future__ import absolute_import
9 import unicodedata, locale, os
9
10 import locale
11 import os
12 import unicodedata
13
14 from . import (
15 error,
16 )
10
17
11 # These unicode characters are ignored by HFS+ (Apple Technote 1150,
18 # These unicode characters are ignored by HFS+ (Apple Technote 1150,
12 # "Unicode Subtleties"), so we need to ignore them in some places for
19 # "Unicode Subtleties"), so we need to ignore them in some places for
13 # sanity.
20 # sanity.
14 _ignore = [unichr(int(x, 16)).encode("utf-8") for x in
21 _ignore = [unichr(int(x, 16)).encode("utf-8") for x in
15 "200c 200d 200e 200f 202a 202b 202c 202d 202e "
22 "200c 200d 200e 200f 202a 202b 202c 202d 202e "
16 "206a 206b 206c 206d 206e 206f feff".split()]
23 "206a 206b 206c 206d 206e 206f feff".split()]
17 # verify the next function will work
24 # verify the next function will work
18 assert set([i[0] for i in _ignore]) == set(["\xe2", "\xef"])
25 assert set([i[0] for i in _ignore]) == set(["\xe2", "\xef"])
19
26
20 def hfsignoreclean(s):
27 def hfsignoreclean(s):
21 """Remove codepoints ignored by HFS+ from s.
28 """Remove codepoints ignored by HFS+ from s.
22
29
23 >>> hfsignoreclean(u'.h\u200cg'.encode('utf-8'))
30 >>> hfsignoreclean(u'.h\u200cg'.encode('utf-8'))
24 '.hg'
31 '.hg'
25 >>> hfsignoreclean(u'.h\ufeffg'.encode('utf-8'))
32 >>> hfsignoreclean(u'.h\ufeffg'.encode('utf-8'))
26 '.hg'
33 '.hg'
27 """
34 """
28 if "\xe2" in s or "\xef" in s:
35 if "\xe2" in s or "\xef" in s:
29 for c in _ignore:
36 for c in _ignore:
30 s = s.replace(c, '')
37 s = s.replace(c, '')
31 return s
38 return s
32
39
33 def _getpreferredencoding():
40 def _getpreferredencoding():
34 '''
41 '''
35 On darwin, getpreferredencoding ignores the locale environment and
42 On darwin, getpreferredencoding ignores the locale environment and
36 always returns mac-roman. http://bugs.python.org/issue6202 fixes this
43 always returns mac-roman. http://bugs.python.org/issue6202 fixes this
37 for Python 2.7 and up. This is the same corrected code for earlier
44 for Python 2.7 and up. This is the same corrected code for earlier
38 Python versions.
45 Python versions.
39
46
40 However, we can't use a version check for this method, as some distributions
47 However, we can't use a version check for this method, as some distributions
41 patch Python to fix this. Instead, we use it as a 'fixer' for the mac-roman
48 patch Python to fix this. Instead, we use it as a 'fixer' for the mac-roman
42 encoding, as it is unlikely that this encoding is the actually expected.
49 encoding, as it is unlikely that this encoding is the actually expected.
43 '''
50 '''
44 try:
51 try:
45 locale.CODESET
52 locale.CODESET
46 except AttributeError:
53 except AttributeError:
47 # Fall back to parsing environment variables :-(
54 # Fall back to parsing environment variables :-(
48 return locale.getdefaultlocale()[1]
55 return locale.getdefaultlocale()[1]
49
56
50 oldloc = locale.setlocale(locale.LC_CTYPE)
57 oldloc = locale.setlocale(locale.LC_CTYPE)
51 locale.setlocale(locale.LC_CTYPE, "")
58 locale.setlocale(locale.LC_CTYPE, "")
52 result = locale.nl_langinfo(locale.CODESET)
59 result = locale.nl_langinfo(locale.CODESET)
53 locale.setlocale(locale.LC_CTYPE, oldloc)
60 locale.setlocale(locale.LC_CTYPE, oldloc)
54
61
55 return result
62 return result
56
63
57 _encodingfixers = {
64 _encodingfixers = {
58 '646': lambda: 'ascii',
65 '646': lambda: 'ascii',
59 'ANSI_X3.4-1968': lambda: 'ascii',
66 'ANSI_X3.4-1968': lambda: 'ascii',
60 'mac-roman': _getpreferredencoding
67 'mac-roman': _getpreferredencoding
61 }
68 }
62
69
63 try:
70 try:
64 encoding = os.environ.get("HGENCODING")
71 encoding = os.environ.get("HGENCODING")
65 if not encoding:
72 if not encoding:
66 encoding = locale.getpreferredencoding() or 'ascii'
73 encoding = locale.getpreferredencoding() or 'ascii'
67 encoding = _encodingfixers.get(encoding, lambda: encoding)()
74 encoding = _encodingfixers.get(encoding, lambda: encoding)()
68 except locale.Error:
75 except locale.Error:
69 encoding = 'ascii'
76 encoding = 'ascii'
70 encodingmode = os.environ.get("HGENCODINGMODE", "strict")
77 encodingmode = os.environ.get("HGENCODINGMODE", "strict")
71 fallbackencoding = 'ISO-8859-1'
78 fallbackencoding = 'ISO-8859-1'
72
79
73 class localstr(str):
80 class localstr(str):
74 '''This class allows strings that are unmodified to be
81 '''This class allows strings that are unmodified to be
75 round-tripped to the local encoding and back'''
82 round-tripped to the local encoding and back'''
76 def __new__(cls, u, l):
83 def __new__(cls, u, l):
77 s = str.__new__(cls, l)
84 s = str.__new__(cls, l)
78 s._utf8 = u
85 s._utf8 = u
79 return s
86 return s
80 def __hash__(self):
87 def __hash__(self):
81 return hash(self._utf8) # avoid collisions in local string space
88 return hash(self._utf8) # avoid collisions in local string space
82
89
83 def tolocal(s):
90 def tolocal(s):
84 """
91 """
85 Convert a string from internal UTF-8 to local encoding
92 Convert a string from internal UTF-8 to local encoding
86
93
87 All internal strings should be UTF-8 but some repos before the
94 All internal strings should be UTF-8 but some repos before the
88 implementation of locale support may contain latin1 or possibly
95 implementation of locale support may contain latin1 or possibly
89 other character sets. We attempt to decode everything strictly
96 other character sets. We attempt to decode everything strictly
90 using UTF-8, then Latin-1, and failing that, we use UTF-8 and
97 using UTF-8, then Latin-1, and failing that, we use UTF-8 and
91 replace unknown characters.
98 replace unknown characters.
92
99
93 The localstr class is used to cache the known UTF-8 encoding of
100 The localstr class is used to cache the known UTF-8 encoding of
94 strings next to their local representation to allow lossless
101 strings next to their local representation to allow lossless
95 round-trip conversion back to UTF-8.
102 round-trip conversion back to UTF-8.
96
103
97 >>> u = 'foo: \\xc3\\xa4' # utf-8
104 >>> u = 'foo: \\xc3\\xa4' # utf-8
98 >>> l = tolocal(u)
105 >>> l = tolocal(u)
99 >>> l
106 >>> l
100 'foo: ?'
107 'foo: ?'
101 >>> fromlocal(l)
108 >>> fromlocal(l)
102 'foo: \\xc3\\xa4'
109 'foo: \\xc3\\xa4'
103 >>> u2 = 'foo: \\xc3\\xa1'
110 >>> u2 = 'foo: \\xc3\\xa1'
104 >>> d = { l: 1, tolocal(u2): 2 }
111 >>> d = { l: 1, tolocal(u2): 2 }
105 >>> len(d) # no collision
112 >>> len(d) # no collision
106 2
113 2
107 >>> 'foo: ?' in d
114 >>> 'foo: ?' in d
108 False
115 False
109 >>> l1 = 'foo: \\xe4' # historical latin1 fallback
116 >>> l1 = 'foo: \\xe4' # historical latin1 fallback
110 >>> l = tolocal(l1)
117 >>> l = tolocal(l1)
111 >>> l
118 >>> l
112 'foo: ?'
119 'foo: ?'
113 >>> fromlocal(l) # magically in utf-8
120 >>> fromlocal(l) # magically in utf-8
114 'foo: \\xc3\\xa4'
121 'foo: \\xc3\\xa4'
115 """
122 """
116
123
117 try:
124 try:
118 try:
125 try:
119 # make sure string is actually stored in UTF-8
126 # make sure string is actually stored in UTF-8
120 u = s.decode('UTF-8')
127 u = s.decode('UTF-8')
121 if encoding == 'UTF-8':
128 if encoding == 'UTF-8':
122 # fast path
129 # fast path
123 return s
130 return s
124 r = u.encode(encoding, "replace")
131 r = u.encode(encoding, "replace")
125 if u == r.decode(encoding):
132 if u == r.decode(encoding):
126 # r is a safe, non-lossy encoding of s
133 # r is a safe, non-lossy encoding of s
127 return r
134 return r
128 return localstr(s, r)
135 return localstr(s, r)
129 except UnicodeDecodeError:
136 except UnicodeDecodeError:
130 # we should only get here if we're looking at an ancient changeset
137 # we should only get here if we're looking at an ancient changeset
131 try:
138 try:
132 u = s.decode(fallbackencoding)
139 u = s.decode(fallbackencoding)
133 r = u.encode(encoding, "replace")
140 r = u.encode(encoding, "replace")
134 if u == r.decode(encoding):
141 if u == r.decode(encoding):
135 # r is a safe, non-lossy encoding of s
142 # r is a safe, non-lossy encoding of s
136 return r
143 return r
137 return localstr(u.encode('UTF-8'), r)
144 return localstr(u.encode('UTF-8'), r)
138 except UnicodeDecodeError:
145 except UnicodeDecodeError:
139 u = s.decode("utf-8", "replace") # last ditch
146 u = s.decode("utf-8", "replace") # last ditch
140 return u.encode(encoding, "replace") # can't round-trip
147 return u.encode(encoding, "replace") # can't round-trip
141 except LookupError as k:
148 except LookupError as k:
142 raise error.Abort(k, hint="please check your locale settings")
149 raise error.Abort(k, hint="please check your locale settings")
143
150
144 def fromlocal(s):
151 def fromlocal(s):
145 """
152 """
146 Convert a string from the local character encoding to UTF-8
153 Convert a string from the local character encoding to UTF-8
147
154
148 We attempt to decode strings using the encoding mode set by
155 We attempt to decode strings using the encoding mode set by
149 HGENCODINGMODE, which defaults to 'strict'. In this mode, unknown
156 HGENCODINGMODE, which defaults to 'strict'. In this mode, unknown
150 characters will cause an error message. Other modes include
157 characters will cause an error message. Other modes include
151 'replace', which replaces unknown characters with a special
158 'replace', which replaces unknown characters with a special
152 Unicode character, and 'ignore', which drops the character.
159 Unicode character, and 'ignore', which drops the character.
153 """
160 """
154
161
155 # can we do a lossless round-trip?
162 # can we do a lossless round-trip?
156 if isinstance(s, localstr):
163 if isinstance(s, localstr):
157 return s._utf8
164 return s._utf8
158
165
159 try:
166 try:
160 return s.decode(encoding, encodingmode).encode("utf-8")
167 return s.decode(encoding, encodingmode).encode("utf-8")
161 except UnicodeDecodeError as inst:
168 except UnicodeDecodeError as inst:
162 sub = s[max(0, inst.start - 10):inst.start + 10]
169 sub = s[max(0, inst.start - 10):inst.start + 10]
163 raise error.Abort("decoding near '%s': %s!" % (sub, inst))
170 raise error.Abort("decoding near '%s': %s!" % (sub, inst))
164 except LookupError as k:
171 except LookupError as k:
165 raise error.Abort(k, hint="please check your locale settings")
172 raise error.Abort(k, hint="please check your locale settings")
166
173
167 # How to treat ambiguous-width characters. Set to 'wide' to treat as wide.
174 # How to treat ambiguous-width characters. Set to 'wide' to treat as wide.
168 wide = (os.environ.get("HGENCODINGAMBIGUOUS", "narrow") == "wide"
175 wide = (os.environ.get("HGENCODINGAMBIGUOUS", "narrow") == "wide"
169 and "WFA" or "WF")
176 and "WFA" or "WF")
170
177
171 def colwidth(s):
178 def colwidth(s):
172 "Find the column width of a string for display in the local encoding"
179 "Find the column width of a string for display in the local encoding"
173 return ucolwidth(s.decode(encoding, 'replace'))
180 return ucolwidth(s.decode(encoding, 'replace'))
174
181
175 def ucolwidth(d):
182 def ucolwidth(d):
176 "Find the column width of a Unicode string for display"
183 "Find the column width of a Unicode string for display"
177 eaw = getattr(unicodedata, 'east_asian_width', None)
184 eaw = getattr(unicodedata, 'east_asian_width', None)
178 if eaw is not None:
185 if eaw is not None:
179 return sum([eaw(c) in wide and 2 or 1 for c in d])
186 return sum([eaw(c) in wide and 2 or 1 for c in d])
180 return len(d)
187 return len(d)
181
188
182 def getcols(s, start, c):
189 def getcols(s, start, c):
183 '''Use colwidth to find a c-column substring of s starting at byte
190 '''Use colwidth to find a c-column substring of s starting at byte
184 index start'''
191 index start'''
185 for x in xrange(start + c, len(s)):
192 for x in xrange(start + c, len(s)):
186 t = s[start:x]
193 t = s[start:x]
187 if colwidth(t) == c:
194 if colwidth(t) == c:
188 return t
195 return t
189
196
190 def trim(s, width, ellipsis='', leftside=False):
197 def trim(s, width, ellipsis='', leftside=False):
191 """Trim string 's' to at most 'width' columns (including 'ellipsis').
198 """Trim string 's' to at most 'width' columns (including 'ellipsis').
192
199
193 If 'leftside' is True, left side of string 's' is trimmed.
200 If 'leftside' is True, left side of string 's' is trimmed.
194 'ellipsis' is always placed at trimmed side.
201 'ellipsis' is always placed at trimmed side.
195
202
196 >>> ellipsis = '+++'
203 >>> ellipsis = '+++'
197 >>> from mercurial import encoding
204 >>> from . import encoding
198 >>> encoding.encoding = 'utf-8'
205 >>> encoding.encoding = 'utf-8'
199 >>> t= '1234567890'
206 >>> t= '1234567890'
200 >>> print trim(t, 12, ellipsis=ellipsis)
207 >>> print trim(t, 12, ellipsis=ellipsis)
201 1234567890
208 1234567890
202 >>> print trim(t, 10, ellipsis=ellipsis)
209 >>> print trim(t, 10, ellipsis=ellipsis)
203 1234567890
210 1234567890
204 >>> print trim(t, 8, ellipsis=ellipsis)
211 >>> print trim(t, 8, ellipsis=ellipsis)
205 12345+++
212 12345+++
206 >>> print trim(t, 8, ellipsis=ellipsis, leftside=True)
213 >>> print trim(t, 8, ellipsis=ellipsis, leftside=True)
207 +++67890
214 +++67890
208 >>> print trim(t, 8)
215 >>> print trim(t, 8)
209 12345678
216 12345678
210 >>> print trim(t, 8, leftside=True)
217 >>> print trim(t, 8, leftside=True)
211 34567890
218 34567890
212 >>> print trim(t, 3, ellipsis=ellipsis)
219 >>> print trim(t, 3, ellipsis=ellipsis)
213 +++
220 +++
214 >>> print trim(t, 1, ellipsis=ellipsis)
221 >>> print trim(t, 1, ellipsis=ellipsis)
215 +
222 +
216 >>> u = u'\u3042\u3044\u3046\u3048\u304a' # 2 x 5 = 10 columns
223 >>> u = u'\u3042\u3044\u3046\u3048\u304a' # 2 x 5 = 10 columns
217 >>> t = u.encode(encoding.encoding)
224 >>> t = u.encode(encoding.encoding)
218 >>> print trim(t, 12, ellipsis=ellipsis)
225 >>> print trim(t, 12, ellipsis=ellipsis)
219 \xe3\x81\x82\xe3\x81\x84\xe3\x81\x86\xe3\x81\x88\xe3\x81\x8a
226 \xe3\x81\x82\xe3\x81\x84\xe3\x81\x86\xe3\x81\x88\xe3\x81\x8a
220 >>> print trim(t, 10, ellipsis=ellipsis)
227 >>> print trim(t, 10, ellipsis=ellipsis)
221 \xe3\x81\x82\xe3\x81\x84\xe3\x81\x86\xe3\x81\x88\xe3\x81\x8a
228 \xe3\x81\x82\xe3\x81\x84\xe3\x81\x86\xe3\x81\x88\xe3\x81\x8a
222 >>> print trim(t, 8, ellipsis=ellipsis)
229 >>> print trim(t, 8, ellipsis=ellipsis)
223 \xe3\x81\x82\xe3\x81\x84+++
230 \xe3\x81\x82\xe3\x81\x84+++
224 >>> print trim(t, 8, ellipsis=ellipsis, leftside=True)
231 >>> print trim(t, 8, ellipsis=ellipsis, leftside=True)
225 +++\xe3\x81\x88\xe3\x81\x8a
232 +++\xe3\x81\x88\xe3\x81\x8a
226 >>> print trim(t, 5)
233 >>> print trim(t, 5)
227 \xe3\x81\x82\xe3\x81\x84
234 \xe3\x81\x82\xe3\x81\x84
228 >>> print trim(t, 5, leftside=True)
235 >>> print trim(t, 5, leftside=True)
229 \xe3\x81\x88\xe3\x81\x8a
236 \xe3\x81\x88\xe3\x81\x8a
230 >>> print trim(t, 4, ellipsis=ellipsis)
237 >>> print trim(t, 4, ellipsis=ellipsis)
231 +++
238 +++
232 >>> print trim(t, 4, ellipsis=ellipsis, leftside=True)
239 >>> print trim(t, 4, ellipsis=ellipsis, leftside=True)
233 +++
240 +++
234 >>> t = '\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa' # invalid byte sequence
241 >>> t = '\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa' # invalid byte sequence
235 >>> print trim(t, 12, ellipsis=ellipsis)
242 >>> print trim(t, 12, ellipsis=ellipsis)
236 \x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa
243 \x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa
237 >>> print trim(t, 10, ellipsis=ellipsis)
244 >>> print trim(t, 10, ellipsis=ellipsis)
238 \x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa
245 \x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa
239 >>> print trim(t, 8, ellipsis=ellipsis)
246 >>> print trim(t, 8, ellipsis=ellipsis)
240 \x11\x22\x33\x44\x55+++
247 \x11\x22\x33\x44\x55+++
241 >>> print trim(t, 8, ellipsis=ellipsis, leftside=True)
248 >>> print trim(t, 8, ellipsis=ellipsis, leftside=True)
242 +++\x66\x77\x88\x99\xaa
249 +++\x66\x77\x88\x99\xaa
243 >>> print trim(t, 8)
250 >>> print trim(t, 8)
244 \x11\x22\x33\x44\x55\x66\x77\x88
251 \x11\x22\x33\x44\x55\x66\x77\x88
245 >>> print trim(t, 8, leftside=True)
252 >>> print trim(t, 8, leftside=True)
246 \x33\x44\x55\x66\x77\x88\x99\xaa
253 \x33\x44\x55\x66\x77\x88\x99\xaa
247 >>> print trim(t, 3, ellipsis=ellipsis)
254 >>> print trim(t, 3, ellipsis=ellipsis)
248 +++
255 +++
249 >>> print trim(t, 1, ellipsis=ellipsis)
256 >>> print trim(t, 1, ellipsis=ellipsis)
250 +
257 +
251 """
258 """
252 try:
259 try:
253 u = s.decode(encoding)
260 u = s.decode(encoding)
254 except UnicodeDecodeError:
261 except UnicodeDecodeError:
255 if len(s) <= width: # trimming is not needed
262 if len(s) <= width: # trimming is not needed
256 return s
263 return s
257 width -= len(ellipsis)
264 width -= len(ellipsis)
258 if width <= 0: # no enough room even for ellipsis
265 if width <= 0: # no enough room even for ellipsis
259 return ellipsis[:width + len(ellipsis)]
266 return ellipsis[:width + len(ellipsis)]
260 if leftside:
267 if leftside:
261 return ellipsis + s[-width:]
268 return ellipsis + s[-width:]
262 return s[:width] + ellipsis
269 return s[:width] + ellipsis
263
270
264 if ucolwidth(u) <= width: # trimming is not needed
271 if ucolwidth(u) <= width: # trimming is not needed
265 return s
272 return s
266
273
267 width -= len(ellipsis)
274 width -= len(ellipsis)
268 if width <= 0: # no enough room even for ellipsis
275 if width <= 0: # no enough room even for ellipsis
269 return ellipsis[:width + len(ellipsis)]
276 return ellipsis[:width + len(ellipsis)]
270
277
271 if leftside:
278 if leftside:
272 uslice = lambda i: u[i:]
279 uslice = lambda i: u[i:]
273 concat = lambda s: ellipsis + s
280 concat = lambda s: ellipsis + s
274 else:
281 else:
275 uslice = lambda i: u[:-i]
282 uslice = lambda i: u[:-i]
276 concat = lambda s: s + ellipsis
283 concat = lambda s: s + ellipsis
277 for i in xrange(1, len(u)):
284 for i in xrange(1, len(u)):
278 usub = uslice(i)
285 usub = uslice(i)
279 if ucolwidth(usub) <= width:
286 if ucolwidth(usub) <= width:
280 return concat(usub.encode(encoding))
287 return concat(usub.encode(encoding))
281 return ellipsis # no enough room for multi-column characters
288 return ellipsis # no enough room for multi-column characters
282
289
283 def _asciilower(s):
290 def _asciilower(s):
284 '''convert a string to lowercase if ASCII
291 '''convert a string to lowercase if ASCII
285
292
286 Raises UnicodeDecodeError if non-ASCII characters are found.'''
293 Raises UnicodeDecodeError if non-ASCII characters are found.'''
287 s.decode('ascii')
294 s.decode('ascii')
288 return s.lower()
295 return s.lower()
289
296
290 def asciilower(s):
297 def asciilower(s):
291 # delay importing avoids cyclic dependency around "parsers" in
298 # delay importing avoids cyclic dependency around "parsers" in
292 # pure Python build (util => i18n => encoding => parsers => util)
299 # pure Python build (util => i18n => encoding => parsers => util)
293 import parsers
300 from . import parsers
294 impl = getattr(parsers, 'asciilower', _asciilower)
301 impl = getattr(parsers, 'asciilower', _asciilower)
295 global asciilower
302 global asciilower
296 asciilower = impl
303 asciilower = impl
297 return impl(s)
304 return impl(s)
298
305
299 def _asciiupper(s):
306 def _asciiupper(s):
300 '''convert a string to uppercase if ASCII
307 '''convert a string to uppercase if ASCII
301
308
302 Raises UnicodeDecodeError if non-ASCII characters are found.'''
309 Raises UnicodeDecodeError if non-ASCII characters are found.'''
303 s.decode('ascii')
310 s.decode('ascii')
304 return s.upper()
311 return s.upper()
305
312
306 def asciiupper(s):
313 def asciiupper(s):
307 # delay importing avoids cyclic dependency around "parsers" in
314 # delay importing avoids cyclic dependency around "parsers" in
308 # pure Python build (util => i18n => encoding => parsers => util)
315 # pure Python build (util => i18n => encoding => parsers => util)
309 import parsers
316 from . import parsers
310 impl = getattr(parsers, 'asciiupper', _asciiupper)
317 impl = getattr(parsers, 'asciiupper', _asciiupper)
311 global asciiupper
318 global asciiupper
312 asciiupper = impl
319 asciiupper = impl
313 return impl(s)
320 return impl(s)
314
321
315 def lower(s):
322 def lower(s):
316 "best-effort encoding-aware case-folding of local string s"
323 "best-effort encoding-aware case-folding of local string s"
317 try:
324 try:
318 return asciilower(s)
325 return asciilower(s)
319 except UnicodeDecodeError:
326 except UnicodeDecodeError:
320 pass
327 pass
321 try:
328 try:
322 if isinstance(s, localstr):
329 if isinstance(s, localstr):
323 u = s._utf8.decode("utf-8")
330 u = s._utf8.decode("utf-8")
324 else:
331 else:
325 u = s.decode(encoding, encodingmode)
332 u = s.decode(encoding, encodingmode)
326
333
327 lu = u.lower()
334 lu = u.lower()
328 if u == lu:
335 if u == lu:
329 return s # preserve localstring
336 return s # preserve localstring
330 return lu.encode(encoding)
337 return lu.encode(encoding)
331 except UnicodeError:
338 except UnicodeError:
332 return s.lower() # we don't know how to fold this except in ASCII
339 return s.lower() # we don't know how to fold this except in ASCII
333 except LookupError as k:
340 except LookupError as k:
334 raise error.Abort(k, hint="please check your locale settings")
341 raise error.Abort(k, hint="please check your locale settings")
335
342
336 def upper(s):
343 def upper(s):
337 "best-effort encoding-aware case-folding of local string s"
344 "best-effort encoding-aware case-folding of local string s"
338 try:
345 try:
339 return asciiupper(s)
346 return asciiupper(s)
340 except UnicodeDecodeError:
347 except UnicodeDecodeError:
341 return upperfallback(s)
348 return upperfallback(s)
342
349
343 def upperfallback(s):
350 def upperfallback(s):
344 try:
351 try:
345 if isinstance(s, localstr):
352 if isinstance(s, localstr):
346 u = s._utf8.decode("utf-8")
353 u = s._utf8.decode("utf-8")
347 else:
354 else:
348 u = s.decode(encoding, encodingmode)
355 u = s.decode(encoding, encodingmode)
349
356
350 uu = u.upper()
357 uu = u.upper()
351 if u == uu:
358 if u == uu:
352 return s # preserve localstring
359 return s # preserve localstring
353 return uu.encode(encoding)
360 return uu.encode(encoding)
354 except UnicodeError:
361 except UnicodeError:
355 return s.upper() # we don't know how to fold this except in ASCII
362 return s.upper() # we don't know how to fold this except in ASCII
356 except LookupError as k:
363 except LookupError as k:
357 raise error.Abort(k, hint="please check your locale settings")
364 raise error.Abort(k, hint="please check your locale settings")
358
365
359 class normcasespecs(object):
366 class normcasespecs(object):
360 '''what a platform's normcase does to ASCII strings
367 '''what a platform's normcase does to ASCII strings
361
368
362 This is specified per platform, and should be consistent with what normcase
369 This is specified per platform, and should be consistent with what normcase
363 on that platform actually does.
370 on that platform actually does.
364
371
365 lower: normcase lowercases ASCII strings
372 lower: normcase lowercases ASCII strings
366 upper: normcase uppercases ASCII strings
373 upper: normcase uppercases ASCII strings
367 other: the fallback function should always be called
374 other: the fallback function should always be called
368
375
369 This should be kept in sync with normcase_spec in util.h.'''
376 This should be kept in sync with normcase_spec in util.h.'''
370 lower = -1
377 lower = -1
371 upper = 1
378 upper = 1
372 other = 0
379 other = 0
373
380
374 _jsonmap = {}
381 _jsonmap = {}
375
382
376 def jsonescape(s):
383 def jsonescape(s):
377 '''returns a string suitable for JSON
384 '''returns a string suitable for JSON
378
385
379 JSON is problematic for us because it doesn't support non-Unicode
386 JSON is problematic for us because it doesn't support non-Unicode
380 bytes. To deal with this, we take the following approach:
387 bytes. To deal with this, we take the following approach:
381
388
382 - localstr objects are converted back to UTF-8
389 - localstr objects are converted back to UTF-8
383 - valid UTF-8/ASCII strings are passed as-is
390 - valid UTF-8/ASCII strings are passed as-is
384 - other strings are converted to UTF-8b surrogate encoding
391 - other strings are converted to UTF-8b surrogate encoding
385 - apply JSON-specified string escaping
392 - apply JSON-specified string escaping
386
393
387 (escapes are doubled in these tests)
394 (escapes are doubled in these tests)
388
395
389 >>> jsonescape('this is a test')
396 >>> jsonescape('this is a test')
390 'this is a test'
397 'this is a test'
391 >>> jsonescape('escape characters: \\0 \\x0b \\t \\n \\r \\" \\\\')
398 >>> jsonescape('escape characters: \\0 \\x0b \\t \\n \\r \\" \\\\')
392 'escape characters: \\\\u0000 \\\\u000b \\\\t \\\\n \\\\r \\\\" \\\\\\\\'
399 'escape characters: \\\\u0000 \\\\u000b \\\\t \\\\n \\\\r \\\\" \\\\\\\\'
393 >>> jsonescape('a weird byte: \\xdd')
400 >>> jsonescape('a weird byte: \\xdd')
394 'a weird byte: \\xed\\xb3\\x9d'
401 'a weird byte: \\xed\\xb3\\x9d'
395 >>> jsonescape('utf-8: caf\\xc3\\xa9')
402 >>> jsonescape('utf-8: caf\\xc3\\xa9')
396 'utf-8: caf\\xc3\\xa9'
403 'utf-8: caf\\xc3\\xa9'
397 >>> jsonescape('')
404 >>> jsonescape('')
398 ''
405 ''
399 '''
406 '''
400
407
401 if not _jsonmap:
408 if not _jsonmap:
402 for x in xrange(32):
409 for x in xrange(32):
403 _jsonmap[chr(x)] = "\u%04x" %x
410 _jsonmap[chr(x)] = "\u%04x" %x
404 for x in xrange(32, 256):
411 for x in xrange(32, 256):
405 c = chr(x)
412 c = chr(x)
406 _jsonmap[c] = c
413 _jsonmap[c] = c
407 _jsonmap['\t'] = '\\t'
414 _jsonmap['\t'] = '\\t'
408 _jsonmap['\n'] = '\\n'
415 _jsonmap['\n'] = '\\n'
409 _jsonmap['\"'] = '\\"'
416 _jsonmap['\"'] = '\\"'
410 _jsonmap['\\'] = '\\\\'
417 _jsonmap['\\'] = '\\\\'
411 _jsonmap['\b'] = '\\b'
418 _jsonmap['\b'] = '\\b'
412 _jsonmap['\f'] = '\\f'
419 _jsonmap['\f'] = '\\f'
413 _jsonmap['\r'] = '\\r'
420 _jsonmap['\r'] = '\\r'
414
421
415 return ''.join(_jsonmap[c] for c in toutf8b(s))
422 return ''.join(_jsonmap[c] for c in toutf8b(s))
416
423
417 _utf8len = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 4]
424 _utf8len = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 4]
418
425
419 def getutf8char(s, pos):
426 def getutf8char(s, pos):
420 '''get the next full utf-8 character in the given string, starting at pos
427 '''get the next full utf-8 character in the given string, starting at pos
421
428
422 Raises a UnicodeError if the given location does not start a valid
429 Raises a UnicodeError if the given location does not start a valid
423 utf-8 character.
430 utf-8 character.
424 '''
431 '''
425
432
426 # find how many bytes to attempt decoding from first nibble
433 # find how many bytes to attempt decoding from first nibble
427 l = _utf8len[ord(s[pos]) >> 4]
434 l = _utf8len[ord(s[pos]) >> 4]
428 if not l: # ascii
435 if not l: # ascii
429 return s[pos]
436 return s[pos]
430
437
431 c = s[pos:pos + l]
438 c = s[pos:pos + l]
432 # validate with attempted decode
439 # validate with attempted decode
433 c.decode("utf-8")
440 c.decode("utf-8")
434 return c
441 return c
435
442
436 def toutf8b(s):
443 def toutf8b(s):
437 '''convert a local, possibly-binary string into UTF-8b
444 '''convert a local, possibly-binary string into UTF-8b
438
445
439 This is intended as a generic method to preserve data when working
446 This is intended as a generic method to preserve data when working
440 with schemes like JSON and XML that have no provision for
447 with schemes like JSON and XML that have no provision for
441 arbitrary byte strings. As Mercurial often doesn't know
448 arbitrary byte strings. As Mercurial often doesn't know
442 what encoding data is in, we use so-called UTF-8b.
449 what encoding data is in, we use so-called UTF-8b.
443
450
444 If a string is already valid UTF-8 (or ASCII), it passes unmodified.
451 If a string is already valid UTF-8 (or ASCII), it passes unmodified.
445 Otherwise, unsupported bytes are mapped to UTF-16 surrogate range,
452 Otherwise, unsupported bytes are mapped to UTF-16 surrogate range,
446 uDC00-uDCFF.
453 uDC00-uDCFF.
447
454
448 Principles of operation:
455 Principles of operation:
449
456
450 - ASCII and UTF-8 data successfully round-trips and is understood
457 - ASCII and UTF-8 data successfully round-trips and is understood
451 by Unicode-oriented clients
458 by Unicode-oriented clients
452 - filenames and file contents in arbitrary other encodings can have
459 - filenames and file contents in arbitrary other encodings can have
453 be round-tripped or recovered by clueful clients
460 be round-tripped or recovered by clueful clients
454 - local strings that have a cached known UTF-8 encoding (aka
461 - local strings that have a cached known UTF-8 encoding (aka
455 localstr) get sent as UTF-8 so Unicode-oriented clients get the
462 localstr) get sent as UTF-8 so Unicode-oriented clients get the
456 Unicode data they want
463 Unicode data they want
457 - because we must preserve UTF-8 bytestring in places such as
464 - because we must preserve UTF-8 bytestring in places such as
458 filenames, metadata can't be roundtripped without help
465 filenames, metadata can't be roundtripped without help
459
466
460 (Note: "UTF-8b" often refers to decoding a mix of valid UTF-8 and
467 (Note: "UTF-8b" often refers to decoding a mix of valid UTF-8 and
461 arbitrary bytes into an internal Unicode format that can be
468 arbitrary bytes into an internal Unicode format that can be
462 re-encoded back into the original. Here we are exposing the
469 re-encoded back into the original. Here we are exposing the
463 internal surrogate encoding as a UTF-8 string.)
470 internal surrogate encoding as a UTF-8 string.)
464 '''
471 '''
465
472
466 if "\xed" not in s:
473 if "\xed" not in s:
467 if isinstance(s, localstr):
474 if isinstance(s, localstr):
468 return s._utf8
475 return s._utf8
469 try:
476 try:
470 s.decode('utf-8')
477 s.decode('utf-8')
471 return s
478 return s
472 except UnicodeDecodeError:
479 except UnicodeDecodeError:
473 pass
480 pass
474
481
475 r = ""
482 r = ""
476 pos = 0
483 pos = 0
477 l = len(s)
484 l = len(s)
478 while pos < l:
485 while pos < l:
479 try:
486 try:
480 c = getutf8char(s, pos)
487 c = getutf8char(s, pos)
481 if "\xed\xb0\x80" <= c <= "\xed\xb3\xbf":
488 if "\xed\xb0\x80" <= c <= "\xed\xb3\xbf":
482 # have to re-escape existing U+DCxx characters
489 # have to re-escape existing U+DCxx characters
483 c = unichr(0xdc00 + ord(s[pos])).encode('utf-8')
490 c = unichr(0xdc00 + ord(s[pos])).encode('utf-8')
484 pos += 1
491 pos += 1
485 else:
492 else:
486 pos += len(c)
493 pos += len(c)
487 except UnicodeDecodeError:
494 except UnicodeDecodeError:
488 c = unichr(0xdc00 + ord(s[pos])).encode('utf-8')
495 c = unichr(0xdc00 + ord(s[pos])).encode('utf-8')
489 pos += 1
496 pos += 1
490 r += c
497 r += c
491 return r
498 return r
492
499
493 def fromutf8b(s):
500 def fromutf8b(s):
494 '''Given a UTF-8b string, return a local, possibly-binary string.
501 '''Given a UTF-8b string, return a local, possibly-binary string.
495
502
496 return the original binary string. This
503 return the original binary string. This
497 is a round-trip process for strings like filenames, but metadata
504 is a round-trip process for strings like filenames, but metadata
498 that's was passed through tolocal will remain in UTF-8.
505 that's was passed through tolocal will remain in UTF-8.
499
506
500 >>> roundtrip = lambda x: fromutf8b(toutf8b(x)) == x
507 >>> roundtrip = lambda x: fromutf8b(toutf8b(x)) == x
501 >>> m = "\\xc3\\xa9\\x99abcd"
508 >>> m = "\\xc3\\xa9\\x99abcd"
502 >>> toutf8b(m)
509 >>> toutf8b(m)
503 '\\xc3\\xa9\\xed\\xb2\\x99abcd'
510 '\\xc3\\xa9\\xed\\xb2\\x99abcd'
504 >>> roundtrip(m)
511 >>> roundtrip(m)
505 True
512 True
506 >>> roundtrip("\\xc2\\xc2\\x80")
513 >>> roundtrip("\\xc2\\xc2\\x80")
507 True
514 True
508 >>> roundtrip("\\xef\\xbf\\xbd")
515 >>> roundtrip("\\xef\\xbf\\xbd")
509 True
516 True
510 >>> roundtrip("\\xef\\xef\\xbf\\xbd")
517 >>> roundtrip("\\xef\\xef\\xbf\\xbd")
511 True
518 True
512 '''
519 '''
513
520
514 # fast path - look for uDxxx prefixes in s
521 # fast path - look for uDxxx prefixes in s
515 if "\xed" not in s:
522 if "\xed" not in s:
516 return s
523 return s
517
524
518 u = s.decode("utf-8")
525 u = s.decode("utf-8")
519 r = ""
526 r = ""
520 for c in u:
527 for c in u:
521 if ord(c) & 0xffff00 == 0xdc00:
528 if ord(c) & 0xffff00 == 0xdc00:
522 r += chr(ord(c) & 0xff)
529 r += chr(ord(c) & 0xff)
523 else:
530 else:
524 r += c.encode("utf-8")
531 r += c.encode("utf-8")
525 return r
532 return r
@@ -1,212 +1,211 b''
1 #require test-repo
1 #require test-repo
2
2
3 $ cd "$TESTDIR"/..
3 $ cd "$TESTDIR"/..
4
4
5 $ hg files 'set:(**.py)' | xargs python contrib/check-py3-compat.py
5 $ hg files 'set:(**.py)' | xargs python contrib/check-py3-compat.py
6 contrib/casesmash.py not using absolute_import
6 contrib/casesmash.py not using absolute_import
7 contrib/check-code.py not using absolute_import
7 contrib/check-code.py not using absolute_import
8 contrib/check-code.py requires print_function
8 contrib/check-code.py requires print_function
9 contrib/check-config.py not using absolute_import
9 contrib/check-config.py not using absolute_import
10 contrib/check-config.py requires print_function
10 contrib/check-config.py requires print_function
11 contrib/debugcmdserver.py not using absolute_import
11 contrib/debugcmdserver.py not using absolute_import
12 contrib/debugcmdserver.py requires print_function
12 contrib/debugcmdserver.py requires print_function
13 contrib/debugshell.py not using absolute_import
13 contrib/debugshell.py not using absolute_import
14 contrib/fixpax.py not using absolute_import
14 contrib/fixpax.py not using absolute_import
15 contrib/fixpax.py requires print_function
15 contrib/fixpax.py requires print_function
16 contrib/hgclient.py not using absolute_import
16 contrib/hgclient.py not using absolute_import
17 contrib/hgclient.py requires print_function
17 contrib/hgclient.py requires print_function
18 contrib/hgfixes/fix_bytes.py not using absolute_import
18 contrib/hgfixes/fix_bytes.py not using absolute_import
19 contrib/hgfixes/fix_bytesmod.py not using absolute_import
19 contrib/hgfixes/fix_bytesmod.py not using absolute_import
20 contrib/hgfixes/fix_leftover_imports.py not using absolute_import
20 contrib/hgfixes/fix_leftover_imports.py not using absolute_import
21 contrib/import-checker.py not using absolute_import
21 contrib/import-checker.py not using absolute_import
22 contrib/import-checker.py requires print_function
22 contrib/import-checker.py requires print_function
23 contrib/memory.py not using absolute_import
23 contrib/memory.py not using absolute_import
24 contrib/perf.py not using absolute_import
24 contrib/perf.py not using absolute_import
25 contrib/python-hook-examples.py not using absolute_import
25 contrib/python-hook-examples.py not using absolute_import
26 contrib/revsetbenchmarks.py not using absolute_import
26 contrib/revsetbenchmarks.py not using absolute_import
27 contrib/revsetbenchmarks.py requires print_function
27 contrib/revsetbenchmarks.py requires print_function
28 contrib/showstack.py not using absolute_import
28 contrib/showstack.py not using absolute_import
29 contrib/synthrepo.py not using absolute_import
29 contrib/synthrepo.py not using absolute_import
30 contrib/win32/hgwebdir_wsgi.py not using absolute_import
30 contrib/win32/hgwebdir_wsgi.py not using absolute_import
31 doc/check-seclevel.py not using absolute_import
31 doc/check-seclevel.py not using absolute_import
32 doc/gendoc.py not using absolute_import
32 doc/gendoc.py not using absolute_import
33 doc/hgmanpage.py not using absolute_import
33 doc/hgmanpage.py not using absolute_import
34 hgext/__init__.py not using absolute_import
34 hgext/__init__.py not using absolute_import
35 hgext/acl.py not using absolute_import
35 hgext/acl.py not using absolute_import
36 hgext/blackbox.py not using absolute_import
36 hgext/blackbox.py not using absolute_import
37 hgext/bugzilla.py not using absolute_import
37 hgext/bugzilla.py not using absolute_import
38 hgext/censor.py not using absolute_import
38 hgext/censor.py not using absolute_import
39 hgext/children.py not using absolute_import
39 hgext/children.py not using absolute_import
40 hgext/churn.py not using absolute_import
40 hgext/churn.py not using absolute_import
41 hgext/clonebundles.py not using absolute_import
41 hgext/clonebundles.py not using absolute_import
42 hgext/color.py not using absolute_import
42 hgext/color.py not using absolute_import
43 hgext/convert/__init__.py not using absolute_import
43 hgext/convert/__init__.py not using absolute_import
44 hgext/convert/bzr.py not using absolute_import
44 hgext/convert/bzr.py not using absolute_import
45 hgext/convert/common.py not using absolute_import
45 hgext/convert/common.py not using absolute_import
46 hgext/convert/convcmd.py not using absolute_import
46 hgext/convert/convcmd.py not using absolute_import
47 hgext/convert/cvs.py not using absolute_import
47 hgext/convert/cvs.py not using absolute_import
48 hgext/convert/cvsps.py not using absolute_import
48 hgext/convert/cvsps.py not using absolute_import
49 hgext/convert/darcs.py not using absolute_import
49 hgext/convert/darcs.py not using absolute_import
50 hgext/convert/filemap.py not using absolute_import
50 hgext/convert/filemap.py not using absolute_import
51 hgext/convert/git.py not using absolute_import
51 hgext/convert/git.py not using absolute_import
52 hgext/convert/gnuarch.py not using absolute_import
52 hgext/convert/gnuarch.py not using absolute_import
53 hgext/convert/hg.py not using absolute_import
53 hgext/convert/hg.py not using absolute_import
54 hgext/convert/monotone.py not using absolute_import
54 hgext/convert/monotone.py not using absolute_import
55 hgext/convert/p4.py not using absolute_import
55 hgext/convert/p4.py not using absolute_import
56 hgext/convert/subversion.py not using absolute_import
56 hgext/convert/subversion.py not using absolute_import
57 hgext/convert/transport.py not using absolute_import
57 hgext/convert/transport.py not using absolute_import
58 hgext/eol.py not using absolute_import
58 hgext/eol.py not using absolute_import
59 hgext/extdiff.py not using absolute_import
59 hgext/extdiff.py not using absolute_import
60 hgext/factotum.py not using absolute_import
60 hgext/factotum.py not using absolute_import
61 hgext/fetch.py not using absolute_import
61 hgext/fetch.py not using absolute_import
62 hgext/gpg.py not using absolute_import
62 hgext/gpg.py not using absolute_import
63 hgext/graphlog.py not using absolute_import
63 hgext/graphlog.py not using absolute_import
64 hgext/hgcia.py not using absolute_import
64 hgext/hgcia.py not using absolute_import
65 hgext/hgk.py not using absolute_import
65 hgext/hgk.py not using absolute_import
66 hgext/highlight/__init__.py not using absolute_import
66 hgext/highlight/__init__.py not using absolute_import
67 hgext/highlight/highlight.py not using absolute_import
67 hgext/highlight/highlight.py not using absolute_import
68 hgext/histedit.py not using absolute_import
68 hgext/histedit.py not using absolute_import
69 hgext/keyword.py not using absolute_import
69 hgext/keyword.py not using absolute_import
70 hgext/largefiles/__init__.py not using absolute_import
70 hgext/largefiles/__init__.py not using absolute_import
71 hgext/largefiles/basestore.py not using absolute_import
71 hgext/largefiles/basestore.py not using absolute_import
72 hgext/largefiles/lfcommands.py not using absolute_import
72 hgext/largefiles/lfcommands.py not using absolute_import
73 hgext/largefiles/lfutil.py not using absolute_import
73 hgext/largefiles/lfutil.py not using absolute_import
74 hgext/largefiles/localstore.py not using absolute_import
74 hgext/largefiles/localstore.py not using absolute_import
75 hgext/largefiles/overrides.py not using absolute_import
75 hgext/largefiles/overrides.py not using absolute_import
76 hgext/largefiles/proto.py not using absolute_import
76 hgext/largefiles/proto.py not using absolute_import
77 hgext/largefiles/remotestore.py not using absolute_import
77 hgext/largefiles/remotestore.py not using absolute_import
78 hgext/largefiles/reposetup.py not using absolute_import
78 hgext/largefiles/reposetup.py not using absolute_import
79 hgext/largefiles/uisetup.py not using absolute_import
79 hgext/largefiles/uisetup.py not using absolute_import
80 hgext/largefiles/wirestore.py not using absolute_import
80 hgext/largefiles/wirestore.py not using absolute_import
81 hgext/mq.py not using absolute_import
81 hgext/mq.py not using absolute_import
82 hgext/notify.py not using absolute_import
82 hgext/notify.py not using absolute_import
83 hgext/pager.py not using absolute_import
83 hgext/pager.py not using absolute_import
84 hgext/patchbomb.py not using absolute_import
84 hgext/patchbomb.py not using absolute_import
85 hgext/purge.py not using absolute_import
85 hgext/purge.py not using absolute_import
86 hgext/rebase.py not using absolute_import
86 hgext/rebase.py not using absolute_import
87 hgext/record.py not using absolute_import
87 hgext/record.py not using absolute_import
88 hgext/relink.py not using absolute_import
88 hgext/relink.py not using absolute_import
89 hgext/schemes.py not using absolute_import
89 hgext/schemes.py not using absolute_import
90 hgext/share.py not using absolute_import
90 hgext/share.py not using absolute_import
91 hgext/shelve.py not using absolute_import
91 hgext/shelve.py not using absolute_import
92 hgext/strip.py not using absolute_import
92 hgext/strip.py not using absolute_import
93 hgext/transplant.py not using absolute_import
93 hgext/transplant.py not using absolute_import
94 hgext/win32mbcs.py not using absolute_import
94 hgext/win32mbcs.py not using absolute_import
95 hgext/win32text.py not using absolute_import
95 hgext/win32text.py not using absolute_import
96 hgext/zeroconf/Zeroconf.py not using absolute_import
96 hgext/zeroconf/Zeroconf.py not using absolute_import
97 hgext/zeroconf/Zeroconf.py requires print_function
97 hgext/zeroconf/Zeroconf.py requires print_function
98 hgext/zeroconf/__init__.py not using absolute_import
98 hgext/zeroconf/__init__.py not using absolute_import
99 i18n/check-translation.py not using absolute_import
99 i18n/check-translation.py not using absolute_import
100 i18n/polib.py not using absolute_import
100 i18n/polib.py not using absolute_import
101 mercurial/byterange.py not using absolute_import
101 mercurial/byterange.py not using absolute_import
102 mercurial/cmdutil.py not using absolute_import
102 mercurial/cmdutil.py not using absolute_import
103 mercurial/commands.py not using absolute_import
103 mercurial/commands.py not using absolute_import
104 mercurial/context.py not using absolute_import
104 mercurial/context.py not using absolute_import
105 mercurial/dirstate.py not using absolute_import
105 mercurial/dirstate.py not using absolute_import
106 mercurial/dispatch.py requires print_function
106 mercurial/dispatch.py requires print_function
107 mercurial/encoding.py not using absolute_import
108 mercurial/exchange.py not using absolute_import
107 mercurial/exchange.py not using absolute_import
109 mercurial/help.py not using absolute_import
108 mercurial/help.py not using absolute_import
110 mercurial/httpclient/__init__.py not using absolute_import
109 mercurial/httpclient/__init__.py not using absolute_import
111 mercurial/httpclient/_readers.py not using absolute_import
110 mercurial/httpclient/_readers.py not using absolute_import
112 mercurial/httpclient/socketutil.py not using absolute_import
111 mercurial/httpclient/socketutil.py not using absolute_import
113 mercurial/httpconnection.py not using absolute_import
112 mercurial/httpconnection.py not using absolute_import
114 mercurial/keepalive.py not using absolute_import
113 mercurial/keepalive.py not using absolute_import
115 mercurial/keepalive.py requires print_function
114 mercurial/keepalive.py requires print_function
116 mercurial/localrepo.py not using absolute_import
115 mercurial/localrepo.py not using absolute_import
117 mercurial/lsprof.py requires print_function
116 mercurial/lsprof.py requires print_function
118 mercurial/lsprofcalltree.py not using absolute_import
117 mercurial/lsprofcalltree.py not using absolute_import
119 mercurial/lsprofcalltree.py requires print_function
118 mercurial/lsprofcalltree.py requires print_function
120 mercurial/mail.py requires print_function
119 mercurial/mail.py requires print_function
121 mercurial/manifest.py not using absolute_import
120 mercurial/manifest.py not using absolute_import
122 mercurial/mdiff.py not using absolute_import
121 mercurial/mdiff.py not using absolute_import
123 mercurial/patch.py not using absolute_import
122 mercurial/patch.py not using absolute_import
124 mercurial/pvec.py not using absolute_import
123 mercurial/pvec.py not using absolute_import
125 mercurial/py3kcompat.py not using absolute_import
124 mercurial/py3kcompat.py not using absolute_import
126 mercurial/revlog.py not using absolute_import
125 mercurial/revlog.py not using absolute_import
127 mercurial/scmposix.py not using absolute_import
126 mercurial/scmposix.py not using absolute_import
128 mercurial/scmutil.py not using absolute_import
127 mercurial/scmutil.py not using absolute_import
129 mercurial/scmwindows.py not using absolute_import
128 mercurial/scmwindows.py not using absolute_import
130 mercurial/similar.py not using absolute_import
129 mercurial/similar.py not using absolute_import
131 mercurial/store.py not using absolute_import
130 mercurial/store.py not using absolute_import
132 mercurial/util.py not using absolute_import
131 mercurial/util.py not using absolute_import
133 mercurial/windows.py not using absolute_import
132 mercurial/windows.py not using absolute_import
134 setup.py not using absolute_import
133 setup.py not using absolute_import
135 tests/filterpyflakes.py requires print_function
134 tests/filterpyflakes.py requires print_function
136 tests/generate-working-copy-states.py requires print_function
135 tests/generate-working-copy-states.py requires print_function
137 tests/get-with-headers.py requires print_function
136 tests/get-with-headers.py requires print_function
138 tests/heredoctest.py requires print_function
137 tests/heredoctest.py requires print_function
139 tests/hypothesishelpers.py not using absolute_import
138 tests/hypothesishelpers.py not using absolute_import
140 tests/hypothesishelpers.py requires print_function
139 tests/hypothesishelpers.py requires print_function
141 tests/killdaemons.py not using absolute_import
140 tests/killdaemons.py not using absolute_import
142 tests/md5sum.py not using absolute_import
141 tests/md5sum.py not using absolute_import
143 tests/mockblackbox.py not using absolute_import
142 tests/mockblackbox.py not using absolute_import
144 tests/printenv.py not using absolute_import
143 tests/printenv.py not using absolute_import
145 tests/readlink.py not using absolute_import
144 tests/readlink.py not using absolute_import
146 tests/readlink.py requires print_function
145 tests/readlink.py requires print_function
147 tests/revlog-formatv0.py not using absolute_import
146 tests/revlog-formatv0.py not using absolute_import
148 tests/run-tests.py not using absolute_import
147 tests/run-tests.py not using absolute_import
149 tests/seq.py not using absolute_import
148 tests/seq.py not using absolute_import
150 tests/seq.py requires print_function
149 tests/seq.py requires print_function
151 tests/silenttestrunner.py not using absolute_import
150 tests/silenttestrunner.py not using absolute_import
152 tests/silenttestrunner.py requires print_function
151 tests/silenttestrunner.py requires print_function
153 tests/sitecustomize.py not using absolute_import
152 tests/sitecustomize.py not using absolute_import
154 tests/svn-safe-append.py not using absolute_import
153 tests/svn-safe-append.py not using absolute_import
155 tests/svnxml.py not using absolute_import
154 tests/svnxml.py not using absolute_import
156 tests/test-ancestor.py requires print_function
155 tests/test-ancestor.py requires print_function
157 tests/test-atomictempfile.py not using absolute_import
156 tests/test-atomictempfile.py not using absolute_import
158 tests/test-batching.py not using absolute_import
157 tests/test-batching.py not using absolute_import
159 tests/test-batching.py requires print_function
158 tests/test-batching.py requires print_function
160 tests/test-bdiff.py not using absolute_import
159 tests/test-bdiff.py not using absolute_import
161 tests/test-bdiff.py requires print_function
160 tests/test-bdiff.py requires print_function
162 tests/test-context.py not using absolute_import
161 tests/test-context.py not using absolute_import
163 tests/test-context.py requires print_function
162 tests/test-context.py requires print_function
164 tests/test-demandimport.py not using absolute_import
163 tests/test-demandimport.py not using absolute_import
165 tests/test-demandimport.py requires print_function
164 tests/test-demandimport.py requires print_function
166 tests/test-dispatch.py not using absolute_import
165 tests/test-dispatch.py not using absolute_import
167 tests/test-dispatch.py requires print_function
166 tests/test-dispatch.py requires print_function
168 tests/test-doctest.py not using absolute_import
167 tests/test-doctest.py not using absolute_import
169 tests/test-duplicateoptions.py not using absolute_import
168 tests/test-duplicateoptions.py not using absolute_import
170 tests/test-duplicateoptions.py requires print_function
169 tests/test-duplicateoptions.py requires print_function
171 tests/test-filecache.py not using absolute_import
170 tests/test-filecache.py not using absolute_import
172 tests/test-filecache.py requires print_function
171 tests/test-filecache.py requires print_function
173 tests/test-filelog.py not using absolute_import
172 tests/test-filelog.py not using absolute_import
174 tests/test-filelog.py requires print_function
173 tests/test-filelog.py requires print_function
175 tests/test-hg-parseurl.py not using absolute_import
174 tests/test-hg-parseurl.py not using absolute_import
176 tests/test-hg-parseurl.py requires print_function
175 tests/test-hg-parseurl.py requires print_function
177 tests/test-hgweb-auth.py not using absolute_import
176 tests/test-hgweb-auth.py not using absolute_import
178 tests/test-hgweb-auth.py requires print_function
177 tests/test-hgweb-auth.py requires print_function
179 tests/test-hgwebdir-paths.py not using absolute_import
178 tests/test-hgwebdir-paths.py not using absolute_import
180 tests/test-hybridencode.py not using absolute_import
179 tests/test-hybridencode.py not using absolute_import
181 tests/test-hybridencode.py requires print_function
180 tests/test-hybridencode.py requires print_function
182 tests/test-lrucachedict.py not using absolute_import
181 tests/test-lrucachedict.py not using absolute_import
183 tests/test-lrucachedict.py requires print_function
182 tests/test-lrucachedict.py requires print_function
184 tests/test-manifest.py not using absolute_import
183 tests/test-manifest.py not using absolute_import
185 tests/test-minirst.py not using absolute_import
184 tests/test-minirst.py not using absolute_import
186 tests/test-minirst.py requires print_function
185 tests/test-minirst.py requires print_function
187 tests/test-parseindex2.py not using absolute_import
186 tests/test-parseindex2.py not using absolute_import
188 tests/test-parseindex2.py requires print_function
187 tests/test-parseindex2.py requires print_function
189 tests/test-pathencode.py not using absolute_import
188 tests/test-pathencode.py not using absolute_import
190 tests/test-pathencode.py requires print_function
189 tests/test-pathencode.py requires print_function
191 tests/test-propertycache.py not using absolute_import
190 tests/test-propertycache.py not using absolute_import
192 tests/test-propertycache.py requires print_function
191 tests/test-propertycache.py requires print_function
193 tests/test-revlog-ancestry.py not using absolute_import
192 tests/test-revlog-ancestry.py not using absolute_import
194 tests/test-revlog-ancestry.py requires print_function
193 tests/test-revlog-ancestry.py requires print_function
195 tests/test-run-tests.py not using absolute_import
194 tests/test-run-tests.py not using absolute_import
196 tests/test-simplemerge.py not using absolute_import
195 tests/test-simplemerge.py not using absolute_import
197 tests/test-status-inprocess.py not using absolute_import
196 tests/test-status-inprocess.py not using absolute_import
198 tests/test-status-inprocess.py requires print_function
197 tests/test-status-inprocess.py requires print_function
199 tests/test-symlink-os-yes-fs-no.py not using absolute_import
198 tests/test-symlink-os-yes-fs-no.py not using absolute_import
200 tests/test-trusted.py not using absolute_import
199 tests/test-trusted.py not using absolute_import
201 tests/test-trusted.py requires print_function
200 tests/test-trusted.py requires print_function
202 tests/test-ui-color.py not using absolute_import
201 tests/test-ui-color.py not using absolute_import
203 tests/test-ui-color.py requires print_function
202 tests/test-ui-color.py requires print_function
204 tests/test-ui-config.py not using absolute_import
203 tests/test-ui-config.py not using absolute_import
205 tests/test-ui-config.py requires print_function
204 tests/test-ui-config.py requires print_function
206 tests/test-ui-verbosity.py not using absolute_import
205 tests/test-ui-verbosity.py not using absolute_import
207 tests/test-ui-verbosity.py requires print_function
206 tests/test-ui-verbosity.py requires print_function
208 tests/test-url.py not using absolute_import
207 tests/test-url.py not using absolute_import
209 tests/test-url.py requires print_function
208 tests/test-url.py requires print_function
210 tests/test-walkrepo.py requires print_function
209 tests/test-walkrepo.py requires print_function
211 tests/test-wireproto.py requires print_function
210 tests/test-wireproto.py requires print_function
212 tests/tinyproxy.py requires print_function
211 tests/tinyproxy.py requires print_function
General Comments 0
You need to be logged in to leave comments. Login now