Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 3ecfea7

Browse files
committed
Merged revisions 60481,60485,60489-60492,60494-60496,60498-60499,60501-60503,60505-60506,60508-60509,60523-60524,60532,60543,60545,60547-60548,60552,60554,60556-60559,60561-60562,60569,60571-60572,60574,60576-60583,60585-60586,60589,60591,60594-60595,60597-60598,60600-60601,60606-60612,60615,60617,60619-60621,60623-60625,60627-60629,60631,60633,60635,60647,60650,60652,60654,60656,60658-60659,60664-60666,60668-60670,60672,60676,60678-60695 via svnmerge from
svn+ssh://[email protected]/python/trunk ........ r60679 | raymond.hettinger | 2008-02-09 02:18:42 +0100 (Sat, 09 Feb 2008) | 1 line Make ABC containers inherit as documented. ........ r60684 | raymond.hettinger | 2008-02-09 04:34:52 +0100 (Sat, 09 Feb 2008) | 1 line Merge with r60683. ........ r60687 | raymond.hettinger | 2008-02-09 05:37:49 +0100 (Sat, 09 Feb 2008) | 1 line Add -3 warnings that set.copy(), dict.copy(), and defaultdict.copy() will go away in Py3.x ........ r60689 | raymond.hettinger | 2008-02-09 11:04:19 +0100 (Sat, 09 Feb 2008) | 1 line Metaclass declaration is inherited ........ r60691 | raymond.hettinger | 2008-02-09 11:06:20 +0100 (Sat, 09 Feb 2008) | 1 line Temporarily disable this test. It's been broken for a week. ........ r60695 | nick.coghlan | 2008-02-09 16:28:09 +0100 (Sat, 09 Feb 2008) | 1 line Issue 2021: Allow NamedTemporaryFile and SpooledTemporaryFile to be used as context managers. (The NamedTemporaryFile fix should be considered for backporting to 2.5) ........
1 parent bfd0612 commit 3ecfea7

6 files changed

Lines changed: 116 additions & 22 deletions

File tree

Doc/library/tempfile.rst

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ The module defines the following user-callable functions:
5151

5252
The returned object is a true file object on POSIX platforms. On other
5353
platforms, it is a file-like object whose :attr:`file` attribute is the
54-
underlying true file object.
54+
underlying true file object. This file-like object can be used in a :keyword:`with`
55+
statement, just like a normal file.
5556

5657

5758
.. function:: NamedTemporaryFile([mode='w+b'[, bufsize=-1[, suffix[, prefix[, dir[, delete]]]]]])
@@ -64,7 +65,8 @@ The module defines the following user-callable functions:
6465
across platforms (it can be so used on Unix; it cannot on Windows NT or later).
6566
If *delete* is true (the default), the file is deleted as soon as it is closed.
6667
The returned object is always a file-like object whose :attr:`file` attribute
67-
is the underlying true file object.
68+
is the underlying true file object. This file-like object can be used in a :keyword:`with`
69+
statement, just like a normal file.
6870

6971

7072
.. function:: SpooledTemporaryFile([max_size=0, [mode='w+b'[, bufsize=-1[, suffix[, prefix[, dir]]]]]])
@@ -79,7 +81,8 @@ The module defines the following user-callable functions:
7981

8082
The returned object is a file-like object whose :attr:`_file` attribute
8183
is either a :class:`StringIO` object or a true file object, depending on
82-
whether :func:`rollover` has been called.
84+
whether :func:`rollover` has been called. This file-like object can be used in a
85+
:keyword:`with` statement, just like a normal file.
8386

8487

8588
.. function:: mkstemp([suffix[, prefix[, dir[, text]]]])

Lib/io.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,7 @@ def _checkClosed(self, msg=None):
365365

366366
def __enter__(self) -> "IOBase": # That's a forward reference
367367
"""Context management protocol. Returns self."""
368+
self._checkClosed()
368369
return self
369370

370371
def __exit__(self, *args) -> None:

Lib/tempfile.py

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,7 @@ def mktemp(suffix="", prefix=template, dir=None):
363363

364364
raise IOError(_errno.EEXIST, "No usable temporary filename found")
365365

