From afbb7a371fb44edc731344eab5b474ad8f7b57d7 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sat, 30 Mar 2019 08:32:18 +0200 Subject: [PATCH] bpo-22831: Use "with" to avoid possible fd leaks in tools (part 1). (GH-10926) --- Tools/scripts/fixcid.py | 60 ++++++------ Tools/scripts/fixdiv.py | 186 ++++++++++++++++++------------------ Tools/scripts/fixheader.py | 42 ++++---- Tools/scripts/gprof2html.py | 20 ++-- Tools/scripts/texi2html.py | 146 ++++++++++++++-------------- 5 files changed, 226 insertions(+), 228 deletions(-) diff --git a/Tools/scripts/fixcid.py b/Tools/scripts/fixcid.py index c66a0ac093a..8f35eaeeb4f 100755 --- a/Tools/scripts/fixcid.py +++ b/Tools/scripts/fixcid.py @@ -281,36 +281,36 @@ def addsubst(substfile): except IOError as msg: err(substfile + ': cannot read substfile: ' + str(msg) + '\n') sys.exit(1) - lineno = 0 - while 1: - line = fp.readline() - if not line: break - lineno = lineno + 1 - try: - i = line.index('#') - except ValueError: - i = -1 # Happens to delete trailing \n - words = line[:i].split() - if not words: continue - if len(words) == 3 and words[0] == 'struct': - words[:2] = [words[0] + ' ' + words[1]] - elif len(words) != 2: - err(substfile + '%s:%r: warning: bad line: %r' % (substfile, lineno, line)) - continue - if Reverse: - [value, key] = words - else: - [key, value] = words - if value[0] == '*': - value = value[1:] - if key[0] == '*': - key = key[1:] - NotInComment[key] = value - if key in Dict: - err('%s:%r: warning: overriding: %r %r\n' % (substfile, lineno, key, value)) - err('%s:%r: warning: previous: %r\n' % (substfile, lineno, Dict[key])) - Dict[key] = value - fp.close() + with fp: + lineno = 0 + while 1: + line = fp.readline() + if not line: break + lineno = lineno + 1 + try: + i = line.index('#') + except ValueError: + i = -1 # Happens to delete trailing \n + words = line[:i].split() + if not words: continue + if len(words) == 3 and words[0] == 'struct': + words[:2] = [words[0] + ' ' + words[1]] + elif len(words) != 2: + err(substfile + '%s:%r: warning: bad line: %r' % (substfile, lineno, line)) + continue + if Reverse: + [value, key] = words + else: + [key, value] = words + if value[0] == '*': + value = value[1:] + if key[0] == '*': + key = key[1:] + NotInComment[key] = value + if key in Dict: + err('%s:%r: warning: overriding: %r %r\n' % (substfile, lineno, key, value)) + err('%s:%r: warning: previous: %r\n' % (substfile, lineno, Dict[key])) + Dict[key] = value if __name__ == '__main__': main() diff --git a/Tools/scripts/fixdiv.py b/Tools/scripts/fixdiv.py index 1213a4e3976..df7c481aa22 100755 --- a/Tools/scripts/fixdiv.py +++ b/Tools/scripts/fixdiv.py @@ -179,27 +179,27 @@ PATTERN = (r"^(.+?):(\d+): DeprecationWarning: " def readwarnings(warningsfile): prog = re.compile(PATTERN) + warnings = {} try: f = open(warningsfile) except IOError as msg: sys.stderr.write("can't open: %s\n" % msg) return - warnings = {} - while 1: - line = f.readline() - if not line: - break - m = prog.match(line) - if not m: - if line.find("division") >= 0: - sys.stderr.write("Warning: ignored input " + line) - continue - filename, lineno, what = m.groups() - list = warnings.get(filename) - if list is None: - warnings[filename] = list = [] - list.append((int(lineno), sys.intern(what))) - f.close() + with f: + while 1: + line = f.readline() + if not line: + break + m = prog.match(line) + if not m: + if line.find("division") >= 0: + sys.stderr.write("Warning: ignored input " + line) + continue + filename, lineno, what = m.groups() + list = warnings.get(filename) + if list is None: + warnings[filename] = list = [] + list.append((int(lineno), sys.intern(what))) return warnings def process(filename, list): @@ -210,84 +210,84 @@ def process(filename, list): except IOError as msg: sys.stderr.write("can't open: %s\n" % msg) return 1 - print("Index:", filename) - f = FileContext(fp) - list.sort() - index = 0 # list[:index] has been processed, list[index:] is still to do - g = tokenize.generate_tokens(f.readline) - while 1: - startlineno, endlineno, slashes = lineinfo = scanline(g) - if startlineno is None: - break - assert startlineno <= endlineno is not None - orphans = [] - while index < len(list) and list[index][0] < startlineno: - orphans.append(list[index]) - index += 1 - if orphans: - reportphantomwarnings(orphans, f) - warnings = [] - while index < len(list) and list[index][0] <= endlineno: - warnings.append(list[index]) - index += 1 - if not slashes and not warnings: - pass - elif slashes and not warnings: - report(slashes, "No conclusive evidence") - elif warnings and not slashes: - reportphantomwarnings(warnings, f) - else: - if len(slashes) > 1: - if not multi_ok: - rows = [] - lastrow = None - for (row, col), line in slashes: - if row == lastrow: - continue - rows.append(row) - lastrow = row - assert rows - if len(rows) == 1: - print("*** More than one / operator in line", rows[0]) + with fp: + print("Index:", filename) + f = FileContext(fp) + list.sort() + index = 0 # list[:index] has been processed, list[index:] is still to do + g = tokenize.generate_tokens(f.readline) + while 1: + startlineno, endlineno, slashes = lineinfo = scanline(g) + if startlineno is None: + break + assert startlineno <= endlineno is not None + orphans = [] + while index < len(list) and list[index][0] < startlineno: + orphans.append(list[index]) + index += 1 + if orphans: + reportphantomwarnings(orphans, f) + warnings = [] + while index < len(list) and list[index][0] <= endlineno: + warnings.append(list[index]) + index += 1 + if not slashes and not warnings: + pass + elif slashes and not warnings: + report(slashes, "No conclusive evidence") + elif warnings and not slashes: + reportphantomwarnings(warnings, f) + else: + if len(slashes) > 1: + if not multi_ok: + rows = [] + lastrow = None + for (row, col), line in slashes: + if row == lastrow: + continue + rows.append(row) + lastrow = row + assert rows + if len(rows) == 1: + print("*** More than one / operator in line", rows[0]) + else: + print("*** More than one / operator per statement", end=' ') + print("in lines %d-%d" % (rows[0], rows[-1])) + intlong = [] + floatcomplex = [] + bad = [] + for lineno, what in warnings: + if what in ("int", "long"): + intlong.append(what) + elif what in ("float", "complex"): + floatcomplex.append(what) else: - print("*** More than one / operator per statement", end=' ') - print("in lines %d-%d" % (rows[0], rows[-1])) - intlong = [] - floatcomplex = [] - bad = [] - for lineno, what in warnings: - if what in ("int", "long"): - intlong.append(what) - elif what in ("float", "complex"): - floatcomplex.append(what) - else: - bad.append(what) - lastrow = None - for (row, col), line in slashes: - if row == lastrow: - continue - lastrow = row - line = chop(line) - if line[col:col+1] != "/": - print("*** Can't find the / operator in line %d:" % row) - print("*", line) - continue - if bad: - print("*** Bad warning for line %d:" % row, bad) - print("*", line) - elif intlong and not floatcomplex: - print("%dc%d" % (row, row)) - print("<", line) - print("---") - print(">", line[:col] + "/" + line[col:]) - elif floatcomplex and not intlong: - print("True division / operator at line %d:" % row) - print("=", line) - elif intlong and floatcomplex: - print("*** Ambiguous / operator (%s, %s) at line %d:" % ( - "|".join(intlong), "|".join(floatcomplex), row)) - print("?", line) - fp.close() + bad.append(what) + lastrow = None + for (row, col), line in slashes: + if row == lastrow: + continue + lastrow = row + line = chop(line) + if line[col:col+1] != "/": + print("*** Can't find the / operator in line %d:" % row) + print("*", line) + continue + if bad: + print("*** Bad warning for line %d:" % row, bad) + print("*", line) + elif intlong and not floatcomplex: + print("%dc%d" % (row, row)) + print("<", line) + print("---") + print(">", line[:col] + "/" + line[col:]) + elif floatcomplex and not intlong: + print("True division / operator at line %d:" % row) + print("=", line) + elif intlong and floatcomplex: + print("*** Ambiguous / operator (%s, %s) at line %d:" % + ("|".join(intlong), "|".join(floatcomplex), row)) + print("?", line) def reportphantomwarnings(warnings, f): blocks = [] diff --git a/Tools/scripts/fixheader.py b/Tools/scripts/fixheader.py index ec840575b20..c834eec1e20 100755 --- a/Tools/scripts/fixheader.py +++ b/Tools/scripts/fixheader.py @@ -15,8 +15,8 @@ def process(filename): except IOError as msg: sys.stderr.write('%s: can\'t open: %s\n' % (filename, str(msg))) return - data = f.read() - f.close() + with f: + data = f.read() if data[:2] != '/*': sys.stderr.write('%s does not begin with C comment\n' % filename) return @@ -25,25 +25,25 @@ def process(filename): except IOError as msg: sys.stderr.write('%s: can\'t write: %s\n' % (filename, str(msg))) return - sys.stderr.write('Processing %s ...\n' % filename) - magic = 'Py_' - for c in filename: - if ord(c)<=0x80 and c.isalnum(): - magic = magic + c.upper() - else: magic = magic + '_' - sys.stdout = f - print('#ifndef', magic) - print('#define', magic) - print('#ifdef __cplusplus') - print('extern "C" {') - print('#endif') - print() - f.write(data) - print() - print('#ifdef __cplusplus') - print('}') - print('#endif') - print('#endif /*', '!'+magic, '*/') + with f: + sys.stderr.write('Processing %s ...\n' % filename) + magic = 'Py_' + for c in filename: + if ord(c)<=0x80 and c.isalnum(): + magic = magic + c.upper() + else: magic = magic + '_' + print('#ifndef', magic, file=f) + print('#define', magic, file=f) + print('#ifdef __cplusplus', file=f) + print('extern "C" {', file=f) + print('#endif', file=f) + print(file=f) + f.write(data) + print(file=f) + print('#ifdef __cplusplus', file=f) + print('}', file=f) + print('#endif', file=f) + print('#endif /*', '!'+magic, '*/', file=f) if __name__ == '__main__': main() diff --git a/Tools/scripts/gprof2html.py b/Tools/scripts/gprof2html.py index 4ca705c3c61..b14def4ef84 100755 --- a/Tools/scripts/gprof2html.py +++ b/Tools/scripts/gprof2html.py @@ -28,14 +28,7 @@ def add_escapes(filename): for line in fp: yield html.escape(line) - -def main(): - filename = "gprof.out" - if sys.argv[1:]: - filename = sys.argv[1] - outputfilename = filename + ".html" - input = add_escapes(filename) - output = open(outputfilename, "w") +def gprof2html(input, output, filename): output.write(header % filename) for line in input: output.write(line) @@ -78,7 +71,16 @@ def main(): part = '%s' % (part, part) output.write(part) output.write(trailer) - output.close() + + +def main(): + filename = "gprof.out" + if sys.argv[1:]: + filename = sys.argv[1] + outputfilename = filename + ".html" + input = add_escapes(filename) + with open(outputfilename, "w") as output: + gprof2html(input, output, filename) webbrowser.open("file:" + os.path.abspath(outputfilename)) if __name__ == '__main__': diff --git a/Tools/scripts/texi2html.py b/Tools/scripts/texi2html.py index 5565c210dab..c06d812ab3f 100755 --- a/Tools/scripts/texi2html.py +++ b/Tools/scripts/texi2html.py @@ -118,11 +118,10 @@ class HTMLNode: self.lines.append(line) def flush(self): - fp = open(self.dirname + '/' + makefile(self.name), 'w') - fp.write(self.prologue) - fp.write(self.text) - fp.write(self.epilogue) - fp.close() + with open(self.dirname + '/' + makefile(self.name), 'w') as fp: + fp.write(self.prologue) + fp.write(self.text) + fp.write(self.epilogue) def link(self, label, nodename, rel=None, rev=None): if nodename: @@ -558,14 +557,14 @@ class TexinfoParser: except IOError as msg: print('*** Can\'t open include file', repr(file)) return - print('!'*self.debugging, '--> file', repr(file)) - save_done = self.done - save_skip = self.skip - save_stack = self.stack - self.includedepth = self.includedepth + 1 - self.parserest(fp, 0) - self.includedepth = self.includedepth - 1 - fp.close() + with fp: + print('!'*self.debugging, '--> file', repr(file)) + save_done = self.done + save_skip = self.skip + save_stack = self.stack + self.includedepth = self.includedepth + 1 + self.parserest(fp, 0) + self.includedepth = self.includedepth - 1 self.done = save_done self.skip = save_skip self.stack = save_stack @@ -1770,78 +1769,75 @@ class HTMLHelp: # PROJECT FILE try: - fp = open(projectfile,'w') - print('[OPTIONS]', file=fp) - print('Auto Index=Yes', file=fp) - print('Binary TOC=No', file=fp) - print('Binary Index=Yes', file=fp) - print('Compatibility=1.1', file=fp) - print('Compiled file=' + resultfile + '', file=fp) - print('Contents file=' + contentfile + '', file=fp) - print('Default topic=' + defaulttopic + '', file=fp) - print('Error log file=ErrorLog.log', file=fp) - print('Index file=' + indexfile + '', file=fp) - print('Title=' + title + '', file=fp) - print('Display compile progress=Yes', file=fp) - print('Full-text search=Yes', file=fp) - print('Default window=main', file=fp) - print('', file=fp) - print('[WINDOWS]', file=fp) - print('main=,"' + contentfile + '","' + indexfile - + '","","",,,,,0x23520,222,0x1046,[10,10,780,560],' - '0xB0000,,,,,,0', file=fp) - print('', file=fp) - print('[FILES]', file=fp) - print('', file=fp) - self.dumpfiles(fp) - fp.close() + with open(projectfile, 'w') as fp: + print('[OPTIONS]', file=fp) + print('Auto Index=Yes', file=fp) + print('Binary TOC=No', file=fp) + print('Binary Index=Yes', file=fp) + print('Compatibility=1.1', file=fp) + print('Compiled file=' + resultfile + '', file=fp) + print('Contents file=' + contentfile + '', file=fp) + print('Default topic=' + defaulttopic + '', file=fp) + print('Error log file=ErrorLog.log', file=fp) + print('Index file=' + indexfile + '', file=fp) + print('Title=' + title + '', file=fp) + print('Display compile progress=Yes', file=fp) + print('Full-text search=Yes', file=fp) + print('Default window=main', file=fp) + print('', file=fp) + print('[WINDOWS]', file=fp) + print('main=,"' + contentfile + '","' + indexfile + + '","","",,,,,0x23520,222,0x1046,[10,10,780,560],' + '0xB0000,,,,,,0', file=fp) + print('', file=fp) + print('[FILES]', file=fp) + print('', file=fp) + self.dumpfiles(fp) except IOError as msg: print(projectfile, ':', msg) sys.exit(1) # CONTENT FILE try: - fp = open(contentfile,'w') - print('', file=fp) - print('', file=fp) - print('', file=fp) - print('', file=fp) - print('', file=fp) - print('', file=fp) - print('', file=fp) - print('', file=fp) - print(' ', file=fp) - print(' ', file=fp) - print(' ', file=fp) - print(' ', file=fp) - print(' ', file=fp) - self.dumpnodes(fp) - print('', file=fp) - print('', file=fp) - fp.close() + with open(contentfile, 'w') as fp: + print('', file=fp) + print('', file=fp) + print('', file=fp) + print('', file=fp) + print('', file=fp) + print('', file=fp) + print('', file=fp) + print('', file=fp) + print(' ', file=fp) + print(' ', file=fp) + print(' ', file=fp) + print(' ', file=fp) + print(' ', file=fp) + self.dumpnodes(fp) + print('', file=fp) + print('', file=fp) except IOError as msg: print(contentfile, ':', msg) sys.exit(1) # INDEX FILE try: - fp = open(indexfile ,'w') - print('', file=fp) - print('', file=fp) - print('', file=fp) - print('', file=fp) - print('', file=fp) - print('', file=fp) - print('', file=fp) - print('', file=fp) - print('', file=fp) - print('', file=fp) - self.dumpindex(fp) - print('', file=fp) - print('', file=fp) - fp.close() + with open(indexfile, 'w') as fp: + print('', file=fp) + print('', file=fp) + print('', file=fp) + print('', file=fp) + print('', file=fp) + print('', file=fp) + print('', file=fp) + print('', file=fp) + print('', file=fp) + print('', file=fp) + self.dumpindex(fp) + print('', file=fp) + print('', file=fp) except IOError as msg: print(indexfile , ':', msg) sys.exit(1) @@ -2064,8 +2060,8 @@ def test(): print(file, ':', msg) sys.exit(1) - parser.parse(fp) - fp.close() + with fp: + parser.parse(fp) parser.report() htmlhelp.finalize()