[Thuban-commits] r2745 - branches/WIP-pyshapelib-bramz/libraries/pyshapelib

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Thu Mar 15 23:27:02 CET 2007


Author: bramz
Date: 2007-03-15 23:27:02 +0100 (Thu, 15 Mar 2007)
New Revision: 2745

Modified:
   branches/WIP-pyshapelib-bramz/libraries/pyshapelib/ChangeLog
   branches/WIP-pyshapelib-bramz/libraries/pyshapelib/dbflibmodule.c
   branches/WIP-pyshapelib-bramz/libraries/pyshapelib/pyshapelib_common.h
   branches/WIP-pyshapelib-bramz/libraries/pyshapelib/pytest.py
   branches/WIP-pyshapelib-bramz/libraries/pyshapelib/shapelibmodule.c
   branches/WIP-pyshapelib-bramz/libraries/pyshapelib/shptreemodule.c
Log:
Added FTLogical support to dbflib.  Accept None as no-data for M values.  Added name and mode keywords to mimic Python's file behaviour where appropriate.  Added unpack_vertex() to lift some load of shpobject_init().

Modified: branches/WIP-pyshapelib-bramz/libraries/pyshapelib/ChangeLog
===================================================================
--- branches/WIP-pyshapelib-bramz/libraries/pyshapelib/ChangeLog	2007-03-15 13:48:58 UTC (rev 2744)
+++ branches/WIP-pyshapelib-bramz/libraries/pyshapelib/ChangeLog	2007-03-15 22:27:02 UTC (rev 2745)
@@ -1,5 +1,31 @@
 2007-03-15	Bram de Greve <bram.degreve at intec.ugent.be>
 
+	* shapelib.c: When creating measured shapes (XYM), treat M value
+	value as optional (defaults to zero).  Similar for
+	3D shapes (XYZM), threat both the Z and M value as options 
+	(both default to zero).  When M values are to be given,
+	None is accepted as "no-data" value, and is stored as zero
+	(ESRI shapefile specs define any M value smaller than 1e-38
+	as no-data). Added an unpack_vertex() function to lift some
+	of the load of shpobject_init. Fixed a missing break and
+	PyMem_Free in build_vertex_list(), shapefile_init() and
+	shapelib_create().
+
+	* dbflibmodule.c: Added support for the FTLogical field type.
+	
+	* shapelibmodule.c, dbflibmodule.c: Added 'name' and 'mode' 
+	keywords for ShapeFile and DBFFile constructors and the module's
+	open() function, similiar to Python's file().  Reformatted 
+	the doc strings to have a standard look and feel when parsed
+	through pydoc.
+	
+	* shapelib_common.h: added no-data constants.
+	
+	* pytest.py: Added tests for multipatch shapefile with XYZM values.
+	Added tests for FTLogical field.
+
+2007-03-15	Bram de Greve <bram.degreve at intec.ugent.be>
+
 	* shapelibmodule.c, dbflibmodule.c: added some Unicode support for the
 	filenames (no internal encoding for DBFFile yet).  It now should similar
 	Unicode support Python's file() (concerning the filename, that is).

