Skip to content

Commit bee5cef

Browse files
committed
Always close files in distutils code and tests (#10252).
1 parent afb078d commit bee5cef

24 files changed

Lines changed: 263 additions & 173 deletions

Lib/distutils/ccompiler.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -779,14 +779,16 @@ def has_function(self, funcname, includes=None, include_dirs=None,
779779
library_dirs = []
780780
fd, fname = tempfile.mkstemp(".c", funcname, text=True)
781781
f = os.fdopen(fd, "w")
782-
for incl in includes:
783-
f.write("""#include "%s"\n""" % incl)
784-
f.write("""\
782+
try:
783+
for incl in includes:
784+
f.write("""#include "%s"\n""" % incl)
785+
f.write("""\
785786
main (int argc, char **argv) {
786787
%s();
787788
}
788789
""" % funcname)
789-
f.close()
790+
finally:
791+
f.close()
790792
try:
791793
objects = self.compile([fname], include_dirs=include_dirs)
792794
except CompileError:

Lib/distutils/command/bdist_wininst.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,4 +340,8 @@ def get_exe_bytes(self):
340340
sfix = ''
341341

342342
filename = os.path.join(directory, "wininst-%.1f%s.exe" % (bv, sfix))
343-
return open(filename, "rb").read()
343+
f = open(filename, "rb")
344+
try:
345+
return f.read()
346+
finally:
347+
f.close()

Lib/distutils/command/upload.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,11 @@ def upload_file(self, command, pyversion, filename):
7676

7777
# Fill in the data - send all the meta-data in case we need to
7878
# register a new release
79-
content = open(filename,'rb').read()
79+
f = open(filename,'rb')
80+
try:
81+
content = f.read()
82+
finally:
83+
f.close()
8084
meta = self.distribution.metadata
8185
data = {
8286
# action

Lib/distutils/core.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,11 @@ def run_setup (script_name, script_args=None, stop_after="run"):
215215
sys.argv[0] = script_name
216216
if script_args is not None:
217217
sys.argv[1:] = script_args
218-
exec(open(script_name).read(), g, l)
218+
f = open(script_name)
219+
try:
220+
exec(f.read(), g, l)
221+
finally:
222+
f.close()
219223
finally:
220224
sys.argv = save_argv
221225
_setup_stop_after = None

Lib/distutils/cygwinccompiler.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,11 +350,14 @@ def check_config_h():
350350
# let's see if __GNUC__ is mentioned in python.h
351351
fn = sysconfig.get_config_h_filename()
352352
try:
353-
with open(fn) as config_h:
353+
config_h = open(fn)
354+
try:
354355
if "__GNUC__" in config_h.read():
355356
return CONFIG_H_OK, "'%s' mentions '__GNUC__'" % fn
356357
else:
357358
return CONFIG_H_NOTOK, "'%s' does not mention '__GNUC__'" % fn
359+
finally:
360+
config_h.close()
358361
except IOError as exc:
359362
return (CONFIG_H_UNCERTAIN,
360363
"couldn't read '%s': %s" % (fn, exc.strerror))

Lib/distutils/dist.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,9 +1012,11 @@ def __init__ (self):
10121012
def write_pkg_info(self, base_dir):
10131013
"""Write the PKG-INFO file into the release tree.
10141014
"""
1015-
pkg_info = open( os.path.join(base_dir, 'PKG-INFO'), 'w')
1016-
self.write_pkg_file(pkg_info)
1017-
pkg_info.close()
1015+
pkg_info = open(os.path.join(base_dir, 'PKG-INFO'), 'w')
1016+
try:
1017+
self.write_pkg_file(pkg_info)
1018+
finally:
1019+
pkg_info.close()
10181020

10191021
def write_pkg_file(self, file):
10201022
"""Write the PKG-INFO format data to a file object.

Lib/distutils/emxccompiler.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -270,8 +270,10 @@ def check_config_h():
270270
# It would probably better to read single lines to search.
271271
# But we do this only once, and it is fast enough
272272
f = open(fn)
273-
s = f.read()
274-
f.close()
273+
try:
274+
s = f.read()
275+
finally:
276+
f.close()
275277

276278
except IOError as exc:
277279
# if we can't read this file, we cannot say it is wrong
@@ -298,8 +300,10 @@ def get_versions():
298300
gcc_exe = find_executable('gcc')
299301
if gcc_exe:
300302
out = os.popen(gcc_exe + ' -dumpversion','r')
301-
out_string = out.read()
302-
out.close()
303+
try:
304+
out_string = out.read()
305+
finally:
306+
out.close()
303307
result = re.search('(\d+\.\d+\.\d+)', out_string, re.ASCII)
304308
if result:
305309
gcc_version = StrictVersion(result.group(1))

Lib/distutils/extension.py

Lines changed: 79 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -149,84 +149,87 @@ def read_setup_file(filename):
149149
file = TextFile(filename,
150150
strip_comments=1, skip_blanks=1, join_lines=1,
151151
lstrip_ws=1, rstrip_ws=1)
152-
extensions = []
153-
154-
while True:
155-
line = file.readline()
156-
if line is None: # eof
157-
break
158-
if _variable_rx.match(line): # VAR=VALUE, handled in first pass
159-
continue
160-
161-
if line[0] == line[-1] == "*":
162-
file.warn("'%s' lines not handled yet" % line)
163-
continue
164-
165-
line = expand_makefile_vars(line, vars)
166-
words = split_quoted(line)
167-
168-
# NB. this parses a slightly different syntax than the old
169-
# makesetup script: here, there must be exactly one extension per
170-
# line, and it must be the first word of the line. I have no idea
171-
# why the old syntax supported multiple extensions per line, as
172-
# they all wind up being the same.
173-
174-
module = words[0]
175-
ext = Extension(module, [])
176-
append_next_word = None
177-
178-
for word in words[1:]:
179-
if append_next_word is not None:
180-
append_next_word.append(word)
181-
append_next_word = None
152+
try:
153+
extensions = []
154+
155+
while True:
156+
line = file.readline()
157+
if line is None: # eof
158+
break
159+
if _variable_rx.match(line): # VAR=VALUE, handled in first pass
182160
continue
183161

184-
suffix = os.path.splitext(word)[1]
185-
switch = word[0:2] ; value = word[2:]
186-
187-
if suffix in (".c", ".cc", ".cpp", ".cxx", ".c++", ".m", ".mm"):
188-
# hmm, should we do something about C vs. C++ sources?
189-
# or leave it up to the CCompiler implementation to
190-
# worry about?
191-
ext.sources.append(word)
192-
elif switch == "-I":
193-
ext.include_dirs.append(value)
194-
elif switch == "-D":
195-
equals = value.find("=")
196-
if equals == -1: # bare "-DFOO" -- no value
197-
ext.define_macros.append((value, None))
198-
else: # "-DFOO=blah"
199-
ext.define_macros.append((value[0:equals],
200-
value[equals+2:]))
201-
elif switch == "-U":
202-
ext.undef_macros.append(value)
203-
elif switch == "-C": # only here 'cause makesetup has it!
204-
ext.extra_compile_args.append(word)
205-
elif switch == "-l":
206-
ext.libraries.append(value)
207-
elif switch == "-L":
208-
ext.library_dirs.append(value)
209-
elif switch == "-R":
210-
ext.runtime_library_dirs.append(value)
211-
elif word == "-rpath":
212-
append_next_word = ext.runtime_library_dirs
213-
elif word == "-Xlinker":
214-
append_next_word = ext.extra_link_args
215-
elif word == "-Xcompiler":
216-
append_next_word = ext.extra_compile_args
217-
elif switch == "-u":
218-
ext.extra_link_args.append(word)
219-
if not value:
162+
if line[0] == line[-1] == "*":
163+
file.warn("'%s' lines not handled yet" % line)
164+
continue
165+
166+
line = expand_makefile_vars(line, vars)
167+
words = split_quoted(line)
168+
169+
# NB. this parses a slightly different syntax than the old
170+
# makesetup script: here, there must be exactly one extension per
171+
# line, and it must be the first word of the line. I have no idea
172+
# why the old syntax supported multiple extensions per line, as
173+
# they all wind up being the same.
174+
175+
module = words[0]
176+
ext = Extension(module, [])
177+
append_next_word = None
178+
179+
for word in words[1:]:
180+
if append_next_word is not None:
181+
append_next_word.append(word)
182+
append_next_word = None
183+
continue
184+
185+
suffix = os.path.splitext(word)[1]
186+
switch = word[0:2] ; value = word[2:]
187+
188+
if suffix in (".c", ".cc", ".cpp", ".cxx", ".c++", ".m", ".mm"):
189+
# hmm, should we do something about C vs. C++ sources?
190+
# or leave it up to the CCompiler implementation to
191+
# worry about?
192+
ext.sources.append(word)
193+
elif switch == "-I":
194+
ext.include_dirs.append(value)
195+
elif switch == "-D":
196+
equals = value.find("=")
197+
if equals == -1: # bare "-DFOO" -- no value
198+
ext.define_macros.append((value, None))
199+
else: # "-DFOO=blah"
200+
ext.define_macros.append((value[0:equals],
201+
value[equals+2:]))
202+
elif switch == "-U":
203+
ext.undef_macros.append(value)
204+
elif switch == "-C": # only here 'cause makesetup has it!
205+
ext.extra_compile_args.append(word)
206+
elif switch == "-l":
207+
ext.libraries.append(value)
208+
elif switch == "-L":
209+
ext.library_dirs.append(value)
210+
elif switch == "-R":
211+
ext.runtime_library_dirs.append(value)
212+
elif word == "-rpath":
213+
append_next_word = ext.runtime_library_dirs
214+
elif word == "-Xlinker":
220215
append_next_word = ext.extra_link_args
221-
elif suffix in (".a", ".so", ".sl", ".o", ".dylib"):
222-
# NB. a really faithful emulation of makesetup would
223-
# append a .o file to extra_objects only if it
224-
# had a slash in it; otherwise, it would s/.o/.c/
225-
# and append it to sources. Hmmmm.
226-
ext.extra_objects.append(word)
227-
else:
228-
file.warn("unrecognized argument '%s'" % word)
229-
230-
extensions.append(ext)
216+
elif word == "-Xcompiler":
217+
append_next_word = ext.extra_compile_args
218+
elif switch == "-u":
219+
ext.extra_link_args.append(word)
220+
if not value:
221+
append_next_word = ext.extra_link_args
222+
elif suffix in (".a", ".so", ".sl", ".o", ".dylib"):
223+
# NB. a really faithful emulation of makesetup would
224+
# append a .o file to extra_objects only if it
225+
# had a slash in it; otherwise, it would s/.o/.c/
226+
# and append it to sources. Hmmmm.
227+
ext.extra_objects.append(word)
228+
else:
229+
file.warn("unrecognized argument '%s'" % word)
230+
231+
extensions.append(ext)
232+
finally:
233+
file.close()
231234

232235
return extensions

Lib/distutils/file_util.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,8 @@ def write_file (filename, contents):
234234
sequence of strings without line terminators) to it.
235235
"""
236236
f = open(filename, "w")
237-
for line in contents:
238-
f.write(line + "\n")
239-
f.close()
237+
try:
238+
for line in contents:
239+
f.write(line + "\n")
240+
finally:
241+
f.close()

Lib/distutils/tests/test_build_py.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,15 @@ class BuildPyTestCase(support.TempdirManager,
1919
def test_package_data(self):
2020
sources = self.mkdtemp()
2121
f = open(os.path.join(sources, "__init__.py"), "w")
22-
f.write("# Pretend this is a package.")
23-
f.close()
22+
try:
23+
f.write("# Pretend this is a package.")
24+
finally:
25+
f.close()
2426
f = open(os.path.join(sources, "README.txt"), "w")
25-
f.write("Info about this package")
26-
f.close()
27+
try:
28+
f.write("Info about this package")
29+
finally:
30+
f.close()
2731

2832
destination = self.mkdtemp()
2933

0 commit comments

Comments
 (0)