mirror of
https://github.com/facebook/sapling.git
synced 2024-10-10 00:45:18 +03:00
f1c575a099
Summary: This check is useful and detects real errors (ex. fbconduit). Unfortunately `arc lint` will run it with both py2 and py3 so a lot of py2 builtins will still be warned. I didn't find a clean way to disable py3 check. So this diff tries to fix them. For `xrange`, the change was done by a script: ``` import sys import redbaron headertypes = {'comment', 'endl', 'from_import', 'import', 'string', 'assignment', 'atomtrailers'} xrangefix = '''try: xrange(0) except NameError: xrange = range ''' def isxrange(x): try: return x[0].value == 'xrange' except Exception: return False def main(argv): for i, path in enumerate(argv): print('(%d/%d) scanning %s' % (i + 1, len(argv), path)) content = open(path).read() try: red = redbaron.RedBaron(content) except Exception: print(' warning: failed to parse') continue hasxrange = red.find('atomtrailersnode', value=isxrange) hasxrangefix = 'xrange = range' in content if hasxrangefix or not hasxrange: print(' no need to change') continue # find a place to insert the compatibility statement changed = False for node in red: if node.type in headertypes: continue # node.insert_before is an easier API, but it has bugs changing # other "finally" and "except" positions. So do the insert # manually. # # node.insert_before(xrangefix) line = node.absolute_bounding_box.top_left.line - 1 lines = content.splitlines(1) content = ''.join(lines[:line]) + xrangefix + ''.join(lines[line:]) changed = True break if changed: # "content" is faster than "red.dumps()" open(path, 'w').write(content) print(' updated') if __name__ == "__main__": sys.exit(main(sys.argv[1:])) ``` For other py2 builtins that do not have a py3 equivalent, some `# noqa` were added as a workaround for now. Reviewed By: DurhamG Differential Revision: D6934535 fbshipit-source-id: 546b62830af144bc8b46788d2e0fd00496838939
162 lines
5.5 KiB
Python
162 lines
5.5 KiB
Python
# Copyright 2016-present Facebook. All Rights Reserved.
|
|
#
|
|
# format: defines the format used to output annotate result
|
|
#
|
|
# This software may be used and distributed according to the terms of the
|
|
# GNU General Public License version 2 or any later version.
|
|
|
|
from mercurial import (
|
|
encoding,
|
|
node,
|
|
templatefilters,
|
|
util,
|
|
)
|
|
|
|
# imitating mercurial.commands.annotate, not using the vanilla formatter since
|
|
# the data structures are a bit different, and we have some fast paths.
|
|
try:
|
|
xrange(0)
|
|
except NameError:
|
|
xrange = range
|
|
|
|
class defaultformatter(object):
|
|
"""the default formatter that does leftpad and support some common flags"""
|
|
|
|
def __init__(self, ui, repo, opts):
|
|
self.ui = ui
|
|
self.opts = opts
|
|
|
|
if ui.quiet:
|
|
datefunc = util.shortdate
|
|
else:
|
|
datefunc = util.datestr
|
|
datefunc = util.cachefunc(datefunc)
|
|
getctx = util.cachefunc(lambda x: repo[x[0]])
|
|
hexfunc = self._hexfunc
|
|
|
|
# special handling working copy "changeset" and "rev" functions
|
|
if self.opts.get('rev') == 'wdir()':
|
|
orig = hexfunc
|
|
hexfunc = lambda x: None if x is None else orig(x)
|
|
wnode = hexfunc(repo[None].p1().node()) + '+'
|
|
wrev = str(repo[None].p1().rev())
|
|
wrevpad = ''
|
|
if not opts.get('changeset'): # only show + if changeset is hidden
|
|
wrev += '+'
|
|
wrevpad = ' '
|
|
revenc = lambda x: wrev if x is None else str(x) + wrevpad
|
|
csetenc = lambda x: wnode if x is None else str(x) + ' '
|
|
else:
|
|
revenc = csetenc = str
|
|
|
|
# opt name, separator, raw value (for json/plain), encoder (for plain)
|
|
opmap = [('user', ' ', lambda x: getctx(x).user(), ui.shortuser),
|
|
('number', ' ', lambda x: getctx(x).rev(), revenc),
|
|
('changeset', ' ', lambda x: hexfunc(x[0]), csetenc),
|
|
('date', ' ', lambda x: getctx(x).date(), datefunc),
|
|
('file', ' ', lambda x: x[2], str),
|
|
('line_number', ':', lambda x: x[1] + 1, str)]
|
|
fieldnamemap = {'number': 'rev', 'changeset': 'node'}
|
|
funcmap = [(get, sep, fieldnamemap.get(op, op), enc)
|
|
for op, sep, get, enc in opmap
|
|
if opts.get(op)]
|
|
# no separator for first column
|
|
funcmap[0] = list(funcmap[0])
|
|
funcmap[0][1] = ''
|
|
self.funcmap = funcmap
|
|
|
|
def write(self, annotatedresult, lines=None, existinglines=None):
|
|
"""(annotateresult, [str], set([rev, linenum])) -> None. write output.
|
|
annotateresult can be [(node, linenum, path)], or [(node, linenum)]
|
|
"""
|
|
pieces = [] # [[str]]
|
|
maxwidths = [] # [int]
|
|
|
|
# calculate padding
|
|
for f, sep, name, enc in self.funcmap:
|
|
l = [enc(f(x)) for x in annotatedresult]
|
|
pieces.append(l)
|
|
if name in ['node', 'date']: # node and date has fixed size
|
|
l = l[:1]
|
|
widths = map(encoding.colwidth, set(l))
|
|
maxwidth = (max(widths) if widths else 0)
|
|
maxwidths.append(maxwidth)
|
|
|
|
# buffered output
|
|
result = ''
|
|
for i in xrange(len(annotatedresult)):
|
|
for j, p in enumerate(pieces):
|
|
sep = self.funcmap[j][1]
|
|
padding = ' ' * (maxwidths[j] - len(p[i]))
|
|
result += sep + padding + p[i]
|
|
if lines:
|
|
if existinglines is None:
|
|
result += ': ' + lines[i]
|
|
else: # extra formatting showing whether a line exists
|
|
key = (annotatedresult[i][0], annotatedresult[i][1])
|
|
if key in existinglines:
|
|
result += ': ' + lines[i]
|
|
else:
|
|
result += ': ' + self.ui.label('-' + lines[i],
|
|
'diff.deleted')
|
|
|
|
if result[-1] != '\n':
|
|
result += '\n'
|
|
|
|
self.ui.write(result)
|
|
|
|
@util.propertycache
|
|
def _hexfunc(self):
|
|
if self.ui.debugflag or self.opts.get('long_hash'):
|
|
return node.hex
|
|
else:
|
|
return node.short
|
|
|
|
def end(self):
|
|
pass
|
|
|
|
class jsonformatter(defaultformatter):
|
|
def __init__(self, ui, repo, opts):
|
|
super(jsonformatter, self).__init__(ui, repo, opts)
|
|
self.ui.write('[')
|
|
self.needcomma = False
|
|
|
|
def write(self, annotatedresult, lines=None, existinglines=None):
|
|
if annotatedresult:
|
|
self._writecomma()
|
|
|
|
pieces = [(name, map(f, annotatedresult))
|
|
for f, sep, name, enc in self.funcmap]
|
|
if lines is not None:
|
|
pieces.append(('line', lines))
|
|
pieces.sort()
|
|
|
|
seps = [','] * len(pieces[:-1]) + ['']
|
|
|
|
result = ''
|
|
lasti = len(annotatedresult) - 1
|
|
for i in xrange(len(annotatedresult)):
|
|
result += '\n {\n'
|
|
for j, p in enumerate(pieces):
|
|
k, vs = p
|
|
result += (' "%s": %s%s\n'
|
|
% (k, templatefilters.json(vs[i], paranoid=False),
|
|
seps[j]))
|
|
result += ' }%s' % ('' if i == lasti else ',')
|
|
if lasti >= 0:
|
|
self.needcomma = True
|
|
|
|
self.ui.write(result)
|
|
|
|
def _writecomma(self):
|
|
if self.needcomma:
|
|
self.ui.write(',')
|
|
self.needcomma = False
|
|
|
|
@util.propertycache
|
|
def _hexfunc(self):
|
|
return node.hex
|
|
|
|
def end(self):
|
|
self.ui.write('\n]\n')
|