From c5d5dfdb223efb0e668e3f317d31b8b70ae96aa6 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Thu, 20 Dec 2018 19:00:14 +0200 Subject: [PATCH] bpo-22831: Use "with" to avoid possible fd leaks in distutils. (GH-10921) --- Lib/distutils/archive_util.py | 22 +++++++++--------- Lib/distutils/command/bdist_msi.py | 24 ++++++++++---------- Lib/distutils/command/config.py | 36 ++++++++++++++---------------- Lib/distutils/command/sdist.py | 15 ++++++------- Lib/distutils/util.py | 33 +++++++++++++-------------- 5 files changed, 63 insertions(+), 67 deletions(-) diff --git a/Lib/distutils/archive_util.py b/Lib/distutils/archive_util.py index b002dc3b845..565a3117b4b 100644 --- a/Lib/distutils/archive_util.py +++ b/Lib/distutils/archive_util.py @@ -166,21 +166,21 @@ def make_zipfile(base_name, base_dir, verbose=0, dry_run=0): zip = zipfile.ZipFile(zip_filename, "w", compression=zipfile.ZIP_STORED) - if base_dir != os.curdir: - path = os.path.normpath(os.path.join(base_dir, '')) - zip.write(path, path) - log.info("adding '%s'", path) - for dirpath, dirnames, filenames in os.walk(base_dir): - for name in dirnames: - path = os.path.normpath(os.path.join(dirpath, name, '')) + with zip: + if base_dir != os.curdir: + path = os.path.normpath(os.path.join(base_dir, '')) zip.write(path, path) log.info("adding '%s'", path) - for name in filenames: - path = os.path.normpath(os.path.join(dirpath, name)) - if os.path.isfile(path): + for dirpath, dirnames, filenames in os.walk(base_dir): + for name in dirnames: + path = os.path.normpath(os.path.join(dirpath, name, '')) zip.write(path, path) log.info("adding '%s'", path) - zip.close() + for name in filenames: + path = os.path.normpath(os.path.join(dirpath, name)) + if os.path.isfile(path): + zip.write(path, path) + log.info("adding '%s'", path) return zip_filename diff --git a/Lib/distutils/command/bdist_msi.py b/Lib/distutils/command/bdist_msi.py index 80104c372d9..f335a348986 100644 --- a/Lib/distutils/command/bdist_msi.py +++ b/Lib/distutils/command/bdist_msi.py @@ -390,18 +390,18 @@ class bdist_msi(Command): # entries for each version as the above code does if self.pre_install_script: scriptfn = os.path.join(self.bdist_dir, "preinstall.bat") - f = open(scriptfn, "w") - # The batch file will be executed with [PYTHON], so that %1 - # is the path to the Python interpreter; %0 will be the path - # of the batch file. - # rem =""" - # %1 %0 - # exit - # """ - # - f.write('rem ="""\n%1 %0\nexit\n"""\n') - f.write(open(self.pre_install_script).read()) - f.close() + with open(scriptfn, "w") as f: + # The batch file will be executed with [PYTHON], so that %1 + # is the path to the Python interpreter; %0 will be the path + # of the batch file. + # rem =""" + # %1 %0 + # exit + # """ + # + f.write('rem ="""\n%1 %0\nexit\n"""\n') + with open(self.pre_install_script) as fin: + f.write(fin.read()) add_data(self.db, "Binary", [("PreInstall", msilib.Binary(scriptfn)) ]) diff --git a/Lib/distutils/command/config.py b/Lib/distutils/command/config.py index 4ae153d1943..f511b888577 100644 --- a/Lib/distutils/command/config.py +++ b/Lib/distutils/command/config.py @@ -106,15 +106,14 @@ class config(Command): def _gen_temp_sourcefile(self, body, headers, lang): filename = "_configtest" + LANG_EXT[lang] - file = open(filename, "w") - if headers: - for header in headers: - file.write("#include <%s>\n" % header) - file.write("\n") - file.write(body) - if body[-1] != "\n": - file.write("\n") - file.close() + with open(filename, "w") as file: + if headers: + for header in headers: + file.write("#include <%s>\n" % header) + file.write("\n") + file.write(body) + if body[-1] != "\n": + file.write("\n") return filename def _preprocess(self, body, headers, include_dirs, lang): @@ -203,17 +202,16 @@ class config(Command): if isinstance(pattern, str): pattern = re.compile(pattern) - file = open(out) - match = False - while True: - line = file.readline() - if line == '': - break - if pattern.search(line): - match = True - break + with open(out) as file: + match = False + while True: + line = file.readline() + if line == '': + break + if pattern.search(line): + match = True + break - file.close() self._clean() return match diff --git a/Lib/distutils/command/sdist.py b/Lib/distutils/command/sdist.py index 52eaa15d471..b4996fcb1d2 100644 --- a/Lib/distutils/command/sdist.py +++ b/Lib/distutils/command/sdist.py @@ -407,14 +407,13 @@ class sdist(Command): distribution. """ log.info("reading manifest file '%s'", self.manifest) - manifest = open(self.manifest) - for line in manifest: - # ignore comments and blank lines - line = line.strip() - if line.startswith('#') or not line: - continue - self.filelist.append(line) - manifest.close() + with open(self.manifest) as manifest: + for line in manifest: + # ignore comments and blank lines + line = line.strip() + if line.startswith('#') or not line: + continue + self.filelist.append(line) def make_release_tree(self, base_dir, files): """Create the directory tree that will become the source diff --git a/Lib/distutils/util.py b/Lib/distutils/util.py index 30a21e4afa1..15cd2ad9a9a 100644 --- a/Lib/distutils/util.py +++ b/Lib/distutils/util.py @@ -378,35 +378,34 @@ def byte_compile (py_files, else: script = open(script_name, "w") - script.write("""\ + with script: + script.write("""\ from distutils.util import byte_compile files = [ """) - # XXX would be nice to write absolute filenames, just for - # safety's sake (script should be more robust in the face of - # chdir'ing before running it). But this requires abspath'ing - # 'prefix' as well, and that breaks the hack in build_lib's - # 'byte_compile()' method that carefully tacks on a trailing - # slash (os.sep really) to make sure the prefix here is "just - # right". This whole prefix business is rather delicate -- the - # problem is that it's really a directory, but I'm treating it - # as a dumb string, so trailing slashes and so forth matter. + # XXX would be nice to write absolute filenames, just for + # safety's sake (script should be more robust in the face of + # chdir'ing before running it). But this requires abspath'ing + # 'prefix' as well, and that breaks the hack in build_lib's + # 'byte_compile()' method that carefully tacks on a trailing + # slash (os.sep really) to make sure the prefix here is "just + # right". This whole prefix business is rather delicate -- the + # problem is that it's really a directory, but I'm treating it + # as a dumb string, so trailing slashes and so forth matter. - #py_files = map(os.path.abspath, py_files) - #if prefix: - # prefix = os.path.abspath(prefix) + #py_files = map(os.path.abspath, py_files) + #if prefix: + # prefix = os.path.abspath(prefix) - script.write(",\n".join(map(repr, py_files)) + "]\n") - script.write(""" + script.write(",\n".join(map(repr, py_files)) + "]\n") + script.write(""" byte_compile(files, optimize=%r, force=%r, prefix=%r, base_dir=%r, verbose=%r, dry_run=0, direct=1) """ % (optimize, force, prefix, base_dir, verbose)) - script.close() - cmd = [sys.executable] cmd.extend(subprocess._optim_args_from_interpreter_flags()) cmd.append(script_name)