diff -r fc3eab44765f Doc/library/aifc.rst --- a/Doc/library/aifc.rst Wed Dec 28 20:03:23 2016 -0800 +++ b/Doc/library/aifc.rst Thu Dec 29 19:16:00 2016 -0500 @@ -139,9 +139,9 @@ .. method:: aifc.close() - - Close the AIFF file. After calling this method, the object can no longer be - used. + + Close the AIFF file if it was opened by :mod:`aifc`. After calling this method, + the object can no longer be used. Objects returned by :func:`.open` when a file is opened for writing have all the above methods, except for :meth:`readframes` and :meth:`setpos`. In addition @@ -239,7 +239,7 @@ .. method:: aifc.close() - Close the AIFF file. The header of the file is updated to reflect the actual - size of the audio data. After calling this method, the object can no longer be - used. + Close the AIFF file if it was opened by :mod:`aifc`. The header of the file is + updated to reflect the actual size of the audio data. After calling this method, + the object can no longer be used. diff -r fc3eab44765f Lib/aifc.py --- a/Lib/aifc.py Wed Dec 28 20:03:23 2016 -0800 +++ b/Lib/aifc.py Thu Dec 29 19:16:00 2016 -0500 @@ -343,10 +343,17 @@ raise Error('COMM chunk and/or SSND chunk missing') def __init__(self, f): + self._i_opened_the_file = None if isinstance(f, str): f = builtins.open(f, 'rb') + self._i_opened_the_file = f # else, assume it is an open file object already - self.initfp(f) + try: + self.initfp(f) + except: + if self._i_opened_the_file: + f.close() + raise def __enter__(self): return self @@ -365,9 +372,10 @@ self._soundpos = 0 def close(self): - file = self._file + self._file = None + file = self._i_opened_the_file if file is not None: - self._file = None + self._i_opened_the_file = None file.close() def tell(self): @@ -542,17 +550,23 @@ # _datawritten -- the size of the audio samples actually written def __init__(self, f): + self._i_opened_the_file = None if isinstance(f, str): filename = f f = builtins.open(f, 'wb') + self._i_opened_the_file = f else: - # else, assume it is an open file object already filename = '???' - self.initfp(f) - if filename[-5:] == '.aiff': - self._aifc = 0 - else: - self._aifc = 1 + + try: + self.initfp(f) + except: + if self._i_opened_the_file: + f.close() + raise + + if filename.endswith('.aiff'): + self._aifc = 0 # file extension implies AIFF instead of AIFF-C def initfp(self, file): self._file = file @@ -735,11 +749,12 @@ self._marklength: self._patchheader() finally: - # Prevent ref cycles self._convert = None - f = self._file self._file = None - f.close() + file = self._i_opened_the_file + if file is not None: + self._i_opened_the_file = None + file.close() # # Internal methods. diff -r fc3eab44765f Lib/test/test_aifc.py --- a/Lib/test/test_aifc.py Wed Dec 28 20:03:23 2016 -0800 +++ b/Lib/test/test_aifc.py Thu Dec 29 19:16:00 2016 -0500 @@ -11,7 +11,6 @@ class AifcTest(audiotests.AudioWriteTests, audiotests.AudioTestsWithSourceFile): module = aifc - close_fd = True test_unseekable_read = None