Amaury Forgeot d'Arc avatar Amaury Forgeot d'Arc committed f634999

cpyext: Implement PyFile_WriteObject() and PyFile_SoftSpace()

Comments (0)

Files changed (2)

pypy/module/cpyext/pyfile.py

 from pypy.rpython.lltypesystem import rffi, lltype
 from pypy.module.cpyext.api import (
-    cpython_api, CONST_STRING, FILEP, build_type_checkers)
+    cpython_api, CANNOT_FAIL, CONST_STRING, FILEP, build_type_checkers)
 from pypy.module.cpyext.pyobject import PyObject, borrow_from
+from pypy.module.cpyext.object import Py_PRINT_RAW
 from pypy.interpreter.error import OperationError
 from pypy.module._file.interp_file import W_File
 
 def PyFile_WriteString(space, s, w_p):
     """Write string s to file object p.  Return 0 on success or -1 on
     failure; the appropriate exception will be set."""
-    w_s = space.wrap(rffi.charp2str(s))
-    space.call_method(w_p, "write", w_s)
+    w_str = space.wrap(rffi.charp2str(s))
+    space.call_method(w_p, "write", w_str)
+    return 0
+
+@cpython_api([PyObject, PyObject, rffi.INT_real], rffi.INT_real, error=-1)
+def PyFile_WriteObject(space, w_obj, w_p, flags):
+    """
+    Write object obj to file object p.  The only supported flag for flags is
+    Py_PRINT_RAW; if given, the str() of the object is written
+    instead of the repr().  Return 0 on success or -1 on failure; the
+    appropriate exception will be set."""
+    if rffi.cast(lltype.Signed, flags) & Py_PRINT_RAW:
+        w_str = space.str(w_obj)
+    else:
+        w_str = space.repr(w_obj)
+    space.call_method(w_p, "write", w_str)
     return 0
 
 @cpython_api([PyObject], PyObject)
 def PyFile_Name(space, w_p):
     """Return the name of the file specified by p as a string object."""
-    return borrow_from(w_p, space.getattr(w_p, space.wrap("name")))
+    return borrow_from(w_p, space.getattr(w_p, space.wrap("name")))
+
+@cpython_api([PyObject, rffi.INT_real], rffi.INT_real, error=CANNOT_FAIL)
+def PyFile_SoftSpace(space, w_p, newflag):
+    """
+    This function exists for internal use by the interpreter.  Set the
+    softspace attribute of p to newflag and return the previous value.
+    p does not have to be a file object for this function to work
+    properly; any object is supported (thought its only interesting if
+    the softspace attribute can be set).  This function clears any
+    errors, and will return 0 as the previous value if the attribute
+    either does not exist or if there were errors in retrieving it.
+    There is no way to detect errors from this function, but doing so
+    should not be needed."""
+    try:
+        if newflag:
+            w_newflag = space.w_True
+        else:
+            w_newflag = space.w_False
+        oldflag = space.int_w(space.getattr(w_p, space.wrap("softspace")))
+        space.setattr(w_p, space.wrap("softspace"), w_newflag)
+        return oldflag
+    except OperationError, e:
+        return 0
+

pypy/module/cpyext/test/test_pyfile.py

 from pypy.module.cpyext.api import fopen, fclose, fwrite
 from pypy.module.cpyext.test.test_api import BaseApiTest
+from pypy.module.cpyext.object import Py_PRINT_RAW
 from pypy.rpython.lltypesystem import rffi, lltype
 from pypy.tool.udir import udir
 import pytest
         out = out.replace('\r\n', '\n')
         assert out == "test\n"
 
+    def test_file_writeobject(self, space, api, capfd):
+        w_obj = space.wrap("test\n")
+        w_stdout = space.sys.get("stdout")
+        api.PyFile_WriteObject(w_obj, w_stdout, Py_PRINT_RAW)
+        api.PyFile_WriteObject(w_obj, w_stdout, 0)
+        space.call_method(w_stdout, "flush")
+        out, err = capfd.readouterr()
+        out = out.replace('\r\n', '\n')
+        assert out == "test\n'test\\n'"
+
+    def test_file_softspace(self, space, api, capfd):
+        w_stdout = space.sys.get("stdout")
+        assert api.PyFile_SoftSpace(w_stdout, 1) == 0
+        assert api.PyFile_SoftSpace(w_stdout, 0) == 1
+        
+        api.PyFile_SoftSpace(w_stdout, 1)
+        w_ns = space.newdict()
+        space.exec_("print 1,", w_ns, w_ns)
+        space.exec_("print 2,", w_ns, w_ns)
+        api.PyFile_SoftSpace(w_stdout, 0)
+        space.exec_("print 3", w_ns, w_ns)
+        space.call_method(w_stdout, "flush")
+        out, err = capfd.readouterr()
+        out = out.replace('\r\n', '\n')
+        assert out == " 1 23\n"
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.