mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-10-31 07:57:27 +03:00 
			
		
		
		
	find * -type f "-(" -name "*.bdf" -o -name "*.c" -o -name "*.h" -o -name "*.py" -o -name "*.rst" -o -name "*.txt" "-)" -exec sed -e "s/[[:space:]]*$//" -i {} \;
		
	
			
		
			
				
	
	
		
			641 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			641 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * The Python Imaging Library.
 | |
|  *
 | |
|  * 2D path utilities
 | |
|  *
 | |
|  * history:
 | |
|  * 1996-11-04 fl   Added to PIL (incomplete)
 | |
|  * 1996-11-05 fl   Added sequence semantics
 | |
|  * 1997-02-28 fl   Fixed getbbox
 | |
|  * 1997-06-12 fl   Added id attribute
 | |
|  * 1997-06-14 fl   Added slicing and setitem
 | |
|  * 1998-12-29 fl   Improved sequence handling (from Richard Jones)
 | |
|  * 1999-01-10 fl   Fixed IndexError test for 1.5 (from Fred Drake)
 | |
|  * 2000-10-12 fl   Added special cases for tuples and lists
 | |
|  * 2002-10-27 fl   Added clipping boilerplate
 | |
|  * 2004-09-19 fl   Added tolist(flat) variant
 | |
|  * 2005-05-06 fl   Added buffer interface support to path constructor
 | |
|  *
 | |
|  * notes:
 | |
|  * FIXME: fill in remaining slots in the sequence api
 | |
|  *
 | |
|  * Copyright (c) 1997-2005 by Secret Labs AB
 | |
|  * Copyright (c) 1997-2005 by Fredrik Lundh
 | |
|  *
 | |
|  * See the README file for information on usage and redistribution.
 | |
|  */
 | |
| 
 | |
| 
 | |
| #include "Python.h"
 | |
| 
 | |
| #include <math.h>
 | |
| 
 | |
| #include "py3.h"
 | |
| 
 | |
| /* compatibility wrappers (defined in _imaging.c) */
 | |
| extern int PyImaging_CheckBuffer(PyObject* buffer);
 | |
| extern int PyImaging_GetBuffer(PyObject* buffer, Py_buffer *view);
 | |
| 
 | |
| /* -------------------------------------------------------------------- */
 | |
| /* Class								*/
 | |
| /* -------------------------------------------------------------------- */
 | |
| 
 | |
| typedef struct {
 | |
|     PyObject_HEAD
 | |
|     Py_ssize_t count;
 | |
|     double *xy;
 | |
|     int index; /* temporary use, e.g. in decimate */
 | |
| } PyPathObject;
 | |
| 
 | |
| static PyTypeObject PyPathType;
 | |
| 
 | |
| static double*
 | |
| alloc_array(Py_ssize_t count)
 | |
| {
 | |
|     double* xy;
 | |
|     if (count < 0) {
 | |
|         PyErr_NoMemory();
 | |
|         return NULL;
 | |
|     }
 | |
|     xy = malloc(2 * count * sizeof(double) + 1);
 | |
|     if (!xy)
 | |
|         PyErr_NoMemory();
 | |
|     return xy;
 | |
| }
 | |
| 
 | |
| static PyPathObject*
 | |
| path_new(Py_ssize_t count, double* xy, int duplicate)
 | |
| {
 | |
|     PyPathObject *path;
 | |
| 
 | |
|     if (duplicate) {
 | |
|         /* duplicate path */
 | |
|         double* p = alloc_array(count);
 | |
|         if (!p)
 | |
|             return NULL;
 | |
|         memcpy(p, xy, count * 2 * sizeof(double));
 | |
|         xy = p;
 | |
|     }
 | |
| 
 | |
|     if (PyType_Ready(&PyPathType) < 0)
 | |
|         return NULL;
 | |
| 
 | |
|     path = PyObject_New(PyPathObject, &PyPathType);
 | |
|     if (path == NULL)
 | |
| 	return NULL;
 | |
| 
 | |
|     path->count = count;
 | |
|     path->xy = xy;
 | |
| 
 | |
|     return path;
 | |
| }
 | |
| 
 | |
| static void
 | |
| path_dealloc(PyPathObject* path)
 | |
| {
 | |
|     free(path->xy);
 | |
|     PyObject_Del(path);
 | |
| }
 | |
| 
 | |
| /* -------------------------------------------------------------------- */
 | |
| /* Helpers								*/
 | |
| /* -------------------------------------------------------------------- */
 | |
| 
 | |
| #define PyPath_Check(op) (Py_TYPE(op) == &PyPathType)
 | |
| 
 | |
| int
 | |
| PyPath_Flatten(PyObject* data, double **pxy)
 | |
| {
 | |
|     int i, j, n;
 | |
|     double *xy;
 | |
| 
 | |
|     if (PyPath_Check(data)) {
 | |
| 	/* This was another path object. */
 | |
| 	PyPathObject *path = (PyPathObject*) data;
 | |
|         xy = alloc_array(path->count);
 | |
| 	if (!xy)
 | |
| 	    return -1;
 | |
| 	memcpy(xy, path->xy, 2 * path->count * sizeof(double));
 | |
| 	*pxy = xy;
 | |
| 	return path->count;
 | |
|     }
 | |
| 
 | |
|     if (PyImaging_CheckBuffer(data)) {
 | |
|         /* Assume the buffer contains floats */
 | |
|         Py_buffer buffer;
 | |
|         if (PyImaging_GetBuffer(data, &buffer) == 0) {
 | |
|             int n = buffer.len / (2 * sizeof(float));
 | |
|             float *ptr = (float*) buffer.buf;
 | |
|             xy = alloc_array(n);
 | |
|             if (!xy)
 | |
|                 return -1;
 | |
|             for (i = 0; i < n+n; i++)
 | |
|                 xy[i] = ptr[i];
 | |
|             *pxy = xy;
 | |
|             PyBuffer_Release(&buffer);
 | |
|             return n;
 | |
|         }
 | |
|         PyErr_Clear();
 | |
|     }
 | |
| 
 | |
|     if (!PySequence_Check(data)) {
 | |
| 	PyErr_SetString(PyExc_TypeError, "argument must be sequence");
 | |
| 	return -1;
 | |
|     }
 | |
| 
 | |
|     j = 0;
 | |
|     n = PyObject_Length(data);
 | |
|     /* Just in case __len__ breaks (or doesn't exist) */
 | |
|     if (PyErr_Occurred())
 | |
|         return -1;
 | |
| 
 | |
|     /* Allocate for worst case */
 | |
|     xy = alloc_array(n);
 | |
|     if (!xy)
 | |
| 	return -1;
 | |
| 
 | |
|     /* Copy table to path array */
 | |
|     if (PyList_Check(data)) {
 | |
|         for (i = 0; i < n; i++) {
 | |
|             double x, y;
 | |
|             PyObject *op = PyList_GET_ITEM(data, i);
 | |
|             if (PyFloat_Check(op))
 | |
| 		xy[j++] = PyFloat_AS_DOUBLE(op);
 | |
|             else if (PyInt_Check(op))
 | |
| 		xy[j++] = (float) PyInt_AS_LONG(op);
 | |
|             else if (PyNumber_Check(op))
 | |
|                 xy[j++] = PyFloat_AsDouble(op);
 | |
|             else if (PyArg_ParseTuple(op, "dd", &x, &y)) {
 | |
|                 xy[j++] = x;
 | |
|                 xy[j++] = y;
 | |
|             } else {
 | |
|                 free(xy);
 | |
|                 return -1;
 | |
|             }
 | |
|         }
 | |
|     } else if (PyTuple_Check(data)) {
 | |
|         for (i = 0; i < n; i++) {
 | |
|             double x, y;
 | |
|             PyObject *op = PyTuple_GET_ITEM(data, i);
 | |
|             if (PyFloat_Check(op))
 | |
| 		xy[j++] = PyFloat_AS_DOUBLE(op);
 | |
|             else if (PyInt_Check(op))
 | |
| 		xy[j++] = (float) PyInt_AS_LONG(op);
 | |
|             else if (PyNumber_Check(op))
 | |
|                 xy[j++] = PyFloat_AsDouble(op);
 | |
|             else if (PyArg_ParseTuple(op, "dd", &x, &y)) {
 | |
|                 xy[j++] = x;
 | |
|                 xy[j++] = y;
 | |
|             } else {
 | |
|                 free(xy);
 | |
|                 return -1;
 | |
|             }
 | |
|         }
 | |
|     } else {
 | |
|         for (i = 0; i < n; i++) {
 | |
|             double x, y;
 | |
|             PyObject *op = PySequence_GetItem(data, i);
 | |
|             if (!op) {
 | |
|                 /* treat IndexError as end of sequence */
 | |
|                 if (PyErr_Occurred() &&
 | |
|                     PyErr_ExceptionMatches(PyExc_IndexError)) {
 | |
|                     PyErr_Clear();
 | |
|                     break;
 | |
|                 } else {
 | |
|                     free(xy);
 | |
|                     return -1;
 | |
|                 }
 | |
|             }
 | |
|             if (PyFloat_Check(op))
 | |
| 		xy[j++] = PyFloat_AS_DOUBLE(op);
 | |
|             else if (PyInt_Check(op))
 | |
| 		xy[j++] = (float) PyInt_AS_LONG(op);
 | |
|             else if (PyNumber_Check(op))
 | |
|                 xy[j++] = PyFloat_AsDouble(op);
 | |
|             else if (PyArg_ParseTuple(op, "dd", &x, &y)) {
 | |
|                 xy[j++] = x;
 | |
|                 xy[j++] = y;
 | |
|             } else {
 | |
|                 Py_DECREF(op);
 | |
|                 free(xy);
 | |
|                 return -1;
 | |
|             }
 | |
|             Py_DECREF(op);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (j & 1) {
 | |
| 	PyErr_SetString(PyExc_ValueError, "wrong number of coordinates");
 | |
| 	free(xy);
 | |
| 	return -1;
 | |
|     }
 | |
| 
 | |
|     *pxy = xy;
 | |
|     return j/2;
 | |
| }
 | |
| 
 | |
| 
 | |
| /* -------------------------------------------------------------------- */
 | |
| /* Factories								*/
 | |
| /* -------------------------------------------------------------------- */
 | |
| 
 | |
| PyObject*
 | |
| PyPath_Create(PyObject* self, PyObject* args)
 | |
| {
 | |
|     PyObject* data;
 | |
|     Py_ssize_t count;
 | |
|     double *xy;
 | |
| 
 | |
|     if (PyArg_ParseTuple(args, "n:Path", &count)) {
 | |
| 
 | |
|         /* number of vertices */
 | |
|         xy = alloc_array(count);
 | |
|         if (!xy)
 | |
|             return NULL;
 | |
| 
 | |
|     } else {
 | |
| 
 | |
|         /* sequence or other path */
 | |
|         PyErr_Clear();
 | |
|         if (!PyArg_ParseTuple(args, "O", &data))
 | |
|             return NULL;
 | |
| 
 | |
|         count = PyPath_Flatten(data, &xy);
 | |
|         if (count < 0)
 | |
|             return NULL;
 | |
|     }
 | |
| 
 | |
|     return (PyObject*) path_new(count, xy, 0);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* -------------------------------------------------------------------- */
 | |
| /* Methods								*/
 | |
| /* -------------------------------------------------------------------- */
 | |
| 
 | |
| static PyObject*
 | |
| path_compact(PyPathObject* self, PyObject* args)
 | |
| {
 | |
|     /* Simple-minded method to shorten path.  A point is removed if
 | |
|        the city block distance to the previous point is less than the
 | |
|        given distance */
 | |
|     int i, j;
 | |
|     double *xy;
 | |
| 
 | |
|     double cityblock = 2.0;
 | |
| 
 | |
|     if (!PyArg_ParseTuple(args, "|d:compact", &cityblock))
 | |
| 	return NULL;
 | |
| 
 | |
|     xy = self->xy;
 | |
| 
 | |
|     /* remove bogus vertices */
 | |
|     for (i = j = 1; i < self->count; i++) {
 | |
| 	if (fabs(xy[j+j-2]-xy[i+i]) + fabs(xy[j+j-1]-xy[i+i+1]) >= cityblock) {
 | |
| 	    xy[j+j] = xy[i+i];
 | |
| 	    xy[j+j+1] = xy[i+i+1];
 | |
| 	    j++;
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|     i = self->count - j;
 | |
|     self->count = j;
 | |
| 
 | |
|     /* shrink coordinate array */
 | |
|     self->xy = realloc(self->xy, 2 * self->count * sizeof(double));
 | |
| 
 | |
|     return Py_BuildValue("i", i); /* number of removed vertices */
 | |
| }
 | |
| 
 | |
| static PyObject*
 | |
| path_clip_polygon(PyPathObject* self, PyObject* args)
 | |
| {
 | |
|     /* Clip path representing a single polygon */
 | |
|     PyErr_SetString(PyExc_RuntimeError, "not yet implemented");
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| static PyObject*
 | |
| path_clip_polyline(PyPathObject* self, PyObject* args)
 | |
| {
 | |
|     /* Clip path representing a single polyline (outline) */
 | |
|     PyErr_SetString(PyExc_RuntimeError, "not yet implemented");
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| static PyObject*
 | |
| path_getbbox(PyPathObject* self, PyObject* args)
 | |
| {
 | |
|     /* Find bounding box */
 | |
|     int i;
 | |
|     double *xy;
 | |
|     double x0, y0, x1, y1;
 | |
| 
 | |
|     if (!PyArg_ParseTuple(args, ":getbbox"))
 | |
| 	return NULL;
 | |
| 
 | |
|     xy = self->xy;
 | |
| 
 | |
|     x0 = x1 = xy[0];
 | |
|     y0 = y1 = xy[1];
 | |
| 
 | |
|     for (i = 1; i < self->count; i++) {
 | |
| 	if (xy[i+i] < x0)
 | |
| 	    x0 = xy[i+i];
 | |
| 	if (xy[i+i] > x1)
 | |
| 	    x1 = xy[i+i];
 | |
| 	if (xy[i+i+1] < y0)
 | |
| 	    y0 = xy[i+i+1];
 | |
| 	if (xy[i+i+1] > y1)
 | |
| 	    y1 = xy[i+i+1];
 | |
|     }
 | |
| 
 | |
|     return Py_BuildValue("dddd", x0, y0, x1, y1);
 | |
| }
 | |
| 
 | |
| static PyObject*
 | |
| path_getitem(PyPathObject* self, int i)
 | |
| {
 | |
|     if (i < 0)
 | |
|         i = self->count + i;
 | |
|     if (i < 0 || i >= self->count) {
 | |
| 	PyErr_SetString(PyExc_IndexError, "path index out of range");
 | |
| 	return NULL;
 | |
|     }
 | |
| 
 | |
|     return Py_BuildValue("dd", self->xy[i+i], self->xy[i+i+1]);
 | |
| }
 | |
| 
 | |
| static PyObject*
 | |
| path_getslice(PyPathObject* self, Py_ssize_t ilow, Py_ssize_t ihigh)
 | |
| {
 | |
|     /* adjust arguments */
 | |
|     if (ilow < 0)
 | |
|         ilow = 0;
 | |
|     else if (ilow >= self->count)
 | |
|         ilow = self->count;
 | |
|     if (ihigh < 0)
 | |
|         ihigh = 0;
 | |
|     if (ihigh < ilow)
 | |
|         ihigh = ilow;
 | |
|     else if (ihigh > self->count)
 | |
|         ihigh = self->count;
 | |
| 
 | |
|     return (PyObject*) path_new(ihigh - ilow, self->xy + ilow * 2, 1);
 | |
| }
 | |
| 
 | |
| static Py_ssize_t
 | |
| path_len(PyPathObject* self)
 | |
| {
 | |
|     return self->count;
 | |
| }
 | |
| 
 | |
| static PyObject*
 | |
| path_map(PyPathObject* self, PyObject* args)
 | |
| {
 | |
|     /* Map coordinate set through function */
 | |
|     int i;
 | |
|     double *xy;
 | |
|     PyObject* function;
 | |
| 
 | |
|     if (!PyArg_ParseTuple(args, "O:map", &function))
 | |
| 	return NULL;
 | |
| 
 | |
|     xy = self->xy;
 | |
| 
 | |
|     /* apply function to coordinate set */
 | |
|     for (i = 0; i < self->count; i++) {
 | |
| 	double x = xy[i+i];
 | |
| 	double y = xy[i+i+1];
 | |
| 	PyObject* item = PyObject_CallFunction(function, "dd", x, y);
 | |
| 	if (!item || !PyArg_ParseTuple(item, "dd", &x, &y)) {
 | |
| 	    Py_XDECREF(item);
 | |
| 	    return NULL;
 | |
| 	}
 | |
| 	xy[i+i] = x;
 | |
| 	xy[i+i+1] = y;
 | |
| 	Py_DECREF(item);
 | |
|     }
 | |
| 
 | |
|     Py_INCREF(Py_None);
 | |
|     return Py_None;
 | |
| }
 | |
| 
 | |
| static int
 | |
| path_setitem(PyPathObject* self, int i, PyObject* op)
 | |
| {
 | |
|     double* xy;
 | |
| 
 | |
|     if (i < 0 || i >= self->count) {
 | |
|         PyErr_SetString(PyExc_IndexError,
 | |
|                         "path assignment index out of range");
 | |
|         return -1;
 | |
|     }
 | |
| 
 | |
|     if (op == NULL) {
 | |
|         PyErr_SetString(PyExc_TypeError,
 | |
|                         "cannot delete from path");
 | |
|         return -1;
 | |
|     }
 | |
| 
 | |
|     xy = &self->xy[i+i];
 | |
| 
 | |
|     if (!PyArg_ParseTuple(op, "dd", &xy[0], &xy[1]))
 | |
|         return -1;
 | |
| 
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| static PyObject*
 | |
| path_tolist(PyPathObject* self, PyObject* args)
 | |
| {
 | |
|     PyObject *list;
 | |
|     int i;
 | |
| 
 | |
|     int flat = 0;
 | |
|     if (!PyArg_ParseTuple(args, "|i:tolist", &flat))
 | |
| 	return NULL;
 | |
| 
 | |
|     if (flat) {
 | |
|         list = PyList_New(self->count*2);
 | |
|         for (i = 0; i < self->count*2; i++) {
 | |
|             PyObject* item;
 | |
|             item = PyFloat_FromDouble(self->xy[i]);
 | |
|             if (!item)
 | |
|                 goto error;
 | |
|             PyList_SetItem(list, i, item);
 | |
|         }
 | |
|     } else {
 | |
|         list = PyList_New(self->count);
 | |
|         for (i = 0; i < self->count; i++) {
 | |
|             PyObject* item;
 | |
|             item = Py_BuildValue("dd", self->xy[i+i], self->xy[i+i+1]);
 | |
|             if (!item)
 | |
|                 goto error;
 | |
|             PyList_SetItem(list, i, item);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return list;
 | |
| 
 | |
| error:
 | |
|     Py_DECREF(list);
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| static PyObject*
 | |
| path_transform(PyPathObject* self, PyObject* args)
 | |
| {
 | |
|     /* Apply affine transform to coordinate set */
 | |
|     int i;
 | |
|     double *xy;
 | |
|     double a, b, c, d, e, f;
 | |
| 
 | |
|     double wrap = 0.0;
 | |
| 
 | |
|     if (!PyArg_ParseTuple(args, "(dddddd)|d:transform",
 | |
| 			  &a, &b, &c, &d, &e, &f,
 | |
| 			  &wrap))
 | |
| 	return NULL;
 | |
| 
 | |
|     xy = self->xy;
 | |
| 
 | |
|     /* transform the coordinate set */
 | |
|     if (b == 0.0 && d == 0.0)
 | |
| 	/* scaling */
 | |
| 	for (i = 0; i < self->count; i++) {
 | |
| 	    xy[i+i]   = a*xy[i+i]+c;
 | |
| 	    xy[i+i+1] = e*xy[i+i+1]+f;
 | |
| 	}
 | |
|     else
 | |
| 	/* affine transform */
 | |
| 	for (i = 0; i < self->count; i++) {
 | |
| 	    double x = xy[i+i];
 | |
| 	    double y = xy[i+i+1];
 | |
| 	    xy[i+i]   = a*x+b*y+c;
 | |
| 	    xy[i+i+1] = d*x+e*y+f;
 | |
| 	}
 | |
| 
 | |
|     /* special treatment of geographical map data */
 | |
|     if (wrap != 0.0)
 | |
| 	for (i = 0; i < self->count; i++)
 | |
| 	    xy[i+i] = fmod(xy[i+i], wrap);
 | |
| 
 | |
|     Py_INCREF(Py_None);
 | |
|     return Py_None;
 | |
| }
 | |
| 
 | |
| static struct PyMethodDef methods[] = {
 | |
|     {"getbbox", (PyCFunction)path_getbbox, 1},
 | |
|     {"tolist", (PyCFunction)path_tolist, 1},
 | |
|     {"clip_polygon", (PyCFunction)path_clip_polygon, 1},
 | |
|     {"clip_polyline", (PyCFunction)path_clip_polyline, 1},
 | |
|     {"compact", (PyCFunction)path_compact, 1},
 | |
|     {"map", (PyCFunction)path_map, 1},
 | |
|     {"transform", (PyCFunction)path_transform, 1},
 | |
|     {NULL, NULL} /* sentinel */
 | |
| };
 | |
| 
 | |
| static PyObject*
 | |
| path_getattr_id(PyPathObject* self, void* closure)
 | |
| {
 | |
| 	return Py_BuildValue("n", (Py_ssize_t) self->xy);
 | |
| }
 | |
| 
 | |
| static struct PyGetSetDef getsetters[] = {
 | |
|     { "id", (getter) path_getattr_id },
 | |
|     { NULL }
 | |
| };
 | |
| 
 | |
| static PyObject*
 | |
| path_subscript(PyPathObject* self, PyObject* item) {
 | |
|     if (PyIndex_Check(item)) {
 | |
|         Py_ssize_t i;
 | |
|         i = PyNumber_AsSsize_t(item, PyExc_IndexError);
 | |
|         if (i == -1 && PyErr_Occurred())
 | |
|             return NULL;
 | |
|         return path_getitem(self, i);
 | |
|     }
 | |
|     if (PySlice_Check(item)) {
 | |
|         int len = 4;
 | |
|         Py_ssize_t start, stop, step, slicelength;
 | |
| 
 | |
| #if PY_VERSION_HEX >= 0x03020000
 | |
|         if (PySlice_GetIndicesEx(item, len, &start, &stop, &step, &slicelength) < 0)
 | |
|             return NULL;
 | |
| #else
 | |
|         if (PySlice_GetIndicesEx((PySliceObject*)item, len, &start, &stop, &step, &slicelength) < 0)
 | |
|             return NULL;
 | |
| #endif
 | |
| 
 | |
|         if (slicelength <= 0) {
 | |
|             double *xy = alloc_array(0);
 | |
|             return (PyObject*) path_new(0, xy, 0);
 | |
|         }
 | |
|         else if (step == 1) {
 | |
|             return path_getslice(self, start, stop);
 | |
|         }
 | |
|         else {
 | |
|             PyErr_SetString(PyExc_TypeError, "slice steps not supported");
 | |
|             return NULL;
 | |
|         }
 | |
|     }
 | |
|     else {
 | |
|         PyErr_Format(PyExc_TypeError,
 | |
|                      "Path indices must be integers, not %.200s",
 | |
|                      Py_TYPE(&item)->tp_name);
 | |
|         return NULL;
 | |
|     }
 | |
| }
 | |
| 
 | |
| static PySequenceMethods path_as_sequence = {
 | |
| 	(lenfunc)path_len, /*sq_length*/
 | |
| 	(binaryfunc)0, /*sq_concat*/
 | |
| 	(ssizeargfunc)0, /*sq_repeat*/
 | |
| 	(ssizeargfunc)path_getitem, /*sq_item*/
 | |
| 	(ssizessizeargfunc)path_getslice, /*sq_slice*/
 | |
| 	(ssizeobjargproc)path_setitem, /*sq_ass_item*/
 | |
| 	(ssizessizeobjargproc)0, /*sq_ass_slice*/
 | |
| };
 | |
| 
 | |
| static PyMappingMethods path_as_mapping = {
 | |
|     (lenfunc)path_len,
 | |
|     (binaryfunc)path_subscript,
 | |
|     NULL
 | |
| };
 | |
| 
 | |
| static PyTypeObject PyPathType = {
 | |
| 	PyVarObject_HEAD_INIT(NULL, 0)
 | |
| 	"Path",				/*tp_name*/
 | |
| 	sizeof(PyPathObject),		/*tp_size*/
 | |
| 	0,				/*tp_itemsize*/
 | |
| 	/* methods */
 | |
| 	(destructor)path_dealloc,	/*tp_dealloc*/
 | |
| 	0,				/*tp_print*/
 | |
| 	0,	                            /*tp_getattr*/
 | |
| 	0,				/*tp_setattr*/
 | |
| 	0,				/*tp_compare*/
 | |
| 	0,				/*tp_repr*/
 | |
| 	0,                              /*tp_as_number */
 | |
| 	&path_as_sequence,              /*tp_as_sequence */
 | |
|     &path_as_mapping,           /*tp_as_mapping */
 | |
|     0,                          /*tp_hash*/
 | |
|     0,                          /*tp_call*/
 | |
|     0,                          /*tp_str*/
 | |
|     0,                          /*tp_getattro*/
 | |
|     0,                          /*tp_setattro*/
 | |
|     0,                          /*tp_as_buffer*/
 | |
|     Py_TPFLAGS_DEFAULT,         /*tp_flags*/
 | |
|     0,                          /*tp_doc*/
 | |
|     0,                          /*tp_traverse*/
 | |
|     0,                          /*tp_clear*/
 | |
|     0,                          /*tp_richcompare*/
 | |
|     0,                          /*tp_weaklistoffset*/
 | |
|     0,                          /*tp_iter*/
 | |
|     0,                          /*tp_iternext*/
 | |
|     methods,                    /*tp_methods*/
 | |
|     0,                          /*tp_members*/
 | |
|     getsetters,                 /*tp_getset*/
 | |
| };
 | |
| 
 |