Mercurial > hg
comparison mercurial/__init__.py @ 30118:c19266edd93e
py3: a second argument to open can't be bytes
This fixes open(filename, 'r'), open(filename, 'w'), etc. calls. In Python
3, that second argument *must* be a string, you can't use bytes.
The fix is the same as used with getattr() (where the second argument must
also always be a string); in the tokenizer, where we detect calls, if there
is something that looks like a call to open (and is not an attribute, so
the previous token is not a "." dot) then make sure that that second
argument is not converted to a `bytes` object instead.
There is some remaining issue where the current transformer will also rewrite
open(f('foo')).
However this also affect function for which we perform similar rewrite
('getattr', 'setattr', 'hasattr', 'safehasattr') and will be dealt with in a
follow up.
author | Martijn Pieters <mjpieters@fb.com> |
---|---|
date | Sun, 09 Oct 2016 14:10:01 +0200 |
parents | eaaedad68011 |
children | 423377290a3a |
comparison
equal
deleted
inserted
replaced
30117:b85fa6bf298b | 30118:c19266edd93e |
---|---|
303 tokens[j + 2] = rt | 303 tokens[j + 2] = rt |
304 j = j + 2 | 304 j = j + 2 |
305 except IndexError: | 305 except IndexError: |
306 pass | 306 pass |
307 | 307 |
308 # Bare open call (not an attribute on something else) | |
309 if (fn == 'open' and not (prevtoken.type == token.OP and | |
310 prevtoken.string == '.')): | |
311 try: | |
312 # (NAME, 'open') | |
313 # (OP, '(') | |
314 # (NAME|STRING, 'filename') | |
315 # (OP, ',') | |
316 # (NAME|STRING, mode) | |
317 st = tokens[i + 4] | |
318 if (st.type == token.STRING and | |
319 st.string[0] in ("'", '"')): | |
320 rt = tokenize.TokenInfo(st.type, 'u%s' % st.string, | |
321 st.start, st.end, st.line) | |
322 tokens[i + 4] = rt | |
323 except IndexError: | |
324 pass | |
325 | |
308 # It changes iteritems to items as iteritems is not | 326 # It changes iteritems to items as iteritems is not |
309 # present in Python 3 world. | 327 # present in Python 3 world. |
310 if fn == 'iteritems': | 328 if fn == 'iteritems': |
311 yield tokenize.TokenInfo(t.type, 'items', | 329 yield tokenize.TokenInfo(t.type, 'items', |
312 t.start, t.end, t.line) | 330 t.start, t.end, t.line) |
317 | 335 |
318 # Header to add to bytecode files. This MUST be changed when | 336 # Header to add to bytecode files. This MUST be changed when |
319 # ``replacetoken`` or any mechanism that changes semantics of module | 337 # ``replacetoken`` or any mechanism that changes semantics of module |
320 # loading is changed. Otherwise cached bytecode may get loaded without | 338 # loading is changed. Otherwise cached bytecode may get loaded without |
321 # the new transformation mechanisms applied. | 339 # the new transformation mechanisms applied. |
322 BYTECODEHEADER = b'HG\x00\x04' | 340 BYTECODEHEADER = b'HG\x00\x05' |
323 | 341 |
324 class hgloader(importlib.machinery.SourceFileLoader): | 342 class hgloader(importlib.machinery.SourceFileLoader): |
325 """Custom module loader that transforms source code. | 343 """Custom module loader that transforms source code. |
326 | 344 |
327 When the source code is converted to a code object, we transform | 345 When the source code is converted to a code object, we transform |