Modified: branches/WIP-pyshapelib-bramz/libraries/pyshapelib/dbflibmodule.c
===================================================================
--- branches/WIP-pyshapelib-bramz/libraries/pyshapelib/dbflibmodule.c	2007-03-15 13:48:58 UTC (rev 2744)
+++ branches/WIP-pyshapelib-bramz/libraries/pyshapelib/dbflibmodule.c	2007-03-15 22:27:02 UTC (rev 2745)
@@ -38,13 +38,9 @@
 {
 	char* file;
 	char* mode = "rb";
-	if (kwds != NULL && PyDict_Size(kwds) > 0)
-	{
-		PyErr_Format(PyExc_TypeError, "dbflib.DBFFile.__init__ takes no keyword arguments");
-		return -1;
-	}
-
-	if (!PyArg_ParseTuple(args, "et|s:__init__", Py_FileSystemDefaultEncoding, &file, &mode)) return -1;
+	static char *kwlist[] = {"name", "mode", NULL};
+	if (!PyArg_ParseTupleAndKeywords(args, kwds, "et|s:__init__", kwlist, 
+		Py_FileSystemDefaultEncoding, &file, &mode)) return -1;
 	
 	self->handle = DBFOpen(file, mode);
 	PyMem_Free(file);
@@ -142,26 +138,38 @@
 		{
 		case FTString:
 			temp = DBFReadStringAttribute(handle, record, field);
-			if (!temp)
-			{
-				PyErr_Format(PyExc_IOError,
-						"Can't read value for row %d column %d",
-						record, field);
-				return NULL;
-			}
-			return PyString_FromString(temp);
+			if (temp) return PyString_FromString(temp);
 
 		case FTInteger:
 			return PyInt_FromLong((long)DBFReadIntegerAttribute(handle, record, field));
 
 		case FTDouble:
 			return PyFloat_FromDouble(DBFReadDoubleAttribute(handle, record, field));
+			
+		case FTLogical:
+			temp = DBFReadLogicalAttribute(handle, record, field);
+			if (temp)
+			{
+				switch (temp[0])
+				{
+				case 'F':
+				case 'N':
+					Py_RETURN_FALSE;
+				case 'T':
+				case 'Y':
+					Py_RETURN_TRUE;
+				}
+			}
+			break;
 
 		default:
 			PyErr_Format(PyExc_TypeError, "Invalid field data type %d", type);
 			return NULL;
 		}
 	}
+	
+	PyErr_Format(PyExc_IOError,	"Can't read value for row %d column %d", record, field);
+	return NULL;
 }    
 
 
@@ -247,16 +255,11 @@
 	char * string_value;
 	int int_value;
 	double double_value;
+	int logical_value;
 
 	if (value == Py_None)
 	{
-		if (!DBFWriteNULLAttribute(handle, record, field))
-		{
-			PyErr_Format(PyExc_IOError,
-				"can't write NULL field %d of record %d",
-				field, record);
-			return 0;
-		}
+		if (DBFWriteNULLAttribute(handle, record, field)) return 1;
 	}
 	else
 	{
@@ -265,38 +268,26 @@
 		case FTString:
 			string_value = PyString_AsString(value);
 			if (!string_value) return 0;
-			if (!DBFWriteStringAttribute(handle, record, field, string_value))
-			{
-				PyErr_Format(PyExc_IOError,
-						"can't write field %d of record %d",
-						field, record);
-				return 0;
-			}
+			if (DBFWriteStringAttribute(handle, record, field, string_value)) return 1;
 			break;
 
 		case FTInteger:
 			int_value = PyInt_AsLong(value);
 			if (int_value == -1 && PyErr_Occurred()) return 0;
-			if (!DBFWriteIntegerAttribute(handle, record, field, int_value))
-			{
-				PyErr_Format(PyExc_IOError,
-						"can't write field %d of record %d",
-						field, record);
-				return 0;
-			}
+			if (DBFWriteIntegerAttribute(handle, record, field, int_value)) return 1;
 			break;
 
 		case FTDouble:
 			double_value = PyFloat_AsDouble(value);
 			if (double_value == -1 && PyErr_Occurred()) return 0;
-			if (!DBFWriteDoubleAttribute(handle, record, field, double_value))
-			{
-				PyErr_Format(PyExc_IOError,
-						"can't write field %d of record %d",
-						field, record);
-				return 0;
-			}
+			if (DBFWriteDoubleAttribute(handle, record, field, double_value)) return 1;
 			break;
+			
+		case FTLogical:
+			logical_value = PyObject_IsTrue(value);
+			if (logical_value == -1) return 0;
+			if (DBFWriteLogicalAttribute(handle, record, field, logical_value ? 'T' : 'F')) return 1;
+			break;
 
 		default:
 			PyErr_Format(PyExc_TypeError, "Invalid field data type %d", type);
@@ -304,7 +295,8 @@
 		}
 	}
 
