From 4369a851ff2a539dcffbbdbba43271a20a8c8fe6 Mon Sep 17 00:00:00 2001
From: Berker Peksag <berker.peksag@gmail.com>
Date: Fri, 6 Feb 2015 10:21:37 +0200
Subject: [PATCH] Issue #20289: cgi.FieldStorage() now supports the context
 management protocol.

---
 Doc/library/cgi.rst  |  7 +++++++
 Doc/whatsnew/3.5.rst |  6 ++++++
 Lib/cgi.py           |  6 ++++++
 Lib/test/test_cgi.py | 19 +++++++++++++------
 Misc/NEWS            |  3 +++
 5 files changed, 35 insertions(+), 6 deletions(-)

diff --git a/Doc/library/cgi.rst b/Doc/library/cgi.rst
index fa131453c79..0a9e8842802 100644
--- a/Doc/library/cgi.rst
+++ b/Doc/library/cgi.rst
@@ -157,6 +157,9 @@ return bytes)::
            if not line: break
            linecount = linecount + 1
 
+:class:`FieldStorage` objects also support being used in a :keyword:`with`
+statement, which will automatically close them when done.
+
 If an error is encountered when obtaining the contents of an uploaded file
 (for example, when the user interrupts the form submission by clicking on
 a Back or Cancel button) the :attr:`~FieldStorage.done` attribute of the
@@ -182,6 +185,10 @@ A form submitted via POST that also has a query string will contain both
    The :attr:`~FieldStorage.file` attribute is automatically closed upon the
    garbage collection of the creating :class:`FieldStorage` instance.
 
+.. versionchanged:: 3.5
+   Added support for the context management protocol to the
+   :class:`FieldStorage` class.
+
 
 Higher Level Interface
 ----------------------
diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst
index 979d24186ab..461a14b16fd 100644
--- a/Doc/whatsnew/3.5.rst
+++ b/Doc/whatsnew/3.5.rst
@@ -136,6 +136,12 @@ New Modules
 Improved Modules
 ================
 
+cgi
+---
+
+* :class:`FieldStorage` now supports the context management protocol.
+  (Contributed by Berker Peksag in :issue:`20289`.)
+
 code
 ----
 
diff --git a/Lib/cgi.py b/Lib/cgi.py
index 1ef780c11c4..a55232eb62d 100755
--- a/Lib/cgi.py
+++ b/Lib/cgi.py
@@ -566,6 +566,12 @@ class FieldStorage:
         except AttributeError:
             pass
 
+    def __enter__(self):
+        return self
+
+    def __exit__(self, *args):
+        self.file.close()
+
     def __repr__(self):
         """Return a printable representation."""
         return "FieldStorage(%r, %r, %r)" % (
diff --git a/Lib/test/test_cgi.py b/Lib/test/test_cgi.py
index 86e1f3a5f01..89a6e84df9d 100644
--- a/Lib/test/test_cgi.py
+++ b/Lib/test/test_cgi.py
@@ -1,4 +1,4 @@
-from test.support import run_unittest, check_warnings
+from test.support import check_warnings
 import cgi
 import os
 import sys
@@ -307,6 +307,17 @@ Content-Type: text/plain
                 got = getattr(files[x], k)
                 self.assertEqual(got, exp)
 
+    def test_fieldstorage_as_context_manager(self):
+        fp = BytesIO(b'x' * 10)
+        env = {'REQUEST_METHOD': 'PUT'}
+        with cgi.FieldStorage(fp=fp, environ=env) as fs:
+            content = fs.file.read()
+            self.assertFalse(fs.file.closed)
+        self.assertTrue(fs.file.closed)
+        self.assertEqual(content, 'x' * 10)
+        with self.assertRaisesRegex(ValueError, 'I/O operation on closed file'):
+            fs.file.read()
+
     _qs_result = {
         'key1': 'value1',
         'key2': ['value2x', 'value2y'],
@@ -481,9 +492,5 @@ Content-Transfer-Encoding: binary
 --AaB03x--
 """
 
-
-def test_main():
-    run_unittest(CgiTests)
-
 if __name__ == '__main__':
-    test_main()
+    unittest.main()
diff --git a/Misc/NEWS b/Misc/NEWS
index 25ea656b539..6e7cf75592c 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -235,6 +235,9 @@ Core and Builtins
 Library
 -------
 
+- Issue #20289: cgi.FieldStorage() now supports the context management
+  protocol.
+
 - Issue #13128: Print response headers for CONNECT requests when debuglevel
   > 0. Patch by Demian Brecht.
 
-- 
2.30.9