diff --git a/Misc/NEWS b/Misc/NEWS index 8b9d314a71b..f3dab008fb9 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -89,6 +89,14 @@ Build - Issue #23585: make patchcheck will ensure the interpreter is built. +Tools/Demos +----------- + +- Issue #22826: The result of open() in Tools/freeze/bkfile.py is now better + compatible with regular files (in particular it now supports the context + management protocol). + + What's New in Python 3.5 alpha 2? ================================= diff --git a/Tools/freeze/bkfile.py b/Tools/freeze/bkfile.py index 6abacc9e0ed..20a70b0639d 100644 --- a/Tools/freeze/bkfile.py +++ b/Tools/freeze/bkfile.py @@ -1,49 +1,26 @@ from builtins import open as _orig_open -class _BkFile: - def __init__(self, file, mode, bufsize): - import os - self.__filename = file - self.__backup = file + '~' - try: - os.unlink(self.__backup) - except OSError: - pass - try: - os.rename(file, self.__backup) - except OSError: - self.__backup = None - self.__file = _orig_open(file, mode, bufsize) - self.closed = self.__file.closed - self.fileno = self.__file.fileno - self.flush = self.__file.flush - self.isatty = self.__file.isatty - self.mode = self.__file.mode - self.name = self.__file.name - self.read = self.__file.read - try: - self.readinto = self.__file.readinto - except AttributeError: - pass - self.readline = self.__file.readline - self.readlines = self.__file.readlines - self.seek = self.__file.seek - self.tell = self.__file.tell - self.truncate = self.__file.truncate - self.write = self.__file.write - self.writelines = self.__file.writelines - - def close(self): - self.__file.close() - if self.__backup is None: - return - import filecmp - if filecmp.cmp(self.__backup, self.__filename, shallow = 0): - import os - os.unlink(self.__filename) - os.rename(self.__backup, self.__filename) - -def open(file, mode = 'r', bufsize = -1): +def open(file, mode='r', bufsize=-1): if 'w' not in mode: return _orig_open(file, mode, bufsize) - return _BkFile(file, mode, bufsize) + import os + backup = file + '~' + try: + os.unlink(backup) + except OSError: + pass + try: + os.rename(file, backup) + except OSError: + return _orig_open(file, mode, bufsize) + f = _orig_open(file, mode, bufsize) + _orig_close = f.close + def close(): + _orig_close() + import filecmp + if filecmp.cmp(backup, file, shallow=False): + import os + os.unlink(file) + os.rename(backup, file) + f.close = close + return f diff --git a/Tools/freeze/freeze.py b/Tools/freeze/freeze.py index e0c6c2c580a..15ddbe65001 100755 --- a/Tools/freeze/freeze.py +++ b/Tools/freeze/freeze.py @@ -439,25 +439,17 @@ def main(): frozendllmain_c, os.path.basename(extensions_c)] + files maindefn = checkextensions_win32.CExtension( '__main__', xtras ) frozen_extensions.append( maindefn ) - outfp = open(makefile, 'w') - try: + with open(makefile, 'w') as outfp: winmakemakefile.makemakefile(outfp, locals(), frozen_extensions, os.path.basename(target)) - finally: - outfp.close() return # generate config.c and Makefile builtins.sort() - infp = open(config_c_in) - outfp = bkfile.open(config_c, 'w') - try: + with open(config_c_in) as infp, bkfile.open(config_c, 'w') as outfp: makeconfig.makeconfig(infp, outfp, builtins) - finally: - outfp.close() - infp.close() cflags = ['$(OPT)'] cppflags = defines + includes @@ -475,11 +467,8 @@ def main(): files + supp_sources + addfiles + libs + \ ['$(MODLIBS)', '$(LIBS)', '$(SYSLIBS)'] - outfp = bkfile.open(makefile, 'w') - try: + with bkfile.open(makefile, 'w') as outfp: makemakefile.makemakefile(outfp, somevars, files, base_target) - finally: - outfp.close() # Done! diff --git a/Tools/freeze/makefreeze.py b/Tools/freeze/makefreeze.py index ef18ec7b286..64e3e6bf71e 100644 --- a/Tools/freeze/makefreeze.py +++ b/Tools/freeze/makefreeze.py @@ -39,36 +39,34 @@ def makefreeze(base, dict, debug=0, entry_point=None, fail_import=()): mangled = "__".join(mod.split(".")) if m.__code__: file = 'M_' + mangled + '.c' - outfp = bkfile.open(base + file, 'w') - files.append(file) - if debug: - print("freezing", mod, "...") - str = marshal.dumps(m.__code__) - size = len(str) - if m.__path__: - # Indicate package by negative size - size = -size - done.append((mod, mangled, size)) - writecode(outfp, mangled, str) - outfp.close() + with bkfile.open(base + file, 'w') as outfp: + files.append(file) + if debug: + print("freezing", mod, "...") + str = marshal.dumps(m.__code__) + size = len(str) + if m.__path__: + # Indicate package by negative size + size = -size + done.append((mod, mangled, size)) + writecode(outfp, mangled, str) if debug: print("generating table of frozen modules") - outfp = bkfile.open(base + 'frozen.c', 'w') - for mod, mangled, size in done: - outfp.write('extern unsigned char M_%s[];\n' % mangled) - outfp.write(header) - for mod, mangled, size in done: - outfp.write('\t{"%s", M_%s, %d},\n' % (mod, mangled, size)) - outfp.write('\n') - # The following modules have a NULL code pointer, indicating - # that the frozen program should not search for them on the host - # system. Importing them will *always* raise an ImportError. - # The zero value size is never used. - for mod in fail_import: - outfp.write('\t{"%s", NULL, 0},\n' % (mod,)) - outfp.write(trailer) - outfp.write(entry_point) - outfp.close() + with bkfile.open(base + 'frozen.c', 'w') as outfp: + for mod, mangled, size in done: + outfp.write('extern unsigned char M_%s[];\n' % mangled) + outfp.write(header) + for mod, mangled, size in done: + outfp.write('\t{"%s", M_%s, %d},\n' % (mod, mangled, size)) + outfp.write('\n') + # The following modules have a NULL code pointer, indicating + # that the frozen program should not search for them on the host + # system. Importing them will *always* raise an ImportError. + # The zero value size is never used. + for mod in fail_import: + outfp.write('\t{"%s", NULL, 0},\n' % (mod,)) + outfp.write(trailer) + outfp.write(entry_point) return files