-	return 1;
+	PyErr_Format(PyExc_IOError,	"can't write field %d of record %d", field, record);
+	return 0;
 }
 
 
@@ -422,45 +414,47 @@
 static struct PyMethodDef dbffile_methods[] = 
 {
 	{"close", (PyCFunction)dbffile_close, METH_NOARGS, 
-		"close()\n"
-		"close DBFFile"},
+		"close() -> None\n\n"
+		"closes DBFFile"},
 	{"field_count", (PyCFunction)dbffile_field_count, METH_NOARGS, 
-		"field_count()\n"
+		"field_count() -> integer\n\n"
 		"returns number of fields currently defined"},
 	{"record_count", (PyCFunction)dbffile_record_count, METH_NOARGS, 
-		"record_count()\n"
+		"record_count() -> integer\n\n"
 		"returns number of records that currently exist"},
 	{"field_info", (PyCFunction)dbffile_field_info, METH_VARARGS,
-		"field_info(field_index)\n"
-		"returns info of a field as a tuple (type, name, width, decimals) with:\n"
-		"-type: the type of the field corresponding to the integer value of one of the constants FTString, FTInteger, ...\n"
-		"-name: the name of the field as a string\n"
-		"-width: the width of the field as a number of characters\n"
-		"-decimals: the number of decimal digits" },
+		"field_info(field_index) -> (type, name, width, decimals)\n\n"
+		"returns info of a field as a tuple with:\n"
+		"- type: the type of the field corresponding to the integer value of one "
+		" of the constants FTString, FTInteger, ...\n"
+		"- name: the name of the field as a string\n"
+		"- width: the width of the field as a number of characters\n"
+		"- decimals: the number of decimal digits" },
 	{"add_field", (PyCFunction)dbffile_add_field, METH_VARARGS,
-		"add_field(type, name, width, decimals)\n"
+		"add_field(type, name, width, decimals) -> field_index\n\n"
 		"adds a new field and returns field index if successful\n"
-		"-type: the type of the field corresponding to the integer value of one of the constants FTString, FTInteger, ...\n"
-		"-name: the name of the field as a string\n"
-		"-width: the width of the field as a number of characters\n"
-		"-decimals: the number of decimal digits" },
+		"- type: the type of the field corresponding to the integer value of one "
+		" of the constants FTString, FTInteger, ...\n"
+		"- name: the name of the field as a string\n"
+		"- width: the width of the field as a number of characters\n"
+		"- decimals: the number of decimal digits" },
 	{"read_attribute", (PyCFunction)dbffile_read_attribute, METH_VARARGS, 
-		"read_attribute(record_index, field_index)\n"
-		"return the value of one field of a record"},
+		"read_attribute(record_index, field_index) -> value\n\n"
+		"returns the value of one field of a record"},
 	{"read_record", (PyCFunction)dbffile_read_record, METH_VARARGS, 
-		"read_record(record_index)\n"
-		"return an entire record as a dict of field names and values"},
+		"read_record(record_index) -> dict\n\n"
+		"returns an entire record as a dictionary of field names and values"},
 	{"write_field", (PyCFunction)dbffile_write_field, METH_VARARGS, 
 		"write_field(record_index, field_index, new_value)\n"
-		"write a single field of a record"},
+		"writes a single field of a record"},
 	{"write_record", (PyCFunction)dbffile_write_record, METH_VARARGS, 
-		"write_record(record_index, record)\n"
-		"write an entire record as a dict or a sequence\n"
-		"record can either be a dictionary in which case the keys are used as field names, "
+		"write_record(record_index, record) -> record_index\n\n"
+		"Writes an entire record as a dict or a sequence, and return index of record\n"
+		"Record can either be a dictionary in which case the keys are used as field names, "
 		"or a sequence that must have an item for every field (length = field_count())"},
 #if HAVE_UPDATE_HEADER
 	{"commit", (PyCFunction)dbffile_read_record, METH_NOARGS, 
-		"commit()"},
+		"commit() -> None"},
 #endif
 	{NULL}
 };
