summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Peterson <benjamin@python.org>2019-08-29 05:05:57 -0700
committerChris Dent <cdent@anticdent.org>2019-08-29 13:05:57 +0100
commitcdd2a9a58c59b8e599aa42b66b3c55ea47c7a4b7 (patch)
tree447ac76f8db6b158e7217377e245443a4f911440
parent9eff34df99e9488cec65b21c95e777414c61a379 (diff)
downloadpaste-git-cdd2a9a58c59b8e599aa42b66b3c55ea47c7a4b7.tar.gz
Avoid copying FieldStorage if possible. (#30)
On Python 3, cgi.FieldStorage has a __del__ method that closes the underlying file [1]. This means that if the copy made from UnicodeMultiDict._decode_value is garbage collected, the file underlying the original FieldStorage will be closed! Fix this by not copying FieldStorage if it is not required by decode_keys=False. I cannot think of a nice way to fix this problem if decode_keys=True. [1] https://github.com/python/cpython/commit/f79126f373a9d5c9b584a8db736fe490fcbfa77a
-rw-r--r--paste/util/multidict.py12
-rw-r--r--tests/test_multidict.py13
2 files changed, 15 insertions, 10 deletions
diff --git a/paste/util/multidict.py b/paste/util/multidict.py
index 0b63ebb..0a304d3 100644
--- a/paste/util/multidict.py
+++ b/paste/util/multidict.py
@@ -265,11 +265,13 @@ class UnicodeMultiDict(DictMixin):
"""
if isinstance(value, cgi.FieldStorage):
# decode FieldStorage's field name and filename
- value = copy.copy(value)
- if self.decode_keys and isinstance(value.name, six.binary_type):
- value.name = value.name.decode(self.encoding, self.errors)
- if six.PY2:
- value.filename = value.filename.decode(self.encoding, self.errors)
+ decode_name = self.decode_keys and isinstance(value.name, six.binary_type)
+ if six.PY2 or decode_name:
+ value = copy.copy(value)
+ if decode_name:
+ value.name = value.name.decode(self.encoding, self.errors)
+ if six.PY2:
+ value.filename = value.filename.decode(self.encoding, self.errors)
else:
try:
value = value.decode(self.encoding, self.errors)
diff --git a/tests/test_multidict.py b/tests/test_multidict.py
index a33c13b..f6619fc 100644
--- a/tests/test_multidict.py
+++ b/tests/test_multidict.py
@@ -2,10 +2,11 @@
# (c) 2007 Ian Bicking and Philip Jenvey; written for Paste (http://pythonpaste.org)
# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
import cgi
+import gc
+import io
import pytest
import six
-from six.moves import StringIO
from paste.util.multidict import MultiDict, UnicodeMultiDict
@@ -149,14 +150,16 @@ def _test_unicode_dict(decode_param_names=False):
fs = cgi.FieldStorage()
fs.name = 'thefile'
fs.filename = 'hello.txt'
- fs.file = StringIO('hello')
+ fs.file = io.BytesIO(b'hello')
d[k('f')] = fs
ufs = d[k('f')]
assert isinstance(ufs, cgi.FieldStorage)
- assert ufs is not fs
assert ufs.name == fs.name
assert isinstance(ufs.name, str if six.PY3 else key_str)
assert ufs.filename == fs.filename
assert isinstance(ufs.filename, six.text_type)
- assert isinstance(ufs.value, str)
- assert ufs.value == 'hello'
+ assert isinstance(ufs.value, bytes)
+ assert ufs.value == b'hello'
+ ufs = None
+ gc.collect()
+ assert not fs.file.closed