[pypy-svn] pypy default: file.__exit__ should call self.close, not file.close. Also brought some tests into the 21st century.

alex_gaynor commits-noreply at bitbucket.org
Fri Feb 11 15:23:18 CET 2011


Author: Alex Gaynor <alex.gaynor at gmail.com>
Branch: 
Changeset: r41821:f5278f05c3d1
Date: 2011-02-11 09:23 -0500
http://bitbucket.org/pypy/pypy/changeset/f5278f05c3d1/

Log:	file.__exit__ should call self.close, not file.close. Also brought
	some tests into the 21st century.

diff --git a/pypy/module/_file/interp_file.py b/pypy/module/_file/interp_file.py
--- a/pypy/module/_file/interp_file.py
+++ b/pypy/module/_file/interp_file.py
@@ -6,7 +6,7 @@
 from pypy.module._file.interp_stream import StreamErrors, wrap_streamerror
 from pypy.module.posix.interp_posix import dispatch_filename
 from pypy.interpreter.error import OperationError, operationerrfmt
-from pypy.interpreter.gateway import ObjSpace, W_Root, Arguments
+from pypy.interpreter.gateway import ObjSpace, W_Root, Arguments, unwrap_spec
 from pypy.interpreter.typedef import TypeDef, GetSetProperty
 from pypy.interpreter.typedef import interp_attrproperty, make_weakref_descr
 from pypy.interpreter.typedef import interp_attrproperty_w
@@ -95,14 +95,13 @@
         self.fdopenstream(stream, fd, mode)
 
     def direct___enter__(self):
-        if self.stream is None:
-            space = self.space
-            raise OperationError(space.w_ValueError,
-                                 space.wrap('I/O operation on closed file'))
+        self.check_closed()
         return self
 
-    def direct___exit__(self, __args__):
-        self.direct_close()
+    @unwrap_spec("self", Arguments)
+    def file__exit__(self, __args__):
+        """__exit__(*excinfo) -> None. Closes the file."""
+        self.space.call_method(self, "close")
         # can't return close() value
         return None
 
@@ -286,9 +285,6 @@
 
     _decl(locals(), "__enter__", ['self'], """__enter__() -> self.""")
 
-    _decl(locals(), "__exit__", ['self', Arguments], 
-        """__exit__(*excinfo) -> None. Closes the file.""")
-
     _decl(locals(), "close", ['self'],
         """close() -> None or (perhaps) an integer.  Close the file.
 
@@ -511,6 +507,7 @@
     __repr__ = interp2app(W_File.file__repr__),
     readinto = interp2app(W_File.file_readinto),
     writelines = interp2app(W_File.file_writelines),
+    __exit__ = interp2app(W_File.file__exit__),
     __weakref__ = make_weakref_descr(W_File),
     **dict([(name, interp2app(getattr(W_File, 'file_' + name)))
                 for name in W_File._exposed_method_names])

diff --git a/pypy/module/_file/test/test_file.py b/pypy/module/_file/test/test_file.py
--- a/pypy/module/_file/test/test_file.py
+++ b/pypy/module/_file/test/test_file.py
@@ -312,21 +312,30 @@
         assert f.closed
 
     def test_file_and_with_statement(self):
-        s1 = """from __future__ import with_statement
-with self.file(self.temppath, 'w') as f:
-    f.write('foo')
-"""
-        exec s1
+        with self.file(self.temppath, 'w') as f:
+            f.write('foo')
         assert f.closed
         
-        s2 = """from __future__ import with_statement
-with self.file(self.temppath, 'r') as f:
-    s = f.readline()
-"""
-    
-        exec s2
+        with self.file(self.temppath, 'r') as f:
+            s = f.readline()
+
         assert s == "foo"
         assert f.closed
+    
+    def test_subclass_with(self):
+        file = self.file
+        class C(file):
+            def __init__(self, *args, **kwargs):
+                self.subclass_closed = False
+                file.__init__(self, *args, **kwargs)
+            
+            def close(self):
+                self.subclass_closed = True
+                file.close(self)
+        
+        with C(self.temppath, 'w') as f:
+            pass
+        assert f.subclass_closed
 
 def test_flush_at_exit():
     from pypy import conftest


More information about the Pypy-commit mailing list