Simplified GEOSFuncFactory.
This commit is contained in:
parent
4ac2ab30f5
commit
ff17ef1ada
|
@ -12,7 +12,7 @@ from ctypes import CDLL, CFUNCTYPE, POINTER, Structure, c_char_p
|
|||
from ctypes.util import find_library
|
||||
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.utils.functional import SimpleLazyObject
|
||||
from django.utils.functional import SimpleLazyObject, cached_property
|
||||
from django.utils.version import get_version_tuple
|
||||
|
||||
logger = logging.getLogger('django.contrib.gis')
|
||||
|
@ -148,14 +148,12 @@ class GEOSFuncFactory:
|
|||
self.argtypes = argtypes
|
||||
self.args = args
|
||||
self.kwargs = kwargs
|
||||
self.func = None
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
if self.func is None:
|
||||
self.func = self.get_func(*self.args, **self.kwargs)
|
||||
return self.func(*args, **kwargs)
|
||||
|
||||
def get_func(self, *args, **kwargs):
|
||||
@cached_property
|
||||
def func(self):
|
||||
from django.contrib.gis.geos.prototypes.threadsafe import GEOSFunc
|
||||
func = GEOSFunc(self.func_name)
|
||||
func.argtypes = self.argtypes or []
|
||||
|
|
|
@ -34,30 +34,27 @@ class CsOperation(GEOSFuncFactory):
|
|||
"For coordinate sequence operations."
|
||||
restype = c_int
|
||||
|
||||
def get_func(self, ordinate=False, get=False):
|
||||
def __init__(self, *args, ordinate=False, get=False, **kwargs):
|
||||
if get:
|
||||
# Get routines have double parameter passed-in by reference.
|
||||
self.errcheck = check_cs_get
|
||||
errcheck = check_cs_get
|
||||
dbl_param = POINTER(c_double)
|
||||
else:
|
||||
self.errcheck = check_cs_op
|
||||
errcheck = check_cs_op
|
||||
dbl_param = c_double
|
||||
|
||||
if ordinate:
|
||||
# Get/Set ordinate routines have an extra uint parameter.
|
||||
self.argtypes = [CS_PTR, c_uint, c_uint, dbl_param]
|
||||
argtypes = [CS_PTR, c_uint, c_uint, dbl_param]
|
||||
else:
|
||||
self.argtypes = [CS_PTR, c_uint, dbl_param]
|
||||
return super().get_func()
|
||||
argtypes = [CS_PTR, c_uint, dbl_param]
|
||||
|
||||
super().__init__(*args, **dict(kwargs, errcheck=errcheck, argtypes=argtypes))
|
||||
|
||||
|
||||
class CsOutput(GEOSFuncFactory):
|
||||
restype = CS_PTR
|
||||
|
||||
def get_func(self, argtypes):
|
||||
self.argtypes = argtypes
|
||||
return super().get_func()
|
||||
|
||||
@staticmethod
|
||||
def errcheck(result, func, cargs):
|
||||
if not result:
|
||||
|
@ -71,9 +68,9 @@ class CsOutput(GEOSFuncFactory):
|
|||
# ## Coordinate Sequence ctypes prototypes ##
|
||||
|
||||
# Coordinate Sequence constructors & cloning.
|
||||
cs_clone = CsOutput('GEOSCoordSeq_clone', [CS_PTR])
|
||||
create_cs = CsOutput('GEOSCoordSeq_create', [c_uint, c_uint])
|
||||
get_cs = CsOutput('GEOSGeom_getCoordSeq', [GEOM_PTR])
|
||||
cs_clone = CsOutput('GEOSCoordSeq_clone', argtypes=[CS_PTR])
|
||||
create_cs = CsOutput('GEOSCoordSeq_create', argtypes=[c_uint, c_uint])
|
||||
get_cs = CsOutput('GEOSGeom_getCoordSeq', argtypes=[GEOM_PTR])
|
||||
|
||||
# Getting, setting ordinate
|
||||
cs_getordinate = CsOperation('GEOSCoordSeq_getOrdinate', ordinate=True, get=True)
|
||||
|
|
|
@ -81,11 +81,3 @@ def check_string(result, func, cargs):
|
|||
# Freeing the memory allocated within GEOS
|
||||
free(result)
|
||||
return s
|
||||
|
||||
|
||||
def check_zero(result, func, cargs):
|
||||
"Error checking on routines that should not return 0."
|
||||
if result == 0:
|
||||
raise GEOSException('Error encountered in GEOS C function "%s".' % func.__name__)
|
||||
else:
|
||||
return result
|
||||
|
|
|
@ -2,7 +2,7 @@ from ctypes import POINTER, c_char_p, c_int, c_size_t, c_ubyte
|
|||
|
||||
from django.contrib.gis.geos.libgeos import CS_PTR, GEOM_PTR, GEOSFuncFactory
|
||||
from django.contrib.gis.geos.prototypes.errcheck import (
|
||||
check_geom, check_minus_one, check_sized_string, check_string, check_zero,
|
||||
check_geom, check_minus_one, check_sized_string, check_string,
|
||||
)
|
||||
|
||||
# This is the return type used by binary output (WKB, HEX) routines.
|
||||
|
@ -41,22 +41,12 @@ class GeomOutput(GEOSFuncFactory):
|
|||
restype = GEOM_PTR
|
||||
errcheck = staticmethod(check_geom)
|
||||
|
||||
def get_func(self, argtypes):
|
||||
self.argtypes = argtypes
|
||||
return super().get_func()
|
||||
|
||||
|
||||
class IntFromGeom(GEOSFuncFactory):
|
||||
"Argument is a geometry, return type is an integer."
|
||||
argtypes = [GEOM_PTR]
|
||||
restype = c_int
|
||||
|
||||
def get_func(self, zero=False):
|
||||
if zero:
|
||||
self.errcheck = check_zero
|
||||
else:
|
||||
self.errcheck = check_minus_one
|
||||
return super().get_func()
|
||||
errcheck = staticmethod(check_minus_one)
|
||||
|
||||
|
||||
class StringFromGeom(GEOSFuncFactory):
|
||||
|
@ -77,23 +67,23 @@ get_num_coords = IntFromGeom('GEOSGetNumCoordinates')
|
|||
get_num_geoms = IntFromGeom('GEOSGetNumGeometries')
|
||||
|
||||
# Geometry creation factories
|
||||
create_point = GeomOutput('GEOSGeom_createPoint', [CS_PTR])
|
||||
create_linestring = GeomOutput('GEOSGeom_createLineString', [CS_PTR])
|
||||
create_linearring = GeomOutput('GEOSGeom_createLinearRing', [CS_PTR])
|
||||
create_point = GeomOutput('GEOSGeom_createPoint', argtypes=[CS_PTR])
|
||||
create_linestring = GeomOutput('GEOSGeom_createLineString', argtypes=[CS_PTR])
|
||||
create_linearring = GeomOutput('GEOSGeom_createLinearRing', argtypes=[CS_PTR])
|
||||
|
||||
# Polygon and collection creation routines are special and will not
|
||||
# have their argument types defined.
|
||||
create_polygon = GeomOutput('GEOSGeom_createPolygon', None)
|
||||
create_empty_polygon = GeomOutput('GEOSGeom_createEmptyPolygon', None)
|
||||
create_collection = GeomOutput('GEOSGeom_createCollection', None)
|
||||
create_polygon = GeomOutput('GEOSGeom_createPolygon')
|
||||
create_empty_polygon = GeomOutput('GEOSGeom_createEmptyPolygon')
|
||||
create_collection = GeomOutput('GEOSGeom_createCollection')
|
||||
|
||||
# Ring routines
|
||||
get_extring = GeomOutput('GEOSGetExteriorRing', [GEOM_PTR])
|
||||
get_intring = GeomOutput('GEOSGetInteriorRingN', [GEOM_PTR, c_int])
|
||||
get_extring = GeomOutput('GEOSGetExteriorRing', argtypes=[GEOM_PTR])
|
||||
get_intring = GeomOutput('GEOSGetInteriorRingN', argtypes=[GEOM_PTR, c_int])
|
||||
get_nrings = IntFromGeom('GEOSGetNumInteriorRings')
|
||||
|
||||
# Collection Routines
|
||||
get_geomn = GeomOutput('GEOSGetGeometryN', [GEOM_PTR, c_int])
|
||||
get_geomn = GeomOutput('GEOSGetGeometryN', argtypes=[GEOM_PTR, c_int])
|
||||
|
||||
# Cloning
|
||||
geom_clone = GEOSFuncFactory('GEOSGeom_clone', argtypes=[GEOM_PTR], restype=GEOM_PTR)
|
||||
|
|
|
@ -118,9 +118,7 @@ class IOBase(GEOSBase):
|
|||
self.ptr = self._constructor()
|
||||
# Loading the real destructor function at this point as doing it in
|
||||
# __del__ is too late (import error).
|
||||
self.destructor.func = self.destructor.get_func(
|
||||
*self.destructor.args, **self.destructor.kwargs
|
||||
)
|
||||
self.destructor.func
|
||||
|
||||
# ### Base WKB/WKT Reading and Writing objects ###
|
||||
|
||||
|
|
|
@ -19,19 +19,13 @@ class DblFromGeom(GEOSFuncFactory):
|
|||
restype = c_int # Status code returned
|
||||
errcheck = staticmethod(check_dbl)
|
||||
|
||||
def get_func(self, num_geom=1):
|
||||
argtypes = [GEOM_PTR for i in range(num_geom)]
|
||||
argtypes += [POINTER(c_double)]
|
||||
self.argtypes = argtypes
|
||||
return super().get_func()
|
||||
|
||||
|
||||
# ### ctypes prototypes ###
|
||||
|
||||
# Area, distance, and length prototypes.
|
||||
geos_area = DblFromGeom('GEOSArea')
|
||||
geos_distance = DblFromGeom('GEOSDistance', num_geom=2)
|
||||
geos_length = DblFromGeom('GEOSLength')
|
||||
geos_area = DblFromGeom('GEOSArea', argtypes=[GEOM_PTR, POINTER(c_double)])
|
||||
geos_distance = DblFromGeom('GEOSDistance', argtypes=[GEOM_PTR, GEOM_PTR, POINTER(c_double)])
|
||||
geos_length = DblFromGeom('GEOSLength', argtypes=[GEOM_PTR, POINTER(c_double)])
|
||||
geos_isvalidreason = GEOSFuncFactory(
|
||||
'GEOSisValidReason', restype=geos_char_p, errcheck=check_string, argtypes=[GEOM_PTR]
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue