diff --git a/django/contrib/gis/geos/libgeos.py b/django/contrib/gis/geos/libgeos.py index e63d42659b..b8dca115a0 100644 --- a/django/contrib/gis/geos/libgeos.py +++ b/django/contrib/gis/geos/libgeos.py @@ -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 [] diff --git a/django/contrib/gis/geos/prototypes/coordseq.py b/django/contrib/gis/geos/prototypes/coordseq.py index 7a5149eca5..75b375884c 100644 --- a/django/contrib/gis/geos/prototypes/coordseq.py +++ b/django/contrib/gis/geos/prototypes/coordseq.py @@ -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) diff --git a/django/contrib/gis/geos/prototypes/errcheck.py b/django/contrib/gis/geos/prototypes/errcheck.py index eb24ef2ecd..7d5f8422e0 100644 --- a/django/contrib/gis/geos/prototypes/errcheck.py +++ b/django/contrib/gis/geos/prototypes/errcheck.py @@ -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 diff --git a/django/contrib/gis/geos/prototypes/geom.py b/django/contrib/gis/geos/prototypes/geom.py index d90bd32cf2..03761ace97 100644 --- a/django/contrib/gis/geos/prototypes/geom.py +++ b/django/contrib/gis/geos/prototypes/geom.py @@ -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) diff --git a/django/contrib/gis/geos/prototypes/io.py b/django/contrib/gis/geos/prototypes/io.py index 5f0e945d81..97f49c2069 100644 --- a/django/contrib/gis/geos/prototypes/io.py +++ b/django/contrib/gis/geos/prototypes/io.py @@ -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 ### diff --git a/django/contrib/gis/geos/prototypes/misc.py b/django/contrib/gis/geos/prototypes/misc.py index 1f809ebe70..016c8328cb 100644 --- a/django/contrib/gis/geos/prototypes/misc.py +++ b/django/contrib/gis/geos/prototypes/misc.py @@ -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] )