I finally found some spare time at home for implementing some good support. This will work from 2.3 to 3.0. Of course, the sets.Set and sets.ImmutableSet will only get used in 2.3, for version 2.4 and above, all this is a no-op, but you can use this in Cython code targeting all Python versions starting from 2.3.
You have attached the relevant files. 1) You have a 'cython.py' script. This script just add 'set' and 'frozenset' to __builtin__ module for the case of Python 2.3 . If this is not done, then Cython will not generate the C codes as appropriate, and will not understand 'cdef set s'. Then, for the case of Python 2.3, you have to run Cython using this script. If you use the Distutils support for building Cython extensions, then you will have to add the hackery in 'cython.py' to your 'setup.py'. 2) Place the files 'py23sets.h' and 'py23sets.pxd' as apropriate in your source tree. Then all what you need to do is the following: near the beginning of your pyx module sources, add these two lines: cimport py23sets py23sets.install() And now you are ready to use 'set'/'frozenset' !! 3) You have a 'test.pyx' file were the trick above is used in order to implement some testing. A nice thing of all this is that Cython does not require any modification for supporting sets in Py 2.3. But I believe that this could be more or less safely integrated in Cython. Dag, would you still object this? Could we provide a compiler directive perhaps? PS: Aaron, you owe me a beer ;-) On Fri, Oct 24, 2008 at 4:42 PM, Aaron DeVore <[EMAIL PROTECTED]> wrote: > Amendment: Could I use a compiler directive to import sets if /needed/. > > On Fri, Oct 24, 2008 at 12:17 PM, Aaron DeVore <[EMAIL PROTECTED]> wrote: >> Could I use a compiler directive to import sets if possible, then use >> another compiler directive to pick the type when using cdef? Example: >> >> IF PY_VERSION_HEX < 0x02040000: >> ----DEF USE_SETS_MODULE 1 >> ----from sets import Set as set >> >> Later in the file... >> >> cdef class Foo: >> ----IF USE_SETS_MODULE: >> --------cdef object member_set >> ----ELSE: >> --------cdef set member_set >> >> I haven't figured out how to import compiler directive constants from >> Python.h, hence the lack of me just trying it out on my own. >> >> -Aaron >> >> >>>>> Yes, it would be nice to have that. The idea would be to do the >>>>> Set import >>>>> internally, to provide replacement implementations for the generated >>>>> PySet_*() calls that work at the Python level, and to enable that >>>>> machinery when the C compile-time Python version is Py2.3. >>>>> However, that's >>>>> work that someone has to do. >>>>> >>>>> OTOH, this is a pure legacy feature for code that must run with >>>>> Py2.3. I >>>>> guess people (including myself) can currently live with the little >>>>> performance impact regarding the set operations (which are fast >>>>> anyway), >>>>> given the gain that their code runs unchanged in Py2.3. >>>> >>>> I wish I had the time and expertise for this. :( >>>> >>>> Would this work if put at the top of every file (dashes indicate >>>> indentation)? >>>> if not hasattr(__builtin__, "set"): >>>> ----from sets import Set as set >>>> >>>> or this >>>> try: >>>> ----set >>>> except NameError: >>>> ----from sets import Set as set >>>> >>>> It seems like there could be an issue with static typing using the >>>> imported Python class sets.Set (e.g. `cdef set foo`). I don't know >>>> enough about Cython to make a good guess on that one. >>> >>> I think one would have to do >>> >>> try: >>> from __builtin__ import set >>> except ImportError: >>> from sets import Set as set >>> >>> One couldn't, however, do "cdef set foo" because the symbol set would >>> need to be resolved at compile time, whereas the code (as above) >>> defers its value to runtime. Consequently the code using the >>> PySet_Xxxx api directly wouldn't get generated (which of course only >>> works for 2.4+) Hackery could be done in the compiler to emulate the >>> builtin set API (via calling the Set module's class), but it should >>> be noted that the speed gains we're talking about here for the most >>> part are not that large (compared to, say, indexing into a list or >>> tuple with an int where there are huge savings). >>> >>> - Robert >>> >>> _______________________________________________ >>> Cython-dev mailing list >>> [email protected] >>> http://codespeak.net/mailman/listinfo/cython-dev >>> >> > _______________________________________________ > Cython-dev mailing list > [email protected] > http://codespeak.net/mailman/listinfo/cython-dev > -- Lisandro Dalcín --------------- Centro Internacional de Métodos Computacionales en Ingeniería (CIMEC) Instituto de Desarrollo Tecnológico para la Industria Química (INTEC) Consejo Nacional de Investigaciones Científicas y Técnicas (CONICET) PTLC - Güemes 3450, (3000) Santa Fe, Argentina Tel/Fax: +54-(0)342-451.1594
#!/usr//bin/env python
#
# Cython -- Main Program, Unix
#
import sys
if sys.version_info < (2,4):
import __builtin__, sets
__builtin__.set = sets.Set
__builtin__.frozenset = sets.ImmutableSet
from Cython.Compiler.Main import main
main(command_line = 1)
#include "Python.h"
#ifndef Py_SETOBJECT_H
#define Py_SETOBJECT_H
/* ---------------------------------------------------------------- */
static PyTypeObject *__Pyx_PySet_Type = NULL;
static PyTypeObject *__Pyx_PyFrozenSet_Type = NULL;
static PyObject * __Pyx_PySet_New(PyObject *iterable)
{
return PyObject_CallFunctionObjArgs
((PyObject *)__Pyx_PySet_Type,iterable,NULL);
}
static PyObject * __Pyx_PyFrozenSet_New(PyObject *iterable)
{
return PyObject_CallFunctionObjArgs
((PyObject *)__Pyx_PyFrozenSet_Type,iterable,NULL);
}
static int __Pyx_PySet_Size(PyObject *anyset)
{
return PyObject_Size(anyset);
}
static int __Pyx_PySet_Contains(PyObject *anyset, PyObject *key)
{
return PySequence_Contains(anyset, key);
}
static int __Pyx_PySet_Clear(PyObject *set)
{
PyObject *ret = PyObject_CallMethod(set,"clear",NULL);
if (ret == NULL) return -1;
Py_DECREF(ret); return 0;
}
static int __Pyx_PySet_Discard(PyObject *set, PyObject *key)
{
PyObject *ret = PyObject_CallMethod(set,"discard","O",key);
if (ret == NULL) return -1;
Py_DECREF(ret); return 0;
}
static int __Pyx_PySet_Add(PyObject *set, PyObject *key)
{
PyObject *ret = PyObject_CallMethod(set,"add","O",key);
if (ret == NULL) return -1;
Py_DECREF(ret); return 0;
}
static PyObject * __Pyx_PySet_Pop(PyObject *set)
{
return PyObject_CallMethod(set,"pop",NULL);
}
/* ---------------------------------------------------------------- */
#define PySet_Type (*__Pyx_PySet_Type)
#define PyFrozenSet_Type (*__Pyx_PyFrozenSet_Type)
#define PyAnySet_CheckExact(ob) \
((ob)->ob_type == &PySet_Type || (ob)->ob_type == &PyFrozenSet_Type)
#define PyFrozenSet_CheckExact(ob) ((ob)->ob_type == &PyFrozenSet_Type)
#define PyAnySet_Check(ob) \
((ob)->ob_type == &PySet_Type || (ob)->ob_type == &PyFrozenSet_Type || \
PyType_IsSubtype((ob)->ob_type, &PySet_Type) || \
PyType_IsSubtype((ob)->ob_type, &PyFrozenSet_Type))
static PyObject * (*PySet_New)(PyObject *) = NULL;
static PyObject * (*PyFrozenSet_New)(PyObject *) = NULL;
static int (*PySet_Size)(PyObject *) = NULL;
static int (*PySet_Contains)(PyObject *, PyObject *) = NULL;
static int (*PySet_Clear)(PyObject *) = NULL;
static int (*PySet_Discard)(PyObject *, PyObject *)= NULL;
static int (*PySet_Add)(PyObject *, PyObject *) = NULL;
static PyObject * (*PySet_Pop)(PyObject *) = NULL;
/* ---------------------------------------------------------------- */
static int py23sets_import(void)
{
PyObject *sets=NULL,*Set=NULL,*ImmutableSet=NULL;
sets = PyImport_ImportModule("sets");
if (sets == NULL) goto bad;
Set = PyObject_GetAttrString(sets,"Set");
if (Set == NULL) goto bad;
ImmutableSet = PyObject_GetAttrString(sets,"ImmutableSet");
if (ImmutableSet == NULL) goto bad;
Py_DECREF(sets);
__Pyx_PySet_Type = (PyTypeObject*) Set;
__Pyx_PyFrozenSet_Type = (PyTypeObject*) ImmutableSet;
PySet_New = __Pyx_PySet_New;
PyFrozenSet_New = __Pyx_PyFrozenSet_New;
PySet_Size = __Pyx_PySet_Size;
PySet_Contains = __Pyx_PySet_Contains;
PySet_Clear = __Pyx_PySet_Clear;
PySet_Discard = __Pyx_PySet_Discard;
PySet_Add = __Pyx_PySet_Add;
PySet_Pop = __Pyx_PySet_Pop;
/* XXX This is really dangerous ... !!!
But you know, I hate reference leaks ;-)
*/
Py_DECREF(Set);
Py_DECREF(ImmutableSet);
return 0;
bad:
Py_XDECREF(sets);
Py_XDECREF(Set);
Py_XDECREF(ImmutableSet);
return -1;
}
/* ---------------------------------------------------------------- */
#else
static int py23sets_import(void) { return 0; }
#endif /* !Py_SETOBJECT_H */
py23sets.pxd
Description: Binary data
_______________________________________________ Cython-dev mailing list [email protected] http://codespeak.net/mailman/listinfo/cython-dev
