Mercurial > public > mercurial-scm > hg-stable
comparison contrib/byteify-strings.py @ 38393:b704da9a9dda
byteify-strings: drop import-line hack
This is ugly, and valid only for Python 3. We'll need to find a different
way if we want to get rid of the code transformer at all.
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Thu, 31 May 2018 22:31:37 +0900 |
parents | 9f42e4a83676 |
children | f701bc936e7f |
comparison
equal
deleted
inserted
replaced
38392:9f42e4a83676 | 38393:b704da9a9dda |
---|---|
10 from __future__ import absolute_import | 10 from __future__ import absolute_import |
11 | 11 |
12 import argparse | 12 import argparse |
13 import contextlib | 13 import contextlib |
14 import errno | 14 import errno |
15 import io | |
16 import os | 15 import os |
17 import sys | 16 import sys |
18 import tempfile | 17 import tempfile |
19 import token | 18 import token |
20 import tokenize | 19 import tokenize |
21 | 20 |
22 if True: | 21 if True: |
23 def replacetokens(tokens, fullname): | 22 def replacetokens(tokens): |
24 """Transform a stream of tokens from raw to Python 3. | 23 """Transform a stream of tokens from raw to Python 3. |
25 | 24 |
26 Returns a generator of possibly rewritten tokens. | 25 Returns a generator of possibly rewritten tokens. |
27 | 26 |
28 The input token list may be mutated as part of processing. However, | 27 The input token list may be mutated as part of processing. However, |
29 its changes do not necessarily match the output token stream. | 28 its changes do not necessarily match the output token stream. |
30 """ | 29 """ |
31 futureimpline = False | |
32 | |
33 # The following utility functions access the tokens list and i index of | 30 # The following utility functions access the tokens list and i index of |
34 # the for i, t enumerate(tokens) loop below | 31 # the for i, t enumerate(tokens) loop below |
35 def _isop(j, *o): | 32 def _isop(j, *o): |
36 """Assert that tokens[j] is an OP with one of the given values""" | 33 """Assert that tokens[j] is an OP with one of the given values""" |
37 try: | 34 try: |
109 | 106 |
110 # String literal. Prefix to make a b'' string. | 107 # String literal. Prefix to make a b'' string. |
111 yield t._replace(string='b%s' % t.string) | 108 yield t._replace(string='b%s' % t.string) |
112 continue | 109 continue |
113 | 110 |
114 # Insert compatibility imports at "from __future__ import" line. | |
115 # No '\n' should be added to preserve line numbers. | |
116 if (t.type == token.NAME and t.string == 'import' and | |
117 all(u.type == token.NAME for u in tokens[i - 2:i]) and | |
118 [u.string for u in tokens[i - 2:i]] == ['from', '__future__']): | |
119 futureimpline = True | |
120 if t.type == token.NEWLINE and futureimpline: | |
121 futureimpline = False | |
122 if fullname == 'mercurial.pycompat': | |
123 yield t | |
124 continue | |
125 r, c = t.start | |
126 l = (b'; from mercurial.pycompat import ' | |
127 b'delattr, getattr, hasattr, setattr, xrange, ' | |
128 b'open, unicode\n') | |
129 for u in tokenize.tokenize(io.BytesIO(l).readline): | |
130 if u.type in (tokenize.ENCODING, token.ENDMARKER): | |
131 continue | |
132 yield u._replace( | |
133 start=(r, c + u.start[1]), end=(r, c + u.end[1])) | |
134 continue | |
135 | |
136 # This looks like a function call. | 111 # This looks like a function call. |
137 if t.type == token.NAME and _isop(i + 1, '('): | 112 if t.type == token.NAME and _isop(i + 1, '('): |
138 fn = t.string | 113 fn = t.string |
139 | 114 |
140 # *attr() builtins don't accept byte strings to 2nd argument. | 115 # *attr() builtins don't accept byte strings to 2nd argument. |
161 # Emit unmodified token. | 136 # Emit unmodified token. |
162 yield t | 137 yield t |
163 | 138 |
164 def process(fin, fout): | 139 def process(fin, fout): |
165 tokens = tokenize.tokenize(fin.readline) | 140 tokens = tokenize.tokenize(fin.readline) |
166 tokens = replacetokens(list(tokens), fullname='<dummy>') | 141 tokens = replacetokens(list(tokens)) |
167 fout.write(tokenize.untokenize(tokens)) | 142 fout.write(tokenize.untokenize(tokens)) |
168 | 143 |
169 def tryunlink(fname): | 144 def tryunlink(fname): |
170 try: | 145 try: |
171 os.unlink(fname) | 146 os.unlink(fname) |