@@ -516,10 +510,10 @@
 static struct PyMethodDef dbflib_methods[] = 
 {
 	{"open", (PyCFunction)dbflib_open, METH_VARARGS, 
-		"open(filename [, mode])\n"
-		"open a DBFFile" },
+		"open(name [, mode]) -> DBFFile\n\n"
+		"opens a DBFFile" },
 	{"create", (PyCFunction)dbflib_create, METH_VARARGS, 
-		"create(filename)\n"
+		"create(name) -> DBFFile\n\n"
 		"create a DBFFile" },
 	{NULL}
 };
@@ -536,6 +530,7 @@
 	PYSHAPELIB_ADD_CONSTANT(FTString);
 	PYSHAPELIB_ADD_CONSTANT(FTInteger);
 	PYSHAPELIB_ADD_CONSTANT(FTDouble);
+	PYSHAPELIB_ADD_CONSTANT(FTLogical);
 	PYSHAPELIB_ADD_CONSTANT(FTInvalid);
 	PyModule_AddIntConstant(module, "_have_commit", HAVE_UPDATE_HEADER);
 }

Modified: branches/WIP-pyshapelib-bramz/libraries/pyshapelib/pyshapelib_common.h
===================================================================
--- branches/WIP-pyshapelib-bramz/libraries/pyshapelib/pyshapelib_common.h	2007-03-15 13:48:58 UTC (rev 2744)
+++ branches/WIP-pyshapelib-bramz/libraries/pyshapelib/pyshapelib_common.h	2007-03-15 22:27:02 UTC (rev 2745)
@@ -72,4 +72,7 @@
 		PyModule_AddObject(module, name, (PyObject*)&type); \
 	}
 
+#define PYSHAPELIB_NO_DATA_LIMIT 1e-38
+#define PYSHAPELIB_NO_DATA 0
+
 #endif
\ No newline at end of file

Modified: branches/WIP-pyshapelib-bramz/libraries/pyshapelib/pytest.py
===================================================================
--- branches/WIP-pyshapelib-bramz/libraries/pyshapelib/pytest.py	2007-03-15 13:48:58 UTC (rev 2744)
+++ branches/WIP-pyshapelib-bramz/libraries/pyshapelib/pytest.py	2007-03-15 22:27:02 UTC (rev 2745)
@@ -4,8 +4,6 @@
 #       The the shapefile module
 #
 
-print "--- testing shapelib ---"
-
 def test_shpobject(obj):
     # The vertices method returns the shape as a list of lists of tuples.
     print "vertices:", obj.vertices()
@@ -112,10 +110,67 @@
     print tree.find_shapes(minima[:2], maxima[:2])
 
 
+print "--- testing shapelib ---"
+
 make_shapefile("testfile")
 read_shapefile("testfile")
 
 #
