Back to index

python-biopython  1.60
KDTreemodule.c
Go to the documentation of this file.
00001 #include <Python.h>
00002 #include <numpy/arrayobject.h>
00003 #include "KDTree.h"
00004 
00005 
00006 /* Must define Py_TYPE for Python 2.5 or older */
00007 #ifndef Py_TYPE
00008 #  define Py_TYPE(o) ((o)->ob_type)
00009 #endif
00010 
00011 /* Must define PyVarObject_HEAD_INIT for Python 2.5 or older */
00012 #ifndef PyVarObject_HEAD_INIT
00013 #define PyVarObject_HEAD_INIT(type, size)       \
00014         PyObject_HEAD_INIT(type) size,
00015 #endif
00016 
00017 
00018 typedef struct {
00019     PyObject_HEAD 
00020     struct Neighbor neighbor;
00021 } PyNeighbor;
00022 
00023 static int
00024 PyNeighbor_init(PyNeighbor *self, PyObject *args, PyObject *kwds)
00025 {
00026     long int index1, index2;
00027     float radius = 0.0;
00028     static char *kwlist[] = {"index1", "index2", "radius", NULL};
00029 
00030     if (! PyArg_ParseTupleAndKeywords(args, kwds, "ii|d", kwlist, 
00031                                       &index1, &index2, &radius))
00032         return -1;
00033     self->neighbor.index1 = index1;
00034     self->neighbor.index2 = index2;
00035     self->neighbor.radius = radius;
00036 
00037     return 0;
00038 }
00039 
00040 static PyObject*
00041 PyNeighbor_repr(PyNeighbor* self)
00042 {
00043     char string[64];
00044     sprintf(string, "(%ld, %ld): %g",
00045             self->neighbor.index1, self->neighbor.index2, self->neighbor.radius);
00046 #if PY_MAJOR_VERSION >= 3
00047     return PyUnicode_FromString(string);
00048 #else
00049     return PyString_FromString(string);
00050 #endif
00051 
00052 }
00053 
00054 static char PyNeighbor_index1__doc__[] =
00055 "index of the first neighbor";
00056 
00057 static PyObject*
00058 PyNeighbor_getindex1(PyNeighbor* self, void* closure)
00059 {
00060 #if PY_MAJOR_VERSION >= 3
00061     return PyLong_FromLong(self->neighbor.index1);
00062 #else
00063     return PyInt_FromLong(self->neighbor.index1);
00064 #endif
00065 }
00066 
00067 static int
00068 PyNeighbor_setindex1(PyNeighbor* self, PyObject* value, void* closure)
00069 {
00070 #if PY_MAJOR_VERSION >= 3
00071     long index1 = PyLong_AsLong(value);
00072 #else
00073     long index1 = PyInt_AsLong(value);
00074 #endif
00075     if (PyErr_Occurred()) return -1;
00076     self->neighbor.index1 = index1;
00077     return 0;
00078 }
00079 
00080 static char PyNeighbor_index2__doc__[] =
00081 "index of the second neighbor";
00082 
00083 static PyObject*
00084 PyNeighbor_getindex2(PyNeighbor* self, void* closure)
00085 {
00086 #if PY_MAJOR_VERSION >= 3
00087     return PyLong_FromLong(self->neighbor.index2);
00088 #else
00089     return PyInt_FromLong(self->neighbor.index2);
00090 #endif
00091 }
00092 
00093 static int
00094 PyNeighbor_setindex2(PyNeighbor* self, PyObject* value, void* closure)
00095 {
00096 #if PY_MAJOR_VERSION >= 3
00097     long index2 = PyLong_AsLong(value);
00098 #else
00099     long index2 = PyInt_AsLong(value);
00100 #endif
00101     if (PyErr_Occurred()) return -1;
00102     self->neighbor.index2 = index2;
00103     return 0;
00104 }
00105 
00106 static PyObject*
00107 PyNeighbor_getradius(PyNeighbor* self, void* closure)
00108 {
00109     float value = self->neighbor.radius;
00110     return PyFloat_FromDouble((double)value);
00111 }
00112 
00113 static int
00114 PyNeighbor_setradius(PyNeighbor* self, PyObject* value, void* closure)
00115 { const double radius = PyFloat_AsDouble(value);
00116   if (PyErr_Occurred()) return -1;
00117   self->neighbor.radius = (float)radius;
00118   return 0;
00119 }
00120 
00121 static char PyNeighbor_radius__doc__[] =
00122 "the radius\n";
00123 
00124 static PyGetSetDef PyNeighbor_getset[] = {
00125     {"index1", (getter)PyNeighbor_getindex1, (setter)PyNeighbor_setindex1, PyNeighbor_index1__doc__, NULL},
00126     {"index2", (getter)PyNeighbor_getindex2, (setter)PyNeighbor_setindex2, PyNeighbor_index2__doc__, NULL},
00127     {"radius", (getter)PyNeighbor_getradius, (setter)PyNeighbor_setradius, PyNeighbor_radius__doc__, NULL},
00128     {NULL}  /* Sentinel */
00129 };
00130 
00131 static char PyNeighbor_doc[] =
00132 "A neighbor pair; members are index1, index2, and radius.\n";
00133 
00134 static PyTypeObject PyNeighborType = {
00135     PyVarObject_HEAD_INIT(NULL, 0)
00136     "KDTree.Neighbor",         /* tp_name*/
00137     sizeof(PyNeighbor),        /* tp_basicsize*/
00138     0,                         /* tp_itemsize*/
00139     0,                         /* tp_dealloc*/
00140     0,                         /* tp_print*/
00141     0,                         /* tp_getattr*/
00142     0,                         /* tp_setattr*/
00143     0,                         /* tp_compare*/
00144     (reprfunc)PyNeighbor_repr, /* tp_repr*/
00145     0,                         /* tp_as_number*/
00146     0,                         /* tp_as_sequence*/
00147     0,                         /* tp_as_mapping*/
00148     0,                         /* tp_hash */
00149     0,                         /* tp_call*/
00150     0,                         /* tp_str*/
00151     0,                         /* tp_getattro*/
00152     0,                         /* tp_setattro*/
00153     0,                         /* tp_as_buffer*/
00154     Py_TPFLAGS_DEFAULT,        /* tp_flags*/
00155     PyNeighbor_doc,            /* tp_doc */
00156     0,                         /* tp_traverse */
00157     0,                         /* tp_clear */
00158     0,                         /* tp_richcompare */
00159     0,                         /* tp_weaklistoffset */
00160     0,                         /* tp_iter */
00161     0,                         /* tp_iternext */
00162     0,                         /* tp_methods */
00163     0,                         /* tp_members */
00164     PyNeighbor_getset,         /* tp_getset */
00165     0,                         /* tp_base */
00166     0,                         /* tp_dict */
00167     0,                         /* tp_descr_get */
00168     0,                         /* tp_descr_set */
00169     0,                         /* tp_dictoffset */
00170     (initproc)PyNeighbor_init, /* tp_init */
00171 };
00172 
00173 typedef struct {
00174     PyObject_HEAD
00175     struct KDTree* tree;
00176 } PyTree;
00177 
00178 static void
00179 PyTree_dealloc(PyTree* self)
00180 {
00181     KDTree_destroy(self->tree);
00182     Py_TYPE(self)->tp_free((PyObject*)self);
00183 }
00184 
00185 static int
00186 PyTree_init(PyTree* self, PyObject* args, PyObject* kwds)
00187 {
00188     int dim;
00189     int bucket_size;
00190     struct KDTree* tree;
00191    
00192     if(!PyArg_ParseTuple(args, "ii:KDTree_init" ,&dim, &bucket_size)) return -1;
00193 
00194     if (dim <= 0 || bucket_size <= 0)
00195     {
00196         PyErr_SetString(PyExc_ValueError, "Both arguments should be positive");
00197         return -1;
00198     }
00199 
00200     tree = KDTree_init(dim, bucket_size);
00201     if (tree==NULL)
00202     {
00203         PyErr_SetString(PyExc_MemoryError, "Insufficient memory for tree");
00204        return -1;
00205     }
00206 
00207     self->tree = tree;
00208     return 0;
00209 }
00210 
00211 static PyObject*
00212 PyTree_get_count(PyTree* self)
00213 {
00214     long count;
00215     struct KDTree* tree = self->tree;
00216     PyObject* result;
00217     count = KDTree_get_count(tree);
00218 #if PY_MAJOR_VERSION >= 3
00219     result = PyLong_FromLong(count);
00220 #else
00221     result = PyInt_FromLong(count);
00222 #endif
00223     if (!result)
00224     {
00225         PyErr_SetString (PyExc_MemoryError, "Failed to allocate memory for object.");
00226         return NULL;
00227     }
00228     return result;
00229 }
00230 
00231 static PyObject*
00232 PyTree_neighbor_get_count(PyTree* self)
00233 {
00234     long count;
00235     struct KDTree* tree = self->tree;
00236     PyObject* result;
00237     count = KDTree_neighbor_get_count(tree);
00238 #if PY_MAJOR_VERSION >= 3
00239     result = PyLong_FromLong(count);
00240 #else
00241     result = PyInt_FromLong(count);
00242 #endif
00243     if (!result)
00244     {
00245         PyErr_SetString (PyExc_MemoryError, "Failed to allocate memory for object.");
00246         return NULL;
00247     }
00248     return result;
00249 }
00250 
00251 static PyObject*
00252 PyTree_set_data(PyTree* self, PyObject* args)
00253 {
00254     float* coords;
00255     long int n, m, i;
00256     PyObject *obj;
00257     PyArrayObject *array;
00258     struct KDTree* tree = self->tree;
00259     int ok;
00260     npy_intp rowstride, colstride;
00261     const char* p;
00262 
00263     if(!PyArg_ParseTuple(args, "O:KDTree_set_data",&obj)) return NULL;
00264 
00265     /* Check if it is an array */
00266     if (!PyArray_Check(obj))
00267     {
00268         PyErr_SetString(PyExc_TypeError, "First argument must be an array.");
00269         return NULL;
00270     }
00271     array=(PyArrayObject *) obj;
00272     if(PyArray_NDIM(array)!=2)
00273     {
00274         PyErr_SetString(PyExc_ValueError, "Array must be two dimensional.");
00275         return NULL;
00276     }
00277     if (PyArray_TYPE(array) == NPY_DOUBLE)
00278     {
00279         Py_INCREF(obj);
00280     }
00281     else
00282     {
00283         /* Cast to type double */
00284         obj = PyArray_Cast(array, NPY_DOUBLE);
00285         if (!obj)
00286         {
00287             PyErr_SetString(PyExc_ValueError,
00288                             "coordinates cannot be cast to needed type.");
00289             return NULL;
00290         }
00291         array = (PyArrayObject*) obj;
00292     }
00293 
00294     n = (long int) PyArray_DIM(array, 0);
00295     m = (long int) PyArray_DIM(array, 1);
00296 
00297     /* coord_data is deleted by the KDTree object */
00298     coords= malloc(m*n*sizeof(float));
00299     if (!coords)
00300     {
00301         Py_DECREF(obj);
00302         PyErr_SetString (PyExc_MemoryError, "Failed to allocate memory for coordinates.");
00303         return NULL;
00304     }
00305 
00306     rowstride =  PyArray_STRIDE(array, 0);
00307     colstride =  PyArray_STRIDE(array, 1);
00308     p = PyArray_BYTES(array);
00309 
00310     for (i=0; i<n; i++)
00311     {
00312         int j;
00313 
00314         for (j=0; j<m; j++)
00315         {
00316             coords[i*m+j]=*(double *) (p+i*rowstride+j*colstride);
00317         }
00318     }  
00319     Py_DECREF(obj);
00320 
00321     ok = KDTree_set_data(tree, coords, n);
00322     if (!ok)
00323     {
00324         PyErr_SetString (PyExc_MemoryError, "Failed to allocate memory for nodes.");
00325         return NULL;
00326     }
00327 
00328     Py_INCREF(Py_None);
00329     return Py_None;
00330 }
00331 
00332 static PyObject*
00333 PyTree_search_center_radius(PyTree* self, PyObject* args)
00334 {
00335     PyObject *obj;
00336     double radius;
00337     PyArrayObject *array;
00338     long int n, i;
00339     float *coords;
00340     struct KDTree* tree = self->tree;
00341     int ok;
00342     npy_intp stride;
00343     const char* p;
00344 
00345     if(!PyArg_ParseTuple(args, "Od:KDTree_search_center_radius", &obj ,&radius))
00346         return NULL;
00347 
00348     if(radius <= 0)
00349     {
00350         PyErr_SetString(PyExc_ValueError, "Radius must be positive.");
00351         return NULL;
00352     }
00353 
00354     /* Check if it is an array */
00355     if (!PyArray_Check(obj))
00356     {
00357         PyErr_SetString(PyExc_TypeError, "First argument must be an array.");
00358         return NULL;
00359     }
00360     array=(PyArrayObject *) obj;
00361 
00362     if(PyArray_NDIM(array)!=1)
00363     {
00364         PyErr_SetString(PyExc_ValueError, "Array must be one dimensional.");
00365         return NULL;
00366     }
00367     if (PyArray_TYPE(array) == NPY_DOUBLE)
00368     {
00369         Py_INCREF(obj);
00370     }
00371     else
00372     {
00373         /* Cast to type double */
00374         obj = PyArray_Cast(array, NPY_DOUBLE);
00375         if (!obj)
00376         {
00377             PyErr_SetString(PyExc_ValueError,
00378                             "coordinates cannot be cast to needed type.");
00379             return NULL;
00380         }
00381         array = (PyArrayObject*) obj;
00382     }
00383 
00384     n = (long int) PyArray_DIM(array, 0);
00385 
00386     /* coord_data is deleted by the KDTree object */
00387     coords= malloc(n*sizeof(float));
00388     if (!coords)
00389     {
00390         Py_DECREF(obj);
00391         PyErr_SetString (PyExc_MemoryError, "Failed to allocate memory for coordinates.");
00392         return NULL;
00393     }
00394 
00395     stride =  PyArray_STRIDE(array, 0);
00396     p = PyArray_BYTES(array);
00397     for (i=0; i<n; i++)
00398     {
00399         coords[i]=*(double *) (p+i*stride);
00400     }
00401     Py_DECREF(obj);
00402 
00403     ok = KDTree_search_center_radius(tree, coords, radius);
00404 
00405     if (!ok)
00406     {
00407         PyErr_SetString (PyExc_MemoryError, "Insufficient memory for calculation.");
00408         return NULL;
00409     }
00410 
00411     Py_INCREF(Py_None);
00412     return Py_None;
00413 }
00414 
00415 static PyObject*
00416 PyTree_neighbor_search(PyTree* self, PyObject* args)
00417 {
00418     int ok;
00419     double radius;
00420     struct KDTree* tree = self->tree;
00421     struct Neighbor* neighbors;
00422     struct Neighbor* pp, *qq;
00423     PyObject* list;
00424     Py_ssize_t i, n;
00425 
00426     if(!PyArg_ParseTuple(args, "d:KDTree_neighbor_search", &radius))
00427         return NULL;
00428 
00429     if(radius <= 0)
00430     {
00431         PyErr_SetString(PyExc_ValueError, "Radius must be positive.");
00432         return NULL;
00433     }
00434 
00435     ok = KDTree_neighbor_search(tree, radius, &neighbors);
00436     if (!ok)
00437     {
00438         PyErr_SetString(PyExc_MemoryError,
00439             "calculation failed due to lack of memory");
00440         return NULL;
00441     }
00442 
00443     pp = neighbors;
00444     n = 0;
00445     while (pp)
00446     {
00447         n+=1;
00448         pp = pp->next;
00449     }
00450 
00451     list = PyList_New(n);
00452     if (list)
00453     {
00454         PyNeighbor* p;
00455         pp = neighbors;
00456         for (i = 0; i < n; i++)
00457         {
00458             p = (PyNeighbor*) PyNeighborType.tp_alloc(&PyNeighborType, 0);
00459             if(!p)
00460             {
00461                 PyErr_SetString(PyExc_MemoryError,
00462                     "could not create node for return value");
00463                 Py_DECREF(list);
00464                 return NULL;
00465             }
00466             p->neighbor = *pp;
00467             PyList_SET_ITEM(list, i, (PyObject*)p);
00468             qq = pp->next;
00469             free(pp);
00470             pp = qq;
00471         }
00472     }
00473 
00474     return list;
00475 }
00476 
00477 static PyObject*
00478 PyTree_neighbor_simple_search(PyTree* self, PyObject* args)
00479 {
00480     int ok;
00481     double radius;
00482     struct KDTree* tree = self->tree;
00483     struct Neighbor* neighbors;
00484     struct Neighbor* pp, *qq;
00485     PyObject* list;
00486     Py_ssize_t i, n;
00487 
00488     if(!PyArg_ParseTuple(args, "d:KDTree_neighbor_simple_search", &radius))
00489         return NULL;
00490 
00491     if(radius <= 0)
00492     {
00493         PyErr_SetString(PyExc_ValueError, "Radius must be positive.");
00494         return NULL;
00495     }
00496 
00497     ok = KDTree_neighbor_simple_search(tree, radius, &neighbors);
00498     if (!ok)
00499     {
00500         PyErr_SetString(PyExc_MemoryError,
00501             "calculation failed due to lack of memory");
00502         return NULL;
00503     }
00504 
00505     pp = neighbors;
00506     n = 0;
00507     while (pp)
00508     {
00509         n+=1;
00510         pp = pp->next;
00511     }
00512 
00513     list = PyList_New(n);
00514     if (list)
00515     {
00516         PyNeighbor* p;
00517         pp = neighbors;
00518         for (i = 0; i < n; i++)
00519         {
00520             p = (PyNeighbor*) PyNeighborType.tp_alloc(&PyNeighborType, 0);
00521             if(!p)
00522             {
00523                 PyErr_SetString(PyExc_MemoryError,
00524                     "could not create node for return value");
00525                 Py_DECREF(list);
00526                 return NULL;
00527             }
00528             p->neighbor = *pp;
00529             PyList_SET_ITEM(list, i, (PyObject*)p);
00530             qq = pp->next;
00531             free(pp);
00532             pp = qq;
00533         }
00534     }
00535 
00536     return list;
00537 }
00538 
00539 static char PyTree_get_indices__doc__[] =
00540 "returns indices of coordinates within radius as a Numpy array\n";
00541 
00542 static PyObject *PyTree_get_indices(PyTree *self)
00543 {
00544        npy_intp length;
00545        PyArrayObject *array;
00546        struct KDTree* tree = self->tree;
00547  
00548        length=KDTree_get_count(tree);
00549        
00550        if (length==0)
00551        {
00552               Py_INCREF(Py_None);
00553               return Py_None;
00554        }
00555 
00556        array=(PyArrayObject *) PyArray_SimpleNew(1, &length, PyArray_LONG);
00557        if (!array)
00558        {
00559               PyErr_SetString(PyExc_MemoryError,
00560                             "Insufficient memory for array");
00561               return NULL;
00562        }
00563 
00564        /* copy the data into the Numpy data pointer */
00565        KDTree_copy_indices(tree, (long int *) PyArray_BYTES(array));
00566        return PyArray_Return(array);
00567 }
00568 
00569 static char PyTree_get_radii__doc__[] =
00570 "returns distances of coordinates within radius as a Numpy array.\n";
00571 
00572 static PyObject *PyTree_get_radii(PyTree *self)
00573 {
00574        npy_intp length;
00575        PyArrayObject *array;
00576        struct KDTree* tree = self->tree;
00577         
00578        length=KDTree_get_count(tree);
00579 
00580        if (length==0)
00581        {
00582               Py_INCREF(Py_None);
00583               return Py_None;
00584        }
00585               
00586        array=(PyArrayObject *) PyArray_SimpleNew(1, &length, PyArray_FLOAT);
00587        if (!array)
00588        {
00589               PyErr_SetString(PyExc_MemoryError,
00590                             "Insufficient memory for array");
00591               return NULL;
00592        }
00593 
00594        /* copy the data into the Numpy data pointer */
00595        KDTree_copy_radii(tree, (float *) PyArray_BYTES(array));
00596        return PyArray_Return(array);
00597 }                                   
00598 
00599 static PyMethodDef PyTree_methods[] = {
00600     {"get_count", (PyCFunction)PyTree_get_count, METH_NOARGS, NULL},
00601     {"set_data", (PyCFunction)PyTree_set_data, METH_VARARGS, NULL},
00602     {"search_center_radius", (PyCFunction)PyTree_search_center_radius, METH_VARARGS, NULL},
00603     {"neighbor_get_count", (PyCFunction)PyTree_neighbor_get_count, METH_NOARGS, NULL},
00604     {"neighbor_search", (PyCFunction)PyTree_neighbor_search, METH_VARARGS, NULL},
00605     {"neighbor_simple_search", (PyCFunction)PyTree_neighbor_simple_search, METH_VARARGS, NULL},
00606     {"get_indices", (PyCFunction)PyTree_get_indices, METH_NOARGS, PyTree_get_indices__doc__},
00607     {"get_radii", (PyCFunction)PyTree_get_radii, METH_NOARGS, PyTree_get_radii__doc__},
00608     {NULL}  /* Sentinel */
00609 };
00610 
00611 static char PyTree_doc[] = "C KDTree.\n";
00612 
00613 static PyTypeObject PyTreeType = {
00614     PyVarObject_HEAD_INIT(NULL, 0)
00615     "C KDTree",                  /*tp_name*/
00616     sizeof(PyTree),              /*tp_basicsize*/
00617     0,                           /*tp_itemsize*/
00618     (destructor)PyTree_dealloc,  /*tp_dealloc*/
00619     0,                           /*tp_print*/
00620     0,                           /*tp_getattr*/
00621     0,                           /*tp_setattr*/
00622     0,                           /*tp_compare*/
00623     0,                           /*tp_repr*/
00624     0,                           /*tp_as_number*/
00625     0,                           /*tp_as_sequence*/
00626     0,                           /*tp_as_mapping*/
00627     0,                           /*tp_hash */
00628     0,                           /*tp_call*/
00629     0,                           /*tp_str*/
00630     0,                           /*tp_getattro*/
00631     0,                           /*tp_setattro*/
00632     0,                           /*tp_as_buffer*/
00633     Py_TPFLAGS_DEFAULT,          /*tp_flags*/
00634     PyTree_doc,                  /* tp_doc */
00635     0,                         /* tp_traverse */
00636     0,                         /* tp_clear */
00637     0,                         /* tp_richcompare */
00638     0,                         /* tp_weaklistoffset */
00639     0,                         /* tp_iter */
00640     0,                         /* tp_iternext */
00641     PyTree_methods,              /* tp_methods */
00642     NULL,                        /* tp_members */
00643     0,                           /* tp_getset */
00644     0,                           /* tp_base */
00645     0,                           /* tp_dict */
00646     0,                           /* tp_descr_get */
00647     0,                           /* tp_descr_set */
00648     0,                           /* tp_dictoffset */
00649     (initproc)PyTree_init,       /* tp_init */
00650 };
00651 
00652 /* ========================================================================== */
00653 /* -- Initialization -------------------------------------------------------- */
00654 /* ========================================================================== */
00655 
00656 #if PY_MAJOR_VERSION >= 3
00657 
00658 static struct PyModuleDef moduledef = {
00659         PyModuleDef_HEAD_INIT,
00660         "_CKDTree",
00661         NULL,
00662         -1,
00663         NULL,
00664         NULL,
00665         NULL,
00666         NULL,
00667         NULL
00668 };
00669 
00670 PyObject *
00671 PyInit__CKDTree(void)
00672 
00673 #else
00674 
00675 void
00676 init_CKDTree(void)
00677 #endif
00678 {
00679   PyObject *module;
00680 
00681   import_array();
00682 
00683   PyTreeType.tp_new = PyType_GenericNew;
00684   PyNeighborType.tp_new = PyType_GenericNew;
00685   if (PyType_Ready(&PyTreeType) < 0)
00686 #if PY_MAJOR_VERSION >= 3
00687       return NULL;
00688 #else
00689       return;
00690 #endif
00691   if (PyType_Ready(&PyNeighborType) < 0)
00692 #if PY_MAJOR_VERSION >= 3
00693       return NULL;
00694 #else
00695       return;
00696 #endif
00697 
00698 #if PY_MAJOR_VERSION >= 3
00699   module = PyModule_Create(&moduledef);
00700   if (module==NULL) return NULL;
00701 #else
00702   module = Py_InitModule("_CKDTree", NULL);
00703   if (module==NULL) return;
00704 #endif
00705 
00706   Py_INCREF(&PyTreeType);
00707   Py_INCREF(&PyNeighborType);
00708   PyModule_AddObject(module, "KDTree", (PyObject*) &PyTreeType);
00709   PyModule_AddObject(module, "Neighbor", (PyObject*) &PyNeighborType);
00710 
00711   if (PyErr_Occurred()) Py_FatalError("can't initialize module _CKDTree");
00712 #if PY_MAJOR_VERSION >= 3
00713   return module;
00714 #endif
00715 }