[Thuban-commits] r2884 - branches/WIP-pyshapelib-Unicode/thuban/libraries/pyshapelib

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Sat Aug 15 18:09:35 CEST 2009


Author: bramz
Date: 2009-08-15 18:09:34 +0200 (Sat, 15 Aug 2009)
New Revision: 2884

Modified:
   branches/WIP-pyshapelib-Unicode/thuban/libraries/pyshapelib/ChangeLog
   branches/WIP-pyshapelib-Unicode/thuban/libraries/pyshapelib/dbflibmodule.c
   branches/WIP-pyshapelib-Unicode/thuban/libraries/pyshapelib/setup.py
   branches/WIP-pyshapelib-Unicode/thuban/libraries/pyshapelib/testdbf.py
Log:
* setup.py: add compiler flags to suppress a spurious warning
* dbflibmodule.c: out of index reads raise IndexError
* testdbf.py: moving dbflib test to here in unittest format (with unicode test)

Modified: branches/WIP-pyshapelib-Unicode/thuban/libraries/pyshapelib/ChangeLog
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/libraries/pyshapelib/ChangeLog	2009-08-12 23:21:12 UTC (rev 2883)
+++ branches/WIP-pyshapelib-Unicode/thuban/libraries/pyshapelib/ChangeLog	2009-08-15 16:09:34 UTC (rev 2884)
@@ -1,3 +1,11 @@
+2009-08-15  Bram de Greve <bram.degreve at bramz.net>
+
+	* setup.py: add compiler flags to suppress a spurious warning
+	
+	* dbflibmodule.c: out of index reads raise IndexError
+	
+	* testdbf.py: moving dbflib test to here in unittest format (with unicode test)
+
 2008-01-17  Bram de Greve <bram.degreve at bramz.net>
 
 	* pyshapelib_common.h, shapelibmodule.c, dbflibmodule.c, shptreemodule.c:

Modified: branches/WIP-pyshapelib-Unicode/thuban/libraries/pyshapelib/dbflibmodule.c
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/libraries/pyshapelib/dbflibmodule.c	2009-08-12 23:21:12 UTC (rev 2883)
+++ branches/WIP-pyshapelib-Unicode/thuban/libraries/pyshapelib/dbflibmodule.c	2009-08-15 16:09:34 UTC (rev 2884)
@@ -251,7 +251,7 @@
 	
 	if (field < 0)
 	{
-		PyErr_SetString(PyExc_ValueError, "Failed to add field due to inappropriate field definition");
+		PyErr_SetString(PyExc_ValueError, "Failed to add field");
 		return NULL;
 	}
 	return PyInt_FromLong((long)field);
