Bradley Froehle added the comment: First off, thanks for all the work so far. This has proven incredibly useful to me in a personal project.
However, I think there needs to be some additional discussion of how to handle situations where the arguments passed to PyArg_ParseTuple require additional cleanup. As a prototypical example, I'll consider filename arguments. The Python docs recommend that filename arguments be handled with `O&` and PyUnicode_FSConverter. How can we handle this in clinic? 1. No special handling in clinic: /*[clinic] foo -> None PyObject *filename [clinic]*/ ... foo_impl(PyObject *self, PyObject *filename) /*[clinic end:...*/ { char *c_filename; PyObject *b_filename; if (!PyUnicode_FSConverter(filename, &b_filename)) return NULL; c_filename = PyBytes_AsString(b_filename); // ... Py_DECREF(b_filename); } This offloads all of the processing to the impl function and leaves us no better off. Unacceptable. 2. Use PyObject* and a converter option: /*[clinic] foo -> None PyBytesObject *filename converter=PyUnicode_FSConverter [clinic]*/ ... foo_impl(PyObject *self, PyBytesObject *filename) /*[clinic end:...]*/ { char *c_filename = PyBytes_AsString(filename); ... Py_DECREF(filename); } This is much more convenient, but the `_impl` function now steals the filename reference, which is unexpected (and confusing). 3. "The dream" Ideally `foo_impl` would have a signature like: static PyObject * foo_impl(PyObject *self, char *filename); And `foo` would be automatically generated as: static PyObject * foo(PyObject *self, PyObject *args, PyObject *kwargs) { PyObject *_ret; PyObject *filename; static char *_keywords[] = {"filename", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&:foo", _keywords, PyUnicode_FSConverter, &filename)) return NULL; _ret = foo_impl(self, PyBytes_AsString(filename)); Py_DECREF(filename); return _ret; } It's not clear to me how one would extend the clinic syntax to support this. In particular, clinic would need to know: - The type of the intermediate object (i.e., PyObject * or PyBytesObject *). - The converter to use in PyArg_ParseTupleAndKeywords (i.e., PyUnicode_FSConverter) - The impl type (i.e, char *) - How to convert the intermediate object to the impl type (i.e., PyBytes_AsString(filename)). - How to cleanup in the end (i.e., Py_DECREF(filename)). This seems like too much data to encode in the clinic syntax. 4. Extend clinic to add a cleanup flag which would produce code like: /*[clinic] foo PyBytesObject *filename converter=PyUnicode_FSConverter cleanup=Py_DECREF [clinic]*/ ... static PyObject * foo(PyObject *self, PyObject *args, PyObject *kwargs) { PyObject *_ret; PyBytesObject *filename; static char *_keywords[] = {"filename", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&:foo", _keywords, PyUnicode_FSConverter, &filename)) return NULL; _ret = foo_impl(self, filename); Py_DECREF(filename); return _ret; } static PyObject * foo_impl(PyObject *self, PyBytesObject *filename) /*[clinic end:...]*/ { char *c_filename = PyBytes_AsString(filename); // ... } This seems like a relatively modest addition, which might also work for other cleanup functions like PyBuffer_Release. ---- Additionally, there are a few other bugs I've noticed: - The s* and z* codes should be of type Py_buffer (and not Py_buffer *) - Since Py_buffer is a relatively large struct, zlib_decompress_impl should probably take a pointer to a Py_buffer. This, however, would likely require extending the clinic syntax. ---------- _______________________________________ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue16612> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com