Issue #5202: Added support for unseekable files in the wave module.
diff --git a/Lib/test/audiotests.py b/Lib/test/audiotests.py
index 7b39269..c22f0a1 100644
--- a/Lib/test/audiotests.py
+++ b/Lib/test/audiotests.py
@@ -21,6 +21,13 @@
     a.byteswap()
     return a.tobytes()
 
+class UnseekableIO(io.FileIO):
+    def tell(self):
+        raise io.UnsupportedOperation
+
+    def seek(self, *args, **kwargs):
+        raise io.UnsupportedOperation
+
 
 class AudioTests:
     close_fd = False
@@ -177,6 +184,59 @@
             self.assertEqual(testfile.read(13), b'ababagalamaga')
             self.check_file(testfile, self.nframes, self.frames)
 
+    def test_unseekable_read(self):
+        with self.create_file(TESTFN) as f:
+            f.setnframes(self.nframes)
+            f.writeframes(self.frames)
+
+        with UnseekableIO(TESTFN, 'rb') as testfile:
+            self.check_file(testfile, self.nframes, self.frames)
+
+    def test_unseekable_write(self):
+        with UnseekableIO(TESTFN, 'wb') as testfile:
+            with self.create_file(testfile) as f:
+                f.setnframes(self.nframes)
+                f.writeframes(self.frames)
+
+        self.check_file(TESTFN, self.nframes, self.frames)
+
+    def test_unseekable_incompleted_write(self):
+        with UnseekableIO(TESTFN, 'wb') as testfile:
+            testfile.write(b'ababagalamaga')
+            f = self.create_file(testfile)
+            f.setnframes(self.nframes + 1)
+            try:
+                f.writeframes(self.frames)
+            except OSError:
+                pass
+            try:
+                f.close()
+            except OSError:
+                pass
+
+        with open(TESTFN, 'rb') as testfile:
+            self.assertEqual(testfile.read(13), b'ababagalamaga')
+            self.check_file(testfile, self.nframes + 1, self.frames)
+
+    def test_unseekable_overflowed_write(self):
+        with UnseekableIO(TESTFN, 'wb') as testfile:
+            testfile.write(b'ababagalamaga')
+            f = self.create_file(testfile)
+            f.setnframes(self.nframes - 1)
+            try:
+                f.writeframes(self.frames)
+            except OSError:
+                pass
+            try:
+                f.close()
+            except OSError:
+                pass
+
+        with open(TESTFN, 'rb') as testfile:
+            self.assertEqual(testfile.read(13), b'ababagalamaga')
+            framesize = self.nchannels * self.sampwidth
+            self.check_file(testfile, self.nframes - 1, self.frames[:-framesize])
+
 
 class AudioTestsWithSourceFile(AudioTests):
 
diff --git a/Lib/test/test_aifc.py b/Lib/test/test_aifc.py
index 3e9a1d1..b4270bc 100644
--- a/Lib/test/test_aifc.py
+++ b/Lib/test/test_aifc.py
@@ -8,10 +8,17 @@
 import aifc
 
 
-class AifcPCM8Test(audiotests.AudioWriteTests,
-        audiotests.AudioTestsWithSourceFile,
-        unittest.TestCase):
+class AifcTest(audiotests.AudioWriteTests,
+               audiotests.AudioTestsWithSourceFile):
     module = aifc
+    close_fd = True
+    test_unseekable_read = None
+    test_unseekable_write = None
+    test_unseekable_incompleted_write = None
+    test_unseekable_overflowed_write = None
+
+
+class AifcPCM8Test(AifcTest, unittest.TestCase):
     sndfilename = 'pluck-pcm8.aiff'
     sndfilenframes = 3307
     nchannels = 2