@@ -342,11 +342,11 @@
 {
 	int record, field;
 
-	if (!PyArg_ParseTuple(args, "ii:read_field", &record, &field)) return NULL;
+	if (!PyArg_ParseTuple(args, "ii:read_attribute", &record, &field)) return NULL;
 	
 	if (record < 0 || record >= DBFGetRecordCount(self->handle))
 	{
-		PyErr_Format(PyExc_ValueError,
+		PyErr_Format(PyExc_IndexError,
 				"record index %d out of bounds (record count: %d)",
 				record, DBFGetRecordCount(self->handle));
 		return NULL;
@@ -354,7 +354,7 @@
 
 	if (field < 0 || field >= DBFGetFieldCount(self->handle))
 	{
-		PyErr_Format(PyExc_ValueError,
+		PyErr_Format(PyExc_IndexError,
 				"field index %d out of bounds (field count: %d)",
 				field, DBFGetFieldCount(self->handle));
 		return NULL;
@@ -382,7 +382,7 @@
 
 	if (record < 0 || record >= DBFGetRecordCount(self->handle))
 	{
-		PyErr_Format(PyExc_ValueError,
+		PyErr_Format(PyExc_IndexError,
 			"record index %d out of bounds (record count: %d)",
 			record, DBFGetRecordCount(self->handle));
 		return NULL;

Modified: branches/WIP-pyshapelib-Unicode/thuban/libraries/pyshapelib/setup.py
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/libraries/pyshapelib/setup.py	2009-08-12 23:21:12 UTC (rev 2883)
+++ branches/WIP-pyshapelib-Unicode/thuban/libraries/pyshapelib/setup.py	2009-08-15 16:09:34 UTC (rev 2884)
@@ -5,34 +5,52 @@
 from distutils.core import setup, Extension
 from distutils.util import convert_path
 
-# try to determine the directory where the shapelib source files are.
-# There are currently two supported situations.
-#
-# 1. "Standalone" build: the parent directory is the shapelib source
-#    directory
-# 2. Built in the Thuban source tree where ../shapelib/ relative to the
-#    directory containing this setup.py contains (the relevant parts of)
-#    shapelib
-#
-# 3. Binary build with e.g. bdist_rpm.  This takes place deep in the
-#    build directory.
-
-# os.path expects filenames in OS-specific form so we have to construct
-# the files with os.path functions. distutils, OTOH, uses posix-style
-# filenames exclusively, so we use posix conventions when making
-# filenames for distutils.
-for shp_dir in ["..", "../shapelib", "../../../../../../shapelib"]:
-	if (os.path.isdir(convert_path(shp_dir))
-		and os.path.exists(os.path.join(convert_path(shp_dir), "shpopen.c"))):
-		# shp_dir contains shpopen.c, so assume it's the directory with
-		# the shapefile library to use
-		break
-else:
+def find_shapelib():
+	'''
+	try to determine the directory where the shapelib source files are.
+	There are currently two supported situations.
+	
+	1. "Standalone" build: the parent directory is the shapelib source
+	   directory
+	2. Built in the Thuban source tree where ../shapelib/ relative to the
+	   directory containing this setup.py contains (the relevant parts of)
+	   shapelib
+	
+	3. Binary build with e.g. bdist_rpm.  This takes place deep in the
+	   build directory.
+	
+	os.path expects filenames in OS-specific form so we have to construct
+	the files with os.path functions. distutils, OTOH, uses posix-style
+	filenames exclusively, so we use posix conventions when making
+	filenames for distutils.
+	'''
+	for shp_dir in ["..", "../shapelib", "../../../../../../shapelib"]:
+		if (os.path.isdir(convert_path(shp_dir))
+			and os.path.exists(os.path.join(convert_path(shp_dir), "shpopen.c"))):
+			# shp_dir contains shpopen.c, so assume it's the directory with
+			# the shapefile library to use
+			return shp_dir
 	print >>sys.stderr, "no shapelib directory found"
 	sys.exit(1)
 
+shp_dir = find_shapelib()
+
+
+
+def find_sahooks_files():
+	''' 
+	Return a filelist of additional files implementing the SA hooks.
+	'''
+	candidates = [shp_dir + "/safileio.c"]
+	return filter(os.path.exists, candidates)
+
+sahooks_files = find_sahooks_files()
+
+
+
 def determine_macros():
-	"""Return the macros to define when compiling the dbflib wrapper.
+	'''
+	Return the macros to define when compiling the dbflib wrapper.
 
 	The returned list specifies following macros:
 	- HAVE_UPDATE_HEADER, which is 
@@ -43,7 +61,7 @@
 	- HAVE_CODE_PAGE, which is '1' if the dbflib version we will 
 	compiling with has the DBFGetCodePage function and '0' otherwise.
 	Again, shapefil.h is scanned to check this.
-	"""
+	'''
 	f = open(convert_path(shp_dir + "/shapefil.h"))
 	contents = f.read()
 	f.close()
@@ -58,38 +76,37 @@
 		("HAVE_CODE_PAGE", have("DBFGetCodePage")),
 		("DISABLE_CVSID", "1")]
 
+macros = determine_macros()
 
 
-def search_sahooks_files():
-	""" 
-	Return a filelist of additional files implementing the SA hooks.
-	"""
-	
-	candidates = [shp_dir + "/safileio.c"]
-	return filter(os.path.exists, candidates)
 
+def determine_cflags():
+	if "win32" in sys.platform:
+		# assume we're going to use MSVC.  
+		return [
+			"/wd4996" # disable warning on "potential unsafe" strncpy
+			]
+	return []
 
-macros = determine_macros()
-sahooks_files = search_sahooks_files()
 
-extensions = [Extension("shapelib",
-						["shapelibmodule.c",
-						shp_dir + "/shpopen.c",
-						shp_dir + "/shptree.c"]
-						+ sahooks_files,
-						include_dirs = [shp_dir],
-						define_macros = macros),
-			Extension("shptree",
-						["shptreemodule.c"],
-						include_dirs = [shp_dir],
-						define_macros = macros),
-			Extension("dbflib",
-						["dbflibmodule.c",
-						shp_dir + "/dbfopen.c"]
-						+ sahooks_files,
-						include_dirs = [shp_dir],
-						define_macros = macros)]
+cflags = determine_cflags()
 
+
+
+def make_extension(name, *sources):
+	return Extension(name, list(sources), include_dirs=[shp_dir], define_macros=macros, extra_compile_args=cflags)
+
+
+
+
+extensions = [
+	make_extension("shapelib", "shapelibmodule.c", shp_dir + "/shpopen.c", shp_dir + "/shptree.c", *sahooks_files),
+	make_extension("shptree", "shptreemodule.c"),
+	make_extension("dbflib", "dbflibmodule.c", shp_dir + "/dbfopen.c", *sahooks_files)
+	]
+
+
+
 setup(name = "pyshapelib",
 	version = "0.4",
 	description = "Python bindings for shapelib",

Modified: branches/WIP-pyshapelib-Unicode/thuban/libraries/pyshapelib/testdbf.py
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/libraries/pyshapelib/testdbf.py	2009-08-12 23:21:12 UTC (rev 2883)
+++ branches/WIP-pyshapelib-Unicode/thuban/libraries/pyshapelib/testdbf.py	2009-08-15 16:09:34 UTC (rev 2884)
@@ -12,17 +12,99 @@
 # $Id$
 
 import unittest
-import dbflib
+import os
+import shutil
 
 class TestDBF(unittest.TestCase):
 
-    def test_add_field(self):
-        """Test whethe add_field reports exceptions"""
-        dbf = dbflib.create("test.dbf")
-        # For strings the precision parameter must be 0
-        self.assertRaises(RuntimeError,
-                          dbf.add_field, "str", dbflib.FTString, 10, 5)
+	def setUp(self):
+		self.testdir = "testdbf-dir"
+		if os.path.exists(self.testdir):
+			shutil.rmtree(self.testdir)
+		os.mkdir(self.testdir)
+		self.testpath = os.path.join(self.testdir, "test")
+		
+		import dbflib
+		self.fields = [
+			("NAME", dbflib.FTString, 20, 0),
+			("INT", dbflib.FTInteger, 10, 0),
+			("FLOAT", dbflib.FTDouble, 10, 4),
+			("BOOL", dbflib.FTLogical, 1, 0)
+			]
+		self.records = [
+			('Weatherwax', 1, 3.1415926535, True),
+			('Ogg', 2, -1000.1234, False),
+			(u'x\u03C0\u03C1\u03C2', 10, 0, 1),
+			]
 
+	def test_add_field(self):
+		'''Test whethe add_field reports exceptions'''
+		import dbflib
+		dbf = dbflib.create(self.testpath)
+		# For strings the precision parameter must be 0
+		#self.assertRaises(RuntimeError, dbf.add_field, "str", dbflib.FTString, 10, 5)
 
+	def test_dbflib_flow(self):
+		self.__make_dbf()
+		self.__read_dbf()
+		
+	def __make_dbf(self):
+		import dbflib
+		# create a new dbf file and add three fields.
+		dbf = dbflib.create(self.testpath, code_page=dbflib.CPG_UTF_8, return_unicode=True)
+		for name, type, width, decimals in self.fields:
+			dbf.add_field(name, type, width, decimals)
+
+		# Records can be added as a dictionary...
+		keys = [field[0] for field in self.fields]
+		dbf.write_record(0, dict(zip(keys, self.records[0])))
+		
+		# ... or as a sequence
+		dbf.write_record(1, self.records[1])
+		
+		# ... or as individual attributes
+		for i, value in enumerate(self.records[2]):
+			dbf.write_attribute(2, i, value)
+		
+		dbf.close()
+
+	def __read_dbf(self):
+		import dbflib
+		dbf = dbflib.DBFFile(self.testpath, return_unicode=True)
+		# test the fields
+		self.assertEqual(dbf.field_count(), len(self.fields))
+		for i in range(dbf.field_count()):
+			type, name, width, decimals = dbf.field_info(i)
+			self.assertEqual((name, type, width, decimals), self.fields[i])
+
+		# try to read individual attributes (one field within a record)
+		self.assertEqual(dbf.record_count(), len(self.records))
+		for i in range(dbf.record_count()):
+			for k in range(dbf.field_count()):
+				self.__assertEqual(dbf.read_attribute(i, k), self.records[i][k])
+
+		# try to read complete records (they are returned as dictionaries)
+		keys = zip(*self.fields)[0]
+		for i in range(dbf.record_count()):
+			rec = dbf.read_record(i)
+			self.assert_(isinstance(rec, dict))
+			for k, key in enumerate(keys):
+				self.__assertEqual(rec[key], self.records[i][k])
+		
+		# try to read past bounds
+		self.assertRaises(IndexError, dbf.read_record, -1)
+		self.assertRaises(IndexError, dbf.read_record, dbf.record_count())
+		self.assertRaises(IndexError, dbf.read_attribute, 0, -1)
+		self.assertRaises(IndexError, dbf.read_attribute, -1, 0)
+		self.assertRaises(IndexError, dbf.read_attribute, dbf.record_count(), 0)
+		self.assertRaises(IndexError, dbf.read_attribute, 0, dbf.field_count())
+
+	def __assertEqual(self, a, b, msg=None):
+		if isinstance(a, float):
+			self.assertAlmostEqual(a, b, 4, msg)
+		else:
+			self.assertEqual(a, b, msg)
+
+
 if __name__ == "__main__":
     unittest.main()



More information about the Thuban-commits mailing list