[Python-Dev] PEP 384 status

Nick Coghlan ncoghlan at gmail.com
Sun Aug 29 01:20:56 CEST 2010


On Sun, Aug 29, 2010 at 4:52 AM, "Martin v. Löwis" <martin at v.loewis.de> wrote:
>> This is from tp_new and tp_dealloc, right? I think we should probably
>> provide assessors PyObject_Alloc and PyObject_FreeObject.
>
> Correct, and yes, that sounds like a good approach.
>
>>> - PyObject_Print is used, but can't be supported, as it uses a FILE*
>>>  parameter
>>
>> I thought tp_print was supposed to have been removed.
>
> Yes - that should have happened for 3.0. Not sure how to deal with it now.

tp_print actually is gone, but PyObject_Print was retained. It just
relies on repr() and str() under the hood instead of the old tp_print
slot.

There are 4 operations performed on fp in that function: clearerr,
ferror, fprintf and fwrite.

There is also an implicit reference to errno (through
PyErr_SetFromErrno) which can't be trusted in a mixed CRT world
(PyErr_SetFromErrno() should be excluded from the Limited API, if it
isn't already, and replaced with a PyErr_SetFromErrnoEx which takes
the errno as an explicit argument. That assumes the CRTs will be
sufficiently compatible that strerror() will give the correct answer
for errno values from the other CRT. If that assumption is incorrect,
the new function would also need to accept a string argument for the
error description).

Four options come to mind:

- just leave it out of the limited API, extensions can do their own
thing to print objects
- leave PyObject_Print out of the limited API, but create a
PyObject_PrintEx that takes a Python IO stream via PyObject* rather
than a C level FILE*.
- leave PyObject_Print out of the limited API, but create a
PyObject_PrintEx that takes function pointers for the above 4
operations (so the FILE* pointer is only every operated on by
functions from the extension module's CRT)
- leave PyObject_Print out of the limited API, but create a
PyObject_PRINT macro that does much the same thing with the logic
rearranged so there is an inner function that figures out the string
to be printed, but an outer macro that does all the operations on the
FILE * object (so again, the FILE * is never passed to Python's CRT)

The last option requires the fewest adjustments for extension authors,
and it should be feasible to do it that way (even though it is a bit
of a hack). Something along the lines of the following:

#define PyObject_PRINT (obj, fp, flags, resultp) \
{ \
  int _result = -1;
  _t = _PyObject_PrintInner(obj, flags); \
  if (_t != NULL) { \
    clearerr(fp); \
    fwrite(PyBytes_AS_STRING(_t), 1, PyBytes_GET_SIZE(_t), fp); \
    Py_DECREF(_t); \
    if (ferror(fp)) { \
      PyErr_SetFromErrnoEx(PyExc_IOError, errno); \
      clearerr(fp); \
    } else { \
      _result = 0; \
    } \
  } \
  if (resultp != NULL) { \
    *resultp = _result; \
  } \
}


Cheers,
Nick.

-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia


More information about the Python-Dev mailing list