366+
366367
class _TemporaryFileWrapper:
367368
"""Temporary file wrapper
368369
@@ -378,17 +379,25 @@ def __init__(self, file, name, delete=True):
378379
self.delete = delete
379380

380381
def __getattr__(self, name):
382+
# Attribute lookups are delegated to the underlying file
383+
# and cached for non-numeric results
384+
# (i.e. methods are cached, closed and friends are not)
381385
file = self.__dict__['file']
382386
a = getattr(file, name)
383-
if type(a) != type(0):
387+
if not isinstance(a, int):
384388
setattr(self, name, a)
385389
return a
386390

391+
# The underlying __enter__ method returns the wrong object
392+
# (self.file) so override it to return the wrapper
393+
def __enter__(self):
394+
self.file.__enter__()
395+
return self
396+
387397
# NT provides delete-on-close as a primitive, so we don't need
388398
# the wrapper to do anything special. We still use it so that
389399
# file.name is useful (i.e. not "(fdopen)") with NamedTemporaryFile.
390400
if _os.name != 'nt':
391-
392401
# Cache the unlinker so we don't get spurious errors at
393402
# shutdown when the module-level "os" is None'd out. Note
394403
# that this must be referenced as self.unlink, because the
@@ -406,6 +415,14 @@ def close(self):
406415
def __del__(self):
407416
self.close()
408417

418+
# Need to trap __exit__ as well to ensure the file gets
419+
# deleted when used in a with statement
420+
def __exit__(self, exc, value, tb):
421+
result = self.file.__exit__(exc, value, tb)
422+
self.close()
423+
return result
424+
425+
409426
def NamedTemporaryFile(mode='w+b', buffering=-1, encoding=None,
410427
newline=None, suffix="", prefix=template,
411428
dir=None, delete=True):
@@ -523,6 +540,20 @@ def rollover(self):
523540

524541
self._rolled = True
525542

543+
# The method caching trick from NamedTemporaryFile
544+
# won't work here, because _file may change from a
545+
# _StringIO instance to a real file. So we list
546+
# all the methods directly.
547+
548+
# Context management protocol
549+
def __enter__(self):
550+
if self._file.closed:
551+
raise ValueError("Cannot enter context with closed file")
552+
return self
553+
554+
def __exit__(self, exc, value, tb):
555+
self._file.close()
556+
526557
# file protocol
527558
def __iter__(self):
528559
return self._file.__iter__()

Lib/test/test_sys.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -336,17 +336,17 @@ def test_clear_type_cache(self):
336336
def test_compact_freelists(self):
337337
sys._compact_freelists()
338338
r = sys._compact_freelists()
339-
# freed blocks shouldn't change
340-
self.assertEqual(r[0][2], 0)
341-
# fill freelists
342-
ints = list(range(10000))
343-
floats = [float(i) for i in ints]
344-
del ints
345-
del floats
346-
# should free more than 100 blocks
347-
r = sys._compact_freelists()
348-
self.assert_(r[0][1] > 100, r[0][1])
349-
self.assert_(r[0][2] > 100, r[0][2])
339+
## freed blocks shouldn't change
340+
#self.assertEqual(r[0][2], 0)
341+
## fill freelists
342+
#ints = list(range(10000))
343+
#floats = [float(i) for i in ints]
344+
#del ints
345+
#del floats
346+
## should free more than 100 blocks
347+
#r = sys._compact_freelists()
348+
#self.assert_(r[0][1] > 100, r[0][1])
349+
#self.assert_(r[0][2] > 100, r[0][2])
350350

351351
def test_main():
352352
test.test_support.run_unittest(SysModuleTest)

Lib/test/test_tempfile.py

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
# tempfile.py unit tests.
2-
32
import tempfile
43
import os
54
import sys
@@ -619,7 +618,6 @@ def test_dis_del_on_close(self):
619618

620619
def test_multiple_close(self):
621620
# A NamedTemporaryFile can be closed many times without error
622-
623621
f = tempfile.NamedTemporaryFile()
624622
f.write(b'abc\n')
625623
f.close()
@@ -629,6 +627,16 @@ def test_multiple_close(self):
629627
except:
630628
self.failOnException("close")
631629

630+
def test_context_manager(self):
631+
# A NamedTemporaryFile can be used as a context manager
632+
with tempfile.NamedTemporaryFile() as f:
633+
self.failUnless(os.path.exists(f.name))
634+
self.failIf(os.path.exists(f.name))
635+
def use_closed():
636+
with f:
637+
pass
638+
self.failUnlessRaises(ValueError, use_closed)
639+
632640
# How to test the mode and bufsize parameters?
633641

634642
test_classes.append(test_NamedTemporaryFile)
@@ -707,10 +715,23 @@ def test_fileno(self):
707715
self.failUnless(f.fileno() > 0)
708716
self.failUnless(f._rolled)
709717

710-
def test_multiple_close(self):
718+
def test_multiple_close_before_rollover(self):
711719
# A SpooledTemporaryFile can be closed many times without error
712720
f = tempfile.SpooledTemporaryFile()
713721
f.write(b'abc\n')
722+
self.failIf(f._rolled)
723+
f.close()
724+
try:
725+
f.close()
726+
f.close()
727+
except:
728+
self.failOnException("close")
729+
730+
def test_multiple_close_after_rollover(self):
731+
# A SpooledTemporaryFile can be closed many times without error
732+
f = tempfile.SpooledTemporaryFile(max_size=1)
733+
f.write(b'abc\n')
734+
self.failUnless(f._rolled)
714735
f.close()
715736
try:
716737
f.close()
@@ -759,6 +780,46 @@ def test_text_newline_and_encoding(self):
759780
self.assertEqual(f.read(), "\u039B\r\n" + ("\u039B" * 20) + "\r\n")
760781
self.failUnless(f._rolled)
761782

783+
def test_context_manager_before_rollover(self):
784+
# A SpooledTemporaryFile can be used as a context manager
785+
with tempfile.SpooledTemporaryFile(max_size=1) as f:
786+
self.failIf(f._rolled)
787+
self.failIf(f.closed)
788+
self.failUnless(f.closed)
789+
def use_closed():
790+
with f:
791+
pass
792+
self.failUnlessRaises(ValueError, use_closed)
793+
794+
def test_context_manager_during_rollover(self):
795+
# A SpooledTemporaryFile can be used as a context manager
796+
with tempfile.SpooledTemporaryFile(max_size=1) as f:
797+
self.failIf(f._rolled)
798+
f.write(b'abc\n')
799+
f.flush()
800+
self.failUnless(f._rolled)
801+
self.failIf(f.closed)
802+
self.failUnless(f.closed)
803+
def use_closed():
804+
with f:
805+
pass
806+
self.failUnlessRaises(ValueError, use_closed)
807+
808+
def test_context_manager_after_rollover(self):
809+
# A SpooledTemporaryFile can be used as a context manager
810+
f = tempfile.SpooledTemporaryFile(max_size=1)
811+
f.write(b'abc\n')
812+
f.flush()
813+
self.failUnless(f._rolled)
814+
with f:
815+
self.failIf(f.closed)
816+
self.failUnless(f.closed)
817+
def use_closed():
818+
with f:
819+
pass
820+
self.failUnlessRaises(ValueError, use_closed)
821+
822+
762823
test_classes.append(test_SpooledTemporaryFile)
763824

764825

Modules/_collectionsmodule.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,7 +1127,7 @@ defdict_copy(defdictobject *dd)
11271127
{
11281128
/* This calls the object's class. That only works for subclasses
11291129
whose class constructor has the same signature. Subclasses that
1130-
define a different constructor signature must override copy().
1130+
define a different constructor signature must override __copy__().
11311131
*/
11321132
return PyObject_CallFunctionObjArgs((PyObject*)Py_TYPE(dd),
11331133
dd->default_factory, dd, NULL);
@@ -1182,8 +1182,6 @@ defdict_reduce(defdictobject *dd)
11821182
static PyMethodDef defdict_methods[] = {
11831183
{"__missing__", (PyCFunction)defdict_missing, METH_O,
11841184
defdict_missing_doc},
1185-
{"copy", (PyCFunction)defdict_copy, METH_NOARGS,
1186-
defdict_copy_doc},
11871185
{"__copy__", (PyCFunction)defdict_copy, METH_NOARGS,
11881186
defdict_copy_doc},
11891187
{"__reduce__", (PyCFunction)defdict_reduce, METH_NOARGS,

0 commit comments

Comments
 (0)