diff -r d35fc6e58a70 Lib/tempfile.py --- a/Lib/tempfile.py Sun Dec 04 22:59:09 2016 +0100 +++ b/Lib/tempfile.py Wed Dec 07 07:43:44 2016 -0800 @@ -447,7 +447,10 @@ # Need to ensure the file is deleted on __del__ def __del__(self): - self.close() + if not self.close_called and self.file is not None: + _warnings.warn('unclosed file %r' % self, ResourceWarning, + stacklevel=2, source=self) + self.close() else: def close(self): diff -r d35fc6e58a70 Lib/test/test_tempfile.py --- a/Lib/test/test_tempfile.py Sun Dec 04 22:59:09 2016 +0100 +++ b/Lib/test/test_tempfile.py Wed Dec 07 07:43:44 2016 -0800 @@ -957,6 +957,14 @@ tempfile.NamedTemporaryFile(mode=2, dir=dir) self.assertEqual(os.listdir(dir), []) + def test_resource_warning_on_destructor(self): + file = tempfile.NamedTemporaryFile() + with warnings.catch_warnings(record=True) as w: + del file + self.assertEqual(len(w), 1) + self.assertEqual(w[-1].category, ResourceWarning) + self.assertIn('unclosed file', str(w[-1].message)) + # How to test the mode and bufsize parameters? class TestSpooledTemporaryFile(BaseTestCase): diff -r d35fc6e58a70 Lib/test/test_urllib2.py --- a/Lib/test/test_urllib2.py Sun Dec 04 22:59:09 2016 +0100 +++ b/Lib/test/test_urllib2.py Wed Dec 07 07:43:44 2016 -0800 @@ -739,18 +739,18 @@ ]: req = Request(url) req.timeout = None - r = h.ftp_open(req) - # ftp authentication not yet implemented by FTPHandler - self.assertEqual(h.user, user) - self.assertEqual(h.passwd, passwd) - self.assertEqual(h.host, socket.gethostbyname(host)) - self.assertEqual(h.port, port) - self.assertEqual(h.dirs, dirs) - self.assertEqual(h.ftpwrapper.filename, filename) - self.assertEqual(h.ftpwrapper.filetype, type_) - headers = r.info() - self.assertEqual(headers.get("Content-type"), mimetype) - self.assertEqual(int(headers["Content-length"]), len(data)) + with h.ftp_open(req) as r: + # ftp authentication not yet implemented by FTPHandler + self.assertEqual(h.user, user) + self.assertEqual(h.passwd, passwd) + self.assertEqual(h.host, socket.gethostbyname(host)) + self.assertEqual(h.port, port) + self.assertEqual(h.dirs, dirs) + self.assertEqual(h.ftpwrapper.filename, filename) + self.assertEqual(h.ftpwrapper.filetype, type_) + headers = r.info() + self.assertEqual(headers.get("Content-type"), mimetype) + self.assertEqual(int(headers["Content-length"]), len(data)) def test_file(self): import email.utils @@ -1167,10 +1167,11 @@ try: method(req, MockFile(), code, "Blah", MockHeaders({"location": to_url})) - except urllib.error.HTTPError: + except urllib.error.HTTPError as e: # 307 in response to POST requires user OK self.assertEqual(code, 307) self.assertIsNotNone(data) + e.close() self.assertEqual(o.req.get_full_url(), to_url) try: self.assertEqual(o.req.get_method(), "GET") @@ -1206,9 +1207,10 @@ while 1: redirect(h, req, "http://example.com/") count = count + 1 - except urllib.error.HTTPError: + except urllib.error.HTTPError as e: # don't stop until max_repeats, because cookies may introduce state self.assertEqual(count, urllib.request.HTTPRedirectHandler.max_repeats) + e.close() # detect endless non-repeating chain of redirects req = Request(from_url, origin_req_host="example.com") @@ -1218,9 +1220,10 @@ while 1: redirect(h, req, "http://example.com/%d" % count) count = count + 1 - except urllib.error.HTTPError: + except urllib.error.HTTPError as e: self.assertEqual(count, urllib.request.HTTPRedirectHandler.max_redirections) + e.close() def test_invalid_redirect(self): from_url = "http://example.com/a.html" @@ -1234,9 +1237,13 @@ for scheme in invalid_schemes: invalid_url = scheme + '://' + schemeless_url - self.assertRaises(urllib.error.HTTPError, h.http_error_302, - req, MockFile(), 302, "Security Loophole", - MockHeaders({"location": invalid_url})) + with self.assertRaises(urllib.error.HTTPError): + try: + h.http_error_302(req, MockFile(), 302, "Security Loophole", + MockHeaders({"location": invalid_url})) + except urllib.error.HTTPError as e: + e.close() + raise for scheme in valid_schemes: valid_url = scheme + '://' + schemeless_url