+#		Test MultiPatch shapefiles
+#
+
+def make_multipatch(filename):
+    print "\n* Creating multipatch ShapeFile"
+    
+    # Create a shapefile with multipatches
+    outfile = shapelib.create(filename, shapelib.SHPT_MULTIPATCH)
+
+    # Create a quad as a triangle strip and as a triangle fan, in ONE object!
+    # Multipatch shapefiles use XYZM vertices, but you can get away with
+    # only specifying X and Y, Z and M are zero by default.
+    print "\nA triangle strip"
+    obj = shapelib.SHPObject(shapelib.SHPT_MULTIPATCH, 0,
+        [[(0, 0), (0, 10), (10, 0), (10, 10)],
+         [(20, 20), (20, 30), (30, 30), (30, 20)]], 
+        [shapelib.SHPP_TRISTRIP, shapelib.SHPP_TRIFAN])
+    test_shpobject(obj)
+    outfile.write_object(-1, obj)
+    
+    # A polygon as an Outer ring and inner ring, with XYZ coordinates
+    # and measure values M.  Here we will use the part types to specify 
+    # their particular type.
+    #
+    # You can have more than one polygon in a single Object, as long
+    # as you obey the following sequence: each polygon starts with an
+    # outer ring, followed by its holes as inner rings.  
+    #
+    # None is also accepted as M value to specify no-data.  The ESRI
+    # Shapefile specs define any M value smaller than 1e-38 as no-data.
+    # shapelib will store no-data as a zero. 
+    #
+    # If you don't need the M value, you can leave it out and use triples 
+    # as vertices instead.  For the first half of the inner ring,
+    # we used None to specify no-data.  In the second half, we just 
+    # omitted it.
+    #
+    print "\nA polygon as outer ring and inner ring with XYZM coordinates"
+    obj = shapelib.SHPObject(shapelib.SHPT_MULTIPATCH, 1,
+        [[(0, 0, 0, 35.3), (0, 40, 10, 15.4), (40, 40, 20, 9.5), (40, 0, 10, 24.6), (0, 0, 0, 31.8)],
+         [(10, 10, 5, None), (20, 10, 10, None), (20, 20, 15), (10, 20, 10, 20),(10, 10, 5)]],
+        [shapelib.SHPP_OUTERRING, shapelib.SHPP_INNERRING])
+    test_shpobject(obj)
+    outfile.write_object(-1, obj)
+
+    # close the file.
+    outfile.close()
+    
+
+print "--- testing multipatch ---"
+
+make_multipatch("multipatch")
+read_shapefile("multipatch")
+    
+#
 #       Test the DBF file module.
 #
 
@@ -127,14 +182,15 @@
     dbf.add_field("NAME", dbflib.FTString, 20, 0)
     dbf.add_field("INT", dbflib.FTInteger, 10, 0)
     dbf.add_field("FLOAT", dbflib.FTDouble, 10, 4)
+    dbf.add_field("BOOL", dbflib.FTLogical, 1, 0)
 
 def add_dbf_records(file):
     # add some records to file
     dbf = dbflib.open(file, "r+b")
     # Records can be added as a dictionary...
-    dbf.write_record(0, {'NAME': "Weatherwax", "INT":1, "FLOAT":3.1415926535})
+    dbf.write_record(0, {'NAME': "Weatherwax", "INT":1, "FLOAT":3.1415926535, "BOOL":True})
     # ... or as a sequence
-    dbf.write_record(1, ("Ogg", 2, -1000.1234))
+    dbf.write_record(1, ("Ogg", 2, -1000.1234, False))
 
 def list_dbf(file):
     # print the contents of a dbf file to stdout
@@ -143,12 +199,14 @@
     format = ""
     for i in range(dbf.field_count()):
         type, name, len, decc = dbf.field_info(i)
-        if type == 0:
+        if type == dbflib.FTString:
             format = format + " %%(%s)%ds" % (name, len)
-        elif type == 1:
+        elif type == dbflib.FTInteger:
             format = format + " %%(%s)%dd" % (name, len)
-        elif type == 2:
+        elif type == dbflib.FTDouble:
             format = format + " %%(%s)%dg" % (name, len)
+        elif type == dbflib.FTLogical:
+            format = format + " %%(%s)s" % name
     print format
     for i in range(dbf.record_count()):
         print format % dbf.read_record(i)

Modified: branches/WIP-pyshapelib-bramz/libraries/pyshapelib/shapelibmodule.c
===================================================================
--- branches/WIP-pyshapelib-bramz/libraries/pyshapelib/shapelibmodule.c	2007-03-15 13:48:58 UTC (rev 2744)
+++ branches/WIP-pyshapelib-bramz/libraries/pyshapelib/shapelibmodule.c	2007-03-15 22:27:02 UTC (rev 2745)
@@ -67,6 +67,9 @@
 	self->ob_type->tp_free((PyObject*)self);
 }
 
