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