comparison mercurial/__init__.py @ 43090:1f339b503a40

py3: manually import pycompat.delattr where it is needed And with this change, we no longer need the auto-inserted import statement in the source transformer, so it has been removed! Differential Revision: https://phab.mercurial-scm.org/D7010
author Gregory Szorc <gregory.szorc@gmail.com>
date Sun, 06 Oct 2019 16:58:55 -0400
parents c59eb1560c44
children 127cc1f72e70
comparison
equal deleted inserted replaced
43089:c59eb1560c44 43090:1f339b503a40
99 its changes do not necessarily match the output token stream. 99 its changes do not necessarily match the output token stream.
100 100
101 REMEMBER TO CHANGE ``BYTECODEHEADER`` WHEN CHANGING THIS FUNCTION 101 REMEMBER TO CHANGE ``BYTECODEHEADER`` WHEN CHANGING THIS FUNCTION
102 OR CACHED FILES WON'T GET INVALIDATED PROPERLY. 102 OR CACHED FILES WON'T GET INVALIDATED PROPERLY.
103 """ 103 """
104 futureimpline = False
105
106 # The following utility functions access the tokens list and i index of 104 # The following utility functions access the tokens list and i index of
107 # the for i, t enumerate(tokens) loop below 105 # the for i, t enumerate(tokens) loop below
108 def _isop(j, *o): 106 def _isop(j, *o):
109 """Assert that tokens[j] is an OP with one of the given values""" 107 """Assert that tokens[j] is an OP with one of the given values"""
110 try: 108 try:
151 st = tokens[j] 149 st = tokens[j]
152 if st.type == token.STRING and st.string.startswith(("'", '"')): 150 if st.type == token.STRING and st.string.startswith(("'", '"')):
153 tokens[j] = st._replace(string='u%s' % st.string) 151 tokens[j] = st._replace(string='u%s' % st.string)
154 152
155 for i, t in enumerate(tokens): 153 for i, t in enumerate(tokens):
156 # Insert compatibility imports at "from __future__ import" line.
157 # No '\n' should be added to preserve line numbers.
158 if (
159 t.type == token.NAME
160 and t.string == 'import'
161 and all(u.type == token.NAME for u in tokens[i - 2 : i])
162 and [u.string for u in tokens[i - 2 : i]]
163 == ['from', '__future__']
164 ):
165 futureimpline = True
166 if t.type == token.NEWLINE and futureimpline:
167 futureimpline = False
168 if fullname == 'mercurial.pycompat':
169 yield t
170 continue
171 r, c = t.start
172 l = (
173 b'; from mercurial.pycompat import '
174 b'delattr\n'
175 )
176 for u in tokenize.tokenize(io.BytesIO(l).readline):
177 if u.type in (tokenize.ENCODING, token.ENDMARKER):
178 continue
179 yield u._replace(
180 start=(r, c + u.start[1]), end=(r, c + u.end[1])
181 )
182 continue
183
184 # This looks like a function call. 154 # This looks like a function call.
185 if t.type == token.NAME and _isop(i + 1, '('): 155 if t.type == token.NAME and _isop(i + 1, '('):
186 fn = t.string 156 fn = t.string
187 157
188 # *attr() builtins don't accept byte strings to 2nd argument. 158 # *attr() builtins don't accept byte strings to 2nd argument.
218 188
219 # Header to add to bytecode files. This MUST be changed when 189 # Header to add to bytecode files. This MUST be changed when
220 # ``replacetoken`` or any mechanism that changes semantics of module 190 # ``replacetoken`` or any mechanism that changes semantics of module
221 # loading is changed. Otherwise cached bytecode may get loaded without 191 # loading is changed. Otherwise cached bytecode may get loaded without
222 # the new transformation mechanisms applied. 192 # the new transformation mechanisms applied.
223 BYTECODEHEADER = b'HG\x00\x11' 193 BYTECODEHEADER = b'HG\x00\x12'
224 194
225 class hgloader(importlib.machinery.SourceFileLoader): 195 class hgloader(importlib.machinery.SourceFileLoader):
226 """Custom module loader that transforms source code. 196 """Custom module loader that transforms source code.
227 197
228 When the source code is converted to a code object, we transform 198 When the source code is converted to a code object, we transform