1
0
mirror of https://github.com/django/django.git synced 2025-07-04 09:49:12 +00:00

gis: Fixed segfault on invalid WKT (added test for both invalid HEX and WKT). GEOSException now a proper exception. Updated error handler.

git-svn-id: http://code.djangoproject.com/svn/django/branches/gis@5030 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Justin Bronn 2007-04-19 12:49:40 +00:00
parent 522400d8ef
commit e30720a2dc
3 changed files with 47 additions and 29 deletions

View File

@ -82,6 +82,9 @@ elif os.name == 'posix':
else: else:
raise GEOSException, 'Unsupported OS "%s"' % os.name raise GEOSException, 'Unsupported OS "%s"' % os.name
# The GEOSException class
class GEOSException(Exception): pass
# Getting the GEOS C library. The C interface (CDLL) is used for # Getting the GEOS C library. The C interface (CDLL) is used for
# both *NIX and Windows. # both *NIX and Windows.
# See the GEOS C API source code for more details on the library function calls: # See the GEOS C API source code for more details on the library function calls:
@ -98,11 +101,11 @@ notice_h = NOTICEFUNC(notice_h)
ERRORFUNC = CFUNCTYPE(None, c_char_p, c_char_p) ERRORFUNC = CFUNCTYPE(None, c_char_p, c_char_p)
def error_h(fmt, list): def error_h(fmt, list):
# TODO: Figure out why improper format code given w/some GEOS errors if list:
if not list: err_msg = fmt % list
sys.stderr.write(fmt)
else: else:
sys.stderr.write('ERROR: %s' % str(list)) err_msg = fmt
sys.stderr.write(err_msg)
error_h = ERRORFUNC(error_h) error_h = ERRORFUNC(error_h)
# The initGEOS routine should be called first, however, that routine takes # The initGEOS routine should be called first, however, that routine takes
@ -111,44 +114,42 @@ error_h = ERRORFUNC(error_h)
# "extern void GEOS_DLL initGEOS(GEOSMessageHandler notice_function, GEOSMessageHandler error_function);" # "extern void GEOS_DLL initGEOS(GEOSMessageHandler notice_function, GEOSMessageHandler error_function);"
lgeos.initGEOS(notice_h, error_h) lgeos.initGEOS(notice_h, error_h)
class GEOSException:
"Exception class for any GEOS-related errors."
def __init__(self, msg):
self.msg = msg
def __str__(self):
return repr(self.msg)
class GEOSGeometry: class GEOSGeometry:
"A class that, generally, encapsulates a GEOS geometry." "A class that, generally, encapsulates a GEOS geometry."
#### Python 'magic' routines #### #### Python 'magic' routines ####
def __init__(self, input, geom_type='wkt'): def __init__(self, input, geom_type='wkt'):
"Takes an input and the type of the input for initialization." "Takes an input and the type of the input for initialization."
if geom_type == 'wkt': if geom_type == 'wkt':
# If the geometry is in WKT form # If the geometry is in WKT form
self._g = lgeos.GEOSGeomFromWKT(c_char_p(input)) buf = create_string_buffer(input)
g = lgeos.GEOSGeomFromWKT(buf)
elif geom_type == 'hex': elif geom_type == 'hex':
# If the geometry is in EWHEX form. # If the geometry is in HEX form.
sz = c_size_t(len(input)) sz = c_size_t(len(input))
buf = create_string_buffer(input) buf = create_string_buffer(input)
self._g = lgeos.GEOSGeomFromHEX_buf(buf, sz) g = lgeos.GEOSGeomFromHEX_buf(buf, sz)
elif geom_type == 'geos': elif geom_type == 'geos':
# When the input is a C pointer (Python integer) # When the input is a C pointer (Python integer)
self._g = input g = input
else: else:
# Invalid geometry type. # Invalid geometry type.
raise GEOSException, 'Improper geometry input type!' raise GEOSException, 'Improper geometry input type!'
# If the geometry pointer is NULL (0), then raise an exception.
if not g:
self._g = False # Setting this before raising the exception
raise GEOSException, 'Invalid %s given!' % geom_type.upper()
else:
self._g = g
# Setting the class type (e.g. 'Point', 'Polygon', etc.) # Setting the class type (e.g. 'Point', 'Polygon', etc.)
self.__class__ = GEO_CLASSES[self.geom_type] self.__class__ = GEO_CLASSES[self.geom_type]
# If the geometry pointer is NULL (0), then raise an exception.
if not self._g:
raise GEOSException, 'Could not initialize on input!'
def __del__(self): def __del__(self):
"This cleans up the memory allocated for the geometry." "This cleans up the memory allocated for the geometry."
lgeos.GEOSGeom_destroy(self._g) if self._g: lgeos.GEOSGeom_destroy(self._g)
def __str__(self): def __str__(self):
"WKT is used for the string representation." "WKT is used for the string representation."
@ -412,7 +413,7 @@ class GEOSCoordSeq:
self._z = z self._z = z
def __del__(self): def __del__(self):
lgeos.GEOSCoordSeq_destroy(self._cs) if self._cs: lgeos.GEOSCoordSeq_destroy(self._cs)
def __iter__(self): def __iter__(self):
for i in xrange(self.size): for i in xrange(self.size):
@ -487,7 +488,7 @@ class GEOSCoordSeq:
dim = c_uint(dimension) dim = c_uint(dimension)
idx = c_uint(index) idx = c_uint(index)
# 'd' is the value of the point # 'd' is the value of the point, passed in by reference
d = c_double() d = c_double()
status = lgeos.GEOSCoordSeq_getOrdinate(self._cs, idx, dim, byref(d)) status = lgeos.GEOSCoordSeq_getOrdinate(self._cs, idx, dim, byref(d))
if status == 0: if status == 0:

File diff suppressed because one or more lines are too long

View File

@ -5,18 +5,26 @@ from geometries import *
class GeosTest2(unittest.TestCase): class GeosTest2(unittest.TestCase):
def test010_wkt(self): def test0100_wkt(self):
"Testing WKT output." "Testing WKT output."
for g in wkt_out: for g in wkt_out:
geom = GEOSGeometry(g.wkt) geom = GEOSGeometry(g.wkt)
self.assertEqual(g.ewkt, geom.wkt) self.assertEqual(g.ewkt, geom.wkt)
def test011_hex(self): def test0101_hex(self):
"Testing HEX output." "Testing HEX output."
for g in hex_wkt: for g in hex_wkt:
geom = GEOSGeometry(g.wkt) geom = GEOSGeometry(g.wkt)
self.assertEqual(g.hex, geom.hex) self.assertEqual(g.hex, geom.hex)
def test0102_errors(self):
"Testing the Error handlers."
for err in errors:
if err.hex:
self.assertRaises(GEOSException, GEOSGeometry, err.wkt, 'hex')
else:
self.assertRaises(GEOSException, GEOSGeometry, err.wkt)
def test02_points(self): def test02_points(self):
"Testing Point objects." "Testing Point objects."
prev = GEOSGeometry('POINT(0 0)') prev = GEOSGeometry('POINT(0 0)')