# based on Andrew Kuchling's minigzip.py distributed with the zlib module
-import struct, sys, time, os
-import zlib
+import _compression
import builtins
import io
-import _compression
+import os
+import struct
+import sys
+import time
+import weakref
+import zlib
__all__ = ["BadGzipFile", "GzipFile", "open", "compress", "decompress"]
class _WriteBufferStream(io.RawIOBase):
"""Minimal object to pass WriteBuffer flushes into GzipFile"""
def __init__(self, gzip_file):
- self.gzip_file = gzip_file
+ self.gzip_file = weakref.ref(gzip_file)
def write(self, data):
- return self.gzip_file._write_raw(data)
+ gzip_file = self.gzip_file()
+ if gzip_file is None:
+ raise RuntimeError("lost gzip_file")
+ return gzip_file._write_raw(data)
def seekable(self):
return False
import array
import functools
+import gc
import io
import os
import struct
import sys
import unittest
from subprocess import PIPE, Popen
+from test.support import catch_unraisable_exception
from test.support import import_helper
from test.support import os_helper
from test.support import _4G, bigmemtest, requires_subprocess
self.assertEqual(gzip.decompress(data), message * 2)
+ def test_refloop_unraisable(self):
+ # Ensure a GzipFile referring to a temporary fileobj deletes cleanly.
+ # Previously an unraisable exception would occur on close because the
+ # fileobj would be closed before the GzipFile as the result of a
+ # reference loop. See issue gh-129726
+ with catch_unraisable_exception() as cm:
+ gzip.GzipFile(fileobj=io.BytesIO(), mode="w")
+ gc.collect()
+ self.assertIsNone(cm.unraisable)
+
+
class TestOpen(BaseTest):
def test_binary_modes(self):
uncompressed = data1 * 50