@@ -26,13 +33,9 @@
       11FA 3EFB BCFC 66FF CF04 4309 C10E 5112 EE17 8216 7F14 8012 \
       490E 520D EF0F CE0F E40C 630A 080A 2B0B 510E 8B11 B60E 440A \
       """)
-    close_fd = True
 
 
-class AifcPCM16Test(audiotests.AudioWriteTests,
-        audiotests.AudioTestsWithSourceFile,
-        unittest.TestCase):
-    module = aifc
+class AifcPCM16Test(AifcTest, unittest.TestCase):
     sndfilename = 'pluck-pcm16.aiff'
     sndfilenframes = 3307
     nchannels = 2
@@ -49,13 +52,9 @@
       EEE21753 82071665 7FFF1443 8004128F 49A20EAF 52BB0DBA EFB40F60 CE3C0FBF \
       E4B30CEC 63430A5C 08C80A20 2BBB0B08 514A0E43 8BCF1139 B6F60EEB 44120A5E \
       """)
-    close_fd = True
 
 
-class AifcPCM24Test(audiotests.AudioWriteTests,
-        audiotests.AudioTestsWithSourceFile,
-        unittest.TestCase):
-    module = aifc
+class AifcPCM24Test(AifcTest, unittest.TestCase):
     sndfilename = 'pluck-pcm24.aiff'
     sndfilenframes = 3307
     nchannels = 2
@@ -78,13 +77,9 @@
       E4B49C0CEA2D 6344A80A5A7C 08C8FE0A1FFE 2BB9860B0A0E \
       51486F0E44E1 8BCC64113B05 B6F4EC0EEB36 4413170A5B48 \
       """)
-    close_fd = True
 
 
-class AifcPCM32Test(audiotests.AudioWriteTests,
-        audiotests.AudioTestsWithSourceFile,
-        unittest.TestCase):
-    module = aifc
+class AifcPCM32Test(AifcTest, unittest.TestCase):
     sndfilename = 'pluck-pcm32.aiff'
     sndfilenframes = 3307
     nchannels = 2
@@ -107,13 +102,9 @@
       E4B49CC00CEA2D90 6344A8800A5A7CA0 08C8FE800A1FFEE0 2BB986C00B0A0E00 \
       51486F800E44E190 8BCC6480113B0580 B6F4EC000EEB3630 441317800A5B48A0 \
       """)
-    close_fd = True
 
 
-class AifcULAWTest(audiotests.AudioWriteTests,
-        audiotests.AudioTestsWithSourceFile,
-        unittest.TestCase):
-    module = aifc
+class AifcULAWTest(AifcTest, unittest.TestCase):
     sndfilename = 'pluck-ulaw.aifc'
     sndfilenframes = 3307
     nchannels = 2
@@ -132,13 +123,9 @@
       """)
     if sys.byteorder != 'big':
         frames = audiotests.byteswap2(frames)
-    close_fd = True
 
 
-class AifcALAWTest(audiotests.AudioWriteTests,
-        audiotests.AudioTestsWithSourceFile,
-        unittest.TestCase):
-    module = aifc
+class AifcALAWTest(AifcTest, unittest.TestCase):
     sndfilename = 'pluck-alaw.aifc'
     sndfilenframes = 3307
     nchannels = 2
@@ -157,7 +144,6 @@
       """)
     if sys.byteorder != 'big':
         frames = audiotests.byteswap2(frames)
-    close_fd = True
 
 
 class AifcMiscTest(audiotests.AudioTests, unittest.TestCase):
diff --git a/Lib/wave.py b/Lib/wave.py
index e723423..3d01817 100644
--- a/Lib/wave.py
+++ b/Lib/wave.py
@@ -491,14 +491,18 @@
         if not self._nframes:
             self._nframes = initlength // (self._nchannels * self._sampwidth)
         self._datalength = self._nframes * self._nchannels * self._sampwidth
-        self._form_length_pos = self._file.tell()
+        try:
+            self._form_length_pos = self._file.tell()
+        except (AttributeError, OSError):
+            self._form_length_pos = None
         self._file.write(struct.pack('<L4s4sLHHLLHH4s',
             36 + self._datalength, b'WAVE', b'fmt ', 16,
             WAVE_FORMAT_PCM, self._nchannels, self._framerate,
             self._nchannels * self._framerate * self._sampwidth,
             self._nchannels * self._sampwidth,
             self._sampwidth * 8, b'data'))
-        self._data_length_pos = self._file.tell()
+        if self._form_length_pos is not None:
+            self._data_length_pos = self._file.tell()
         self._file.write(struct.pack('<L', self._datalength))
         self._headerwritten = True