+static int unpack_vertex(PyObject* vertex, int vertex_type, 
+		double* xs, double* ys, double* zs, double* ms, int offset);
+
 /* The constructor of SHPObject. parts is a list of lists of tuples
 * describing the parts and their vertices just likethe output of the
 * vertices() method. part_type_list is the list of part-types and may
@@ -97,7 +100,7 @@
 	int has_m;
 	
 	int i;
-	int ok, return_code = -1;
+	int return_code = -1;
 	
 	/* first, unpack parameters */
 	if (kwds != NULL && PyDict_Size(kwds) > 0)
@@ -202,26 +205,13 @@
 		for (j = 0; j < length; ++j)
 		{
 			PyObject* vertex = PySequence_ITEM(part, j);
-			switch (vertex_type)
+			if (!unpack_vertex(vertex, vertex_type, xs, ys, zs, ms, part_start + j))
 			{
-			case vtXY:
-				ok = PyArg_ParseTuple(vertex, "dd:__init__", xs + part_start + j, ys + part_start + j);
-				break;
-			case vtXYM:
-				ok = PyArg_ParseTuple(vertex, "ddd:__init__", xs + part_start + j, ys + part_start + j, ms + part_start + j);
-				break;
-			case vtXYZM:
-				ms[part_start + j] = 0.;
-				ok = PyArg_ParseTuple(vertex, "ddd|d:__init__", xs + part_start + j, ys + part_start + j, zs + part_start + j,
-					ms + part_start + j);
-				break;
-			}
-			Py_DECREF(vertex);
-			if (!ok)
-			{
+				Py_DECREF(vertex);
 				PyErr_SetString(PyExc_TypeError, "at least one vertex is of the wrong format");
 				goto exit;
 			}
+			Py_DECREF(vertex);
 		}
 		Py_DECREF(part);
 		part = NULL;
@@ -242,6 +232,71 @@
 	return return_code;
 }
 
+/* helper for shpobject_init. Unpacks vertices 
+ */
+static int unpack_vertex(PyObject* vertex, int vertex_type, 
+		double* xs, double* ys, double* zs, double* ms, int offset)
+{
+	int ok;
+	PyObject* m_object;
+	PyObject *err_type, *err_value, *err_traceback;
+
+	switch (vertex_type)
+	{
+	case vtXY:
+		return PyArg_ParseTuple(vertex, "dd:__init__", xs + offset, ys + offset);
+
+	case vtXYM:
+		ms[offset] = PYSHAPELIB_NO_DATA;
+		ok = PyArg_ParseTuple(vertex, "dd|d:__init__", xs + offset, ys + offset, ms + offset);
+		if (!ok)
+		{
+			/* maybe they specified None as M value */
+			PyErr_Fetch(&err_type, &err_value, &err_traceback);
+			ok = PyArg_ParseTuple(vertex, "ddO:__init__", xs + offset, ys + offset, &m_object);
+			if (ok && m_object == Py_None)
+			{
+				Py_XDECREF(err_type);
+				Py_XDECREF(err_value);
+				Py_XDECREF(err_traceback);
+			}
+			else
+			{
+				PyErr_Restore(err_type, err_value, err_traceback);
+			}
+		}
+		return ok;
+
+	case vtXYZM:
+		zs[offset] = 0.;
+		ms[offset] = PYSHAPELIB_NO_DATA;
+		ok = PyArg_ParseTuple(vertex, "dd|dd:__init__", xs + offset, ys + offset,
+				zs + offset, ms + offset);
+		if (!ok)
+		{
+			/* maybe they specified None as M value */
+			PyErr_Fetch(&err_type, &err_value, &err_traceback);
+			ok = PyArg_ParseTuple(vertex, "dddO:__init__", xs + offset, ys + offset, 
+					zs + offset, &m_object);
+			if (ok && m_object == Py_None)
+			{
+				Py_XDECREF(err_type);
+				Py_XDECREF(err_value);
+				Py_XDECREF(err_traceback);
+			}
+			else
+			{
+				PyErr_Restore(err_type, err_value, err_traceback);
+			}
+		}
+		return ok;
+
+	default:
+		PyErr_SetString(PyExc_NotImplementedError, "vertex type not implemented");
+		return 0;
+	}
+}
+
 /*
 * The extents() method of SHPObject.
 *
@@ -340,6 +395,7 @@
 		case vtXYM:
 			vertex = Py_BuildValue("ddd", object->padfX[index], object->padfY[index], 
 				object->padfM[index]);
+			break;
 		case vtXYZM:
 			vertex = Py_BuildValue("dddd", object->padfX[index], object->padfY[index], 
 				object->padfZ[index], object->padfM[index]);
@@ -437,15 +493,16 @@
 static struct PyMethodDef shpobject_methods[] = 
 {
 	{"extents", (PyCFunction)shpobject_extents, METH_NOARGS, 
-		"extents()\n"
-		"returns ((x_min, y_min, z_min, m_min), (x_max, y_max, z_max, m_max)), the 4D bounding box of the SHPObject"},
+		"extents() -> ((x_min, y_min, z_min, m_min), (x_max, y_max, z_max, m_max))\n\n"
+		"returns the 4D bounding box of the SHPObject"},
 	{"vertices", (PyCFunction)shpobject_vertices, METH_NOARGS, 
-		"vertices()\n"
-		"returns [[(x, y, ...), ...], ...], a list of object parts, where each part is again a list of vertices.\n"
-		"each vertex is a tuple of two to four doubles, depending on the object type."},
+		"vertices() ->  [[(x, y, ...), ...], ...]\n\n"
+		"Returns a list of object parts, where each part is again a list of vertices. "
+		"Each vertex is a tuple of two to four doubles, depending on the object type."},
 	{"part_types", (PyCFunction)shpobject_part_types, METH_NOARGS, 
-		"part_types()\n"
-		"returns a tuple of integers, each integer indicating the type of the corresponding part in vertices()"},
+		"part_types() -> tuple\n\n"
+		"returns a tuple of integers, each integer indicating the type of the "
+		"corresponding part in vertices()"},
 	{NULL}
 };
 
@@ -492,14 +549,13 @@
 {
 	char* file;
 	char* mode = "rb";
-	if (kwds != NULL && PyDict_Size(kwds) > 0)
-	{
-		PyErr_Format(PyExc_TypeError, "shapelib.ShapeFile.__init__ takes no keyword arguments");
-		return -1;
-	}
-	if (!PyArg_ParseTuple(args, "et|s:__init__", Py_FileSystemDefaultEncoding, &file, &mode)) return -1;
+	static char *kwlist[] = {"name", "mode", NULL};
+	if (!PyArg_ParseTupleAndKeywords(args, kwds, "et|s:__init__", kwlist, 
+		Py_FileSystemDefaultEncoding, &file, &mode)) return -1;
 	
 	self->handle = SHPOpen(file, mode);
+	PyMem_Free(file);
+	
 	return self->handle ? 0 : -1;
 }
 
@@ -580,23 +636,23 @@
 static struct PyMethodDef shapefile_methods[] = 
 {
 	{"close", (PyCFunction)shapefile_close, METH_NOARGS, 
-		"close()\n"
+		"close() -> None\n\n"
 		"close the shape file" },
 	{"info", (PyCFunction)shapefile_info, METH_NOARGS,
-		"info()\n"
-		"returns (num_shapes, type, (x_min, y_min, z_min, m_min), (x_max, y_max, z_max, m_max)) with:\n"
-		"-num_shapes: the number of the objects in the file\n"
-		"-type: the type of the shape file (SHPT_POINT, SHPT_POLYGON, ...)\n"
-		"-(x_min, y_min, z_min, m_min), (x_max, y_max, z_max, m_max): 4D bounding box of the data in the shape file" },
+		"info() -> (num_shapes, type, (x_min, y_min, z_min, m_min), (x_max, y_max, z_max, m_max))\n\n"
+		"returns info about ShapeFile with:\n"
+		"- num_shapes: the number of the objects in the file\n"
+		"- type: the type of the shape file (SHPT_POINT, SHPT_POLYGON, ...)\n"
+		"- (x_min, ...), (x_max, ...): 4D bounding box of the data in the shape file" },
 	{"read_object", (PyCFunction)shapefile_read_object, METH_VARARGS, 
-		"read_object(id)\n"
-		"Return object indexed by id" },
+		"read_object(id) -> SHPObject\n\n"
+		"Returns shape indexed by id" },
 	{"write_object", (PyCFunction)shapefile_write_object, METH_VARARGS, 
-		"write_object(id, object)\n"
-		"Write an object at index id.\n"
-		"If id == -1, the object is appended at the end of the shape file"},
+		"write_object(id, object) -> id\n\n"
+		"Write an object at index id, and returns id."
+		"If id == -1, the object is appended at the end of the shape file."},
 	{"cobject", (PyCFunction)shapefile_cobject, METH_NOARGS, 
-		"cobject()\n"
+		"cobject() -> CObject\n\n"
 		"Return the shapelib SHPHandle as a Python CObject"},
 	{NULL}
 };
@@ -626,10 +682,13 @@
 	result = PyObject_New(ShapeFileObject, &ShapeFileType);
 	if (!result)
 	{
+		PyMem_Free(file);
 		return PyErr_NoMemory();
 	}
 	
 	result->handle = SHPCreate(file, type);
+	PyMem_Free(file);
+	
 	if (!result->handle)
 	{
 		PyObject_Del((PyObject*)result);
@@ -671,19 +730,19 @@
 static struct PyMethodDef shapelib_methods[] = 
 {
 	{"open", (PyCFunction)shapelib_open, METH_VARARGS, 
-		"open(filename [, mode='rb'])\n"
-		"open a ShapeFile" },
+		"open(name [, mode='rb']) -> ShapeFile\n\n"
+		"opens a ShapeFile" },
 	{"create", (PyCFunction)shapelib_create, METH_VARARGS, 
-		"create(filename, type)\n"
-		"create a ShapeFile of a certain type (one of SHPT_POINT, SHPT_POLYGON)" },
+		"create(name, type) -> ShapeFile\n\n"
+		"creates a ShapeFile of a certain type (one of SHPT_POINT, SHPT_POLYGON)" },
 	{"c_api", (PyCFunction)shapelib_c_api, METH_NOARGS, 
-		"c_api()\n"
-		"get C API of shapelib" },
+		"c_api() -> CObject\n\n"
+		"get C API of shapelib as a CObject" },
 	{"type_name", (PyCFunction)shapelib_type_name, METH_VARARGS, 
-		"type_name(type)\n"
+		"type_name(type) -> string\n\n"
 		"return type as string" },
 	{"part_type_name", (PyCFunction)shapelib_part_type_name, METH_VARARGS, 
-		"part_type_name(part_type)\n"
+		"part_type_name(part_type) -> string\n\n"
 		"return part type as string" },
 	{NULL}
 };

Modified: branches/WIP-pyshapelib-bramz/libraries/pyshapelib/shptreemodule.c
===================================================================
--- branches/WIP-pyshapelib-bramz/libraries/pyshapelib/shptreemodule.c	2007-03-15 13:48:58 UTC (rev 2744)
+++ branches/WIP-pyshapelib-bramz/libraries/pyshapelib/shptreemodule.c	2007-03-15 22:27:02 UTC (rev 2745)
@@ -166,8 +166,11 @@
 };
 
 
-void
-initshptree()
+#ifdef NDEBUG
+PyMODINIT_FUNC initshptree(void)
+#else
+PyMODINIT_FUNC initshptree_d(void)
+#endif
 {
     SHPTreeType.ob_type = &PyType_Type;
 



More information about the Thuban-commits mailing list