Recursive loading trouble for immutables
Mel
mwilson at the-wire.com
Sun Nov 25 12:07:56 EST 2007
Mel wrote:
> rekkufa wrote:
[ ... ]
>> How to load
>> data that specifies immutables that recursively reference
>> themselves.
> I can imagine a C function that might do it.
[ ... ]
Here's something that works, in the sense of creating a tuple
containing a self-reference. I don't know how dangerous it realliy is
-- haven't tested for memory leaks or any other large-scale trouble.
Also, I've only tested on Python 2.5.1 under Ubuntu Linux.
Called as
idiotuple.idiotuple (a_sequence, a_marker)
it returns a tuple containing the items of a_sequence, except that
instances of a_marker are replaced by references to the returned
tuple. Eg.:
import idiotuple
class IdioMarker: "An object that I will never insert into a tuple."
def showid (x):
print id(x)
for y in x:
print ' ', id(y)
showid (idiotuple.idiotuple ((1,2,3), IdioMarker))
showid (idiotuple.idiotuple ((1, IdioMarker, 3), IdioMarker))
The C code is:
/* $Id$ */
#include <Python.h>
/*=======================================================*/
static PyObject *idiotuple_idiotuple (PyObject *self, PyObject *args)
// In Python, call with
// sequence contents
// object marker
// returns
// tuple containing contents, with instances of marker
// replaced by borrowed self-references
{
PyObject *t = NULL;
PyObject *contents, *marker, *x;
Py_ssize_t i, n, z;
if (!PyArg_ParseTuple (args, "OO", &contents, &marker))
return NULL;
n = PySequence_Size (contents);
if (n < 0)
return NULL;
t = PyTuple_New (n); // new tuple
if (t == NULL)
return NULL;
for (i=0; i < n; ++i) {
x = PySequence_GetItem (contents, i); // new reference
if (x != marker) {
z = PyTuple_SetItem (t, i, x); // steals the new
reference to x
if (z == -1) {
goto fail;
}
}
if (x == marker) {
z = PyTuple_SetItem (t, i, t); // stolen reference to t
// Dereference the marker.
// The internal reference to the tuple is effectively
'borrowed'.
// Only external references to the tuple are reflected in
its reference count.
Py_DECREF (x); // dereference the marker
if (z == -1) {
goto fail;
}
}
}
return t;
fail:
Py_DECREF (t); // arrange for the tuple to go away
return NULL;
} /* idiotuple_idiotuple */
/*=======================================================*/
static PyMethodDef IdioTupleMethods[] = {
{"idiotuple", idiotuple_idiotuple, METH_VARARGS, "Create a
possibly self-referential tuple."},
{NULL, NULL, (int)NULL, NULL}
};
PyMODINIT_FUNC initidiotuple (void)
{
PyObject *module;
module = Py_InitModule ("idiotuple", IdioTupleMethods);
}
Setup.py is
# for use by distutils
from distutils.core import setup, Extension
module1 = Extension('idiotuple',
sources = ['idiotuple.c'])
setup (name = 'idiotuple',
version = '1.0',
description = 'Create a possibly self-referential tuple.',
author = 'Mel Wilson',
author_email = 'mwilson at the-wire.com',
ext_modules = [module1])
More information about the Python-list
mailing list