Ticket #10923: geos_threadsafe_v2.diff
File geos_threadsafe_v2.diff, 40.0 KB (added by , 15 years ago) |
---|
-
django/contrib/gis/geos/geometry.py
21 21 # the underlying GEOS library. 22 22 from django.contrib.gis.geos import prototypes as capi 23 23 24 # These functions provide access to a thread-local instance 25 # of their corresponding GEOS I/O class. 26 from django.contrib.gis.geos.prototypes.io import wkt_r, wkt_w, wkb_r, wkb_w, ewkb_w, ewkb_w3d 27 24 28 # Regular expression for recognizing HEXEWKB and WKT. A prophylactic measure 25 29 # to prevent potentially malicious input from reaching the underlying C 26 30 # library. Not a substitute for good web security programming practices. … … 61 65 if wkt_m: 62 66 # Handling WKT input. 63 67 if wkt_m.group('srid'): srid = int(wkt_m.group('srid')) 64 g = wkt_r .read(wkt_m.group('wkt'))68 g = wkt_r().read(wkt_m.group('wkt')) 65 69 elif hex_regex.match(geo_input): 66 70 # Handling HEXEWKB input. 67 g = wkb_r .read(geo_input)71 g = wkb_r().read(geo_input) 68 72 elif gdal.GEOJSON and gdal.geometries.json_regex.match(geo_input): 69 73 # Handling GeoJSON input. 70 g = wkb_r .read(gdal.OGRGeometry(geo_input).wkb)74 g = wkb_r().read(gdal.OGRGeometry(geo_input).wkb) 71 75 else: 72 76 raise ValueError('String or unicode input unrecognized as WKT EWKT, and HEXEWKB.') 73 77 elif isinstance(geo_input, GEOM_PTR): … … 75 79 g = geo_input 76 80 elif isinstance(geo_input, buffer): 77 81 # When the input is a buffer (WKB). 78 g = wkb_r .read(geo_input)82 g = wkb_r().read(geo_input) 79 83 elif isinstance(geo_input, GEOSGeometry): 80 84 g = capi.geom_clone(geo_input.ptr) 81 85 else: … … 368 372 @property 369 373 def wkt(self): 370 374 "Returns the WKT (Well-Known Text) representation of this Geometry." 371 return wkt_w .write(self)375 return wkt_w().write(self) 372 376 373 377 @property 374 378 def hex(self): … … 380 384 """ 381 385 # A possible faster, all-python, implementation: 382 386 # str(self.wkb).encode('hex') 383 return wkb_w .write_hex(self)387 return wkb_w().write_hex(self) 384 388 385 389 @property 386 390 def hexewkb(self): … … 393 397 if not GEOS_PREPARE: 394 398 # See: http://trac.osgeo.org/geos/ticket/216 395 399 raise GEOSException('Upgrade GEOS to 3.1 to get valid 3D HEXEWKB.') 396 return ewkb_w3d .write_hex(self)400 return ewkb_w3d().write_hex(self) 397 401 else: 398 return ewkb_w .write_hex(self)402 return ewkb_w().write_hex(self) 399 403 400 404 @property 401 405 def json(self): … … 416 420 as a Python buffer. SRID and Z values are not included, use the 417 421 `ewkb` property instead. 418 422 """ 419 return wkb_w .write(self)423 return wkb_w().write(self) 420 424 421 425 @property 422 426 def ewkb(self): … … 429 433 if not GEOS_PREPARE: 430 434 # See: http://trac.osgeo.org/geos/ticket/216 431 435 raise GEOSException('Upgrade GEOS to 3.1 to get valid 3D EWKB.') 432 return ewkb_w3d .write(self)436 return ewkb_w3d().write(self) 433 437 else: 434 return ewkb_w .write(self)438 return ewkb_w().write(self) 435 439 436 440 @property 437 441 def kml(self): … … 493 497 g = gdal.OGRGeometry(self.wkb, srid) 494 498 g.transform(ct) 495 499 # Getting a new GEOS pointer 496 ptr = wkb_r .read(g.wkb)500 ptr = wkb_r().read(g.wkb) 497 501 if clone: 498 502 # User wants a cloned transformed geometry returned. 499 503 return GEOSGeometry(ptr, srid=g.srid) … … 655 659 7 : GeometryCollection, 656 660 } 657 661 658 # Similarly, import the GEOS I/O instances here to avoid conflicts.659 from django.contrib.gis.geos.io import wkt_r, wkt_w, wkb_r, wkb_w, ewkb_w, ewkb_w3d660 661 662 # If supported, import the PreparedGeometry class. 662 663 if GEOS_PREPARE: 663 664 from django.contrib.gis.geos.prepared import PreparedGeometry -
django/contrib/gis/geos/prototypes/misc.py
3 3 ones that return the area, distance, and length. 4 4 """ 5 5 from ctypes import c_int, c_double, POINTER 6 from django.contrib.gis.geos.libgeos import lgeos,GEOM_PTR6 from django.contrib.gis.geos.libgeos import GEOM_PTR 7 7 from django.contrib.gis.geos.prototypes.errcheck import check_dbl 8 from django.contrib.gis.geos.prototypes.threadsafe import GEOSFunc 8 9 9 10 ### ctypes generator function ### 10 11 def dbl_from_geom(func, num_geom=1): … … 22 23 ### ctypes prototypes ### 23 24 24 25 # Area, distance, and length prototypes. 25 geos_area = dbl_from_geom( lgeos.GEOSArea)26 geos_distance = dbl_from_geom( lgeos.GEOSDistance, num_geom=2)27 geos_length = dbl_from_geom( lgeos.GEOSLength)26 geos_area = dbl_from_geom(GEOSFunc('GEOSArea')) 27 geos_distance = dbl_from_geom(GEOSFunc('GEOSDistance'), num_geom=2) 28 geos_length = dbl_from_geom(GEOSFunc('GEOSLength')) -
django/contrib/gis/geos/prototypes/topology.py
8 8 'geos_simplify', 'geos_symdifference', 'geos_union', 'geos_relate'] 9 9 10 10 from ctypes import c_char_p, c_double, c_int 11 from django.contrib.gis.geos.libgeos import lgeos,GEOM_PTR, GEOS_PREPARE11 from django.contrib.gis.geos.libgeos import GEOM_PTR, GEOS_PREPARE 12 12 from django.contrib.gis.geos.prototypes.errcheck import check_geom, check_string 13 13 from django.contrib.gis.geos.prototypes.geom import geos_char_p 14 from django.contrib.gis.geos.prototypes.threadsafe import GEOSFunc 14 15 15 16 def topology(func, *args): 16 17 "For GEOS unary topology functions." … … 22 23 return func 23 24 24 25 ### Topology Routines ### 25 geos_boundary = topology( lgeos.GEOSBoundary)26 geos_buffer = topology( lgeos.GEOSBuffer, c_double, c_int)27 geos_centroid = topology( lgeos.GEOSGetCentroid)28 geos_convexhull = topology( lgeos.GEOSConvexHull)29 geos_difference = topology( lgeos.GEOSDifference, GEOM_PTR)30 geos_envelope = topology( lgeos.GEOSEnvelope)31 geos_intersection = topology( lgeos.GEOSIntersection, GEOM_PTR)32 geos_linemerge = topology( lgeos.GEOSLineMerge)33 geos_pointonsurface = topology( lgeos.GEOSPointOnSurface)34 geos_preservesimplify = topology( lgeos.GEOSTopologyPreserveSimplify, c_double)35 geos_simplify = topology( lgeos.GEOSSimplify, c_double)36 geos_symdifference = topology( lgeos.GEOSSymDifference, GEOM_PTR)37 geos_union = topology( lgeos.GEOSUnion, GEOM_PTR)26 geos_boundary = topology(GEOSFunc('GEOSBoundary')) 27 geos_buffer = topology(GEOSFunc('GEOSBuffer'), c_double, c_int) 28 geos_centroid = topology(GEOSFunc('GEOSGetCentroid')) 29 geos_convexhull = topology(GEOSFunc('GEOSConvexHull')) 30 geos_difference = topology(GEOSFunc('GEOSDifference'), GEOM_PTR) 31 geos_envelope = topology(GEOSFunc('GEOSEnvelope')) 32 geos_intersection = topology(GEOSFunc('GEOSIntersection'), GEOM_PTR) 33 geos_linemerge = topology(GEOSFunc('GEOSLineMerge')) 34 geos_pointonsurface = topology(GEOSFunc('GEOSPointOnSurface')) 35 geos_preservesimplify = topology(GEOSFunc('GEOSTopologyPreserveSimplify'), c_double) 36 geos_simplify = topology(GEOSFunc('GEOSSimplify'), c_double) 37 geos_symdifference = topology(GEOSFunc('GEOSSymDifference'), GEOM_PTR) 38 geos_union = topology(GEOSFunc('GEOSUnion'), GEOM_PTR) 38 39 39 40 # GEOSRelate returns a string, not a geometry. 40 geos_relate = lgeos.GEOSRelate41 geos_relate = GEOSFunc('GEOSRelate') 41 42 geos_relate.argtypes = [GEOM_PTR, GEOM_PTR] 42 43 geos_relate.restype = geos_char_p 43 44 geos_relate.errcheck = check_string 44 45 45 46 # Routines only in GEOS 3.1+ 46 47 if GEOS_PREPARE: 47 geos_cascaded_union = lgeos.GEOSUnionCascaded48 geos_cascaded_union = GEOSFunc('GEOSUnionCascaded') 48 49 geos_cascaded_union.argtypes = [GEOM_PTR] 49 50 geos_cascaded_union.restype = GEOM_PTR 50 51 __all__.append('geos_cascaded_union') -
django/contrib/gis/geos/prototypes/coordseq.py
1 1 from ctypes import c_double, c_int, c_uint, POINTER 2 from django.contrib.gis.geos.libgeos import lgeos,GEOM_PTR, CS_PTR2 from django.contrib.gis.geos.libgeos import GEOM_PTR, CS_PTR 3 3 from django.contrib.gis.geos.prototypes.errcheck import last_arg_byref, GEOSException 4 from django.contrib.gis.geos.prototypes.threadsafe import GEOSFunc 4 5 5 6 ## Error-checking routines specific to coordinate sequences. ## 6 7 def check_cs_ptr(result, func, cargs): … … 59 60 ## Coordinate Sequence ctypes prototypes ## 60 61 61 62 # Coordinate Sequence constructors & cloning. 62 cs_clone = cs_output( lgeos.GEOSCoordSeq_clone, [CS_PTR])63 create_cs = cs_output( lgeos.GEOSCoordSeq_create, [c_uint, c_uint])64 get_cs = cs_output( lgeos.GEOSGeom_getCoordSeq, [GEOM_PTR])63 cs_clone = cs_output(GEOSFunc('GEOSCoordSeq_clone'), [CS_PTR]) 64 create_cs = cs_output(GEOSFunc('GEOSCoordSeq_create'), [c_uint, c_uint]) 65 get_cs = cs_output(GEOSFunc('GEOSGeom_getCoordSeq'), [GEOM_PTR]) 65 66 66 67 # Getting, setting ordinate 67 cs_getordinate = cs_operation( lgeos.GEOSCoordSeq_getOrdinate, ordinate=True, get=True)68 cs_setordinate = cs_operation( lgeos.GEOSCoordSeq_setOrdinate, ordinate=True)68 cs_getordinate = cs_operation(GEOSFunc('GEOSCoordSeq_getOrdinate'), ordinate=True, get=True) 69 cs_setordinate = cs_operation(GEOSFunc('GEOSCoordSeq_setOrdinate'), ordinate=True) 69 70 70 71 # For getting, x, y, z 71 cs_getx = cs_operation( lgeos.GEOSCoordSeq_getX, get=True)72 cs_gety = cs_operation( lgeos.GEOSCoordSeq_getY, get=True)73 cs_getz = cs_operation( lgeos.GEOSCoordSeq_getZ, get=True)72 cs_getx = cs_operation(GEOSFunc('GEOSCoordSeq_getX'), get=True) 73 cs_gety = cs_operation(GEOSFunc('GEOSCoordSeq_getY'), get=True) 74 cs_getz = cs_operation(GEOSFunc('GEOSCoordSeq_getZ'), get=True) 74 75 75 76 # For setting, x, y, z 76 cs_setx = cs_operation( lgeos.GEOSCoordSeq_setX)77 cs_sety = cs_operation( lgeos.GEOSCoordSeq_setY)78 cs_setz = cs_operation( lgeos.GEOSCoordSeq_setZ)77 cs_setx = cs_operation(GEOSFunc('GEOSCoordSeq_setX')) 78 cs_sety = cs_operation(GEOSFunc('GEOSCoordSeq_setY')) 79 cs_setz = cs_operation(GEOSFunc('GEOSCoordSeq_setZ')) 79 80 80 81 # These routines return size & dimensions. 81 cs_getsize = cs_int( lgeos.GEOSCoordSeq_getSize)82 cs_getdims = cs_int( lgeos.GEOSCoordSeq_getDimensions)82 cs_getsize = cs_int(GEOSFunc('GEOSCoordSeq_getSize')) 83 cs_getdims = cs_int(GEOSFunc('GEOSCoordSeq_getDimensions')) -
django/contrib/gis/geos/prototypes/prepared.py
1 1 from ctypes import c_char 2 from django.contrib.gis.geos.libgeos import lgeos,GEOM_PTR, PREPGEOM_PTR2 from django.contrib.gis.geos.libgeos import GEOM_PTR, PREPGEOM_PTR 3 3 from django.contrib.gis.geos.prototypes.errcheck import check_predicate 4 from django.contrib.gis.geos.prototypes.threadsafe import GEOSFunc 4 5 5 6 # Prepared geometry constructor and destructors. 6 geos_prepare = lgeos.GEOSPrepare7 geos_prepare = GEOSFunc('GEOSPrepare') 7 8 geos_prepare.argtypes = [GEOM_PTR] 8 9 geos_prepare.restype = PREPGEOM_PTR 9 10 10 prepared_destroy = lgeos.GEOSPreparedGeom_destroy11 prepared_destroy = GEOSFunc('GEOSPreparedGeom_destroy') 11 12 prepared_destroy.argtpes = [PREPGEOM_PTR] 12 13 prepared_destroy.restype = None 13 14 … … 18 19 func.errcheck = check_predicate 19 20 return func 20 21 21 prepared_contains = prepared_predicate( lgeos.GEOSPreparedContains)22 prepared_contains_properly = prepared_predicate( lgeos.GEOSPreparedContainsProperly)23 prepared_covers = prepared_predicate( lgeos.GEOSPreparedCovers)24 prepared_intersects = prepared_predicate( lgeos.GEOSPreparedIntersects)22 prepared_contains = prepared_predicate(GEOSFunc('GEOSPreparedContains')) 23 prepared_contains_properly = prepared_predicate(GEOSFunc('GEOSPreparedContainsProperly')) 24 prepared_covers = prepared_predicate(GEOSFunc('GEOSPreparedCovers')) 25 prepared_intersects = prepared_predicate(GEOSFunc('GEOSPreparedIntersects')) -
django/contrib/gis/geos/prototypes/predicates.py
3 3 unary and binary predicate operations on geometries. 4 4 """ 5 5 from ctypes import c_char, c_char_p, c_double 6 from django.contrib.gis.geos.libgeos import lgeos,GEOM_PTR6 from django.contrib.gis.geos.libgeos import GEOM_PTR 7 7 from django.contrib.gis.geos.prototypes.errcheck import check_predicate 8 from django.contrib.gis.geos.prototypes.threadsafe import GEOSFunc 8 9 9 10 ## Binary & unary predicate functions ## 10 11 def binary_predicate(func, *args): … … 24 25 return func 25 26 26 27 ## Unary Predicates ## 27 geos_hasz = unary_predicate( lgeos.GEOSHasZ)28 geos_isempty = unary_predicate( lgeos.GEOSisEmpty)29 geos_isring = unary_predicate( lgeos.GEOSisRing)30 geos_issimple = unary_predicate( lgeos.GEOSisSimple)31 geos_isvalid = unary_predicate( lgeos.GEOSisValid)28 geos_hasz = unary_predicate(GEOSFunc('GEOSHasZ')) 29 geos_isempty = unary_predicate(GEOSFunc('GEOSisEmpty')) 30 geos_isring = unary_predicate(GEOSFunc('GEOSisRing')) 31 geos_issimple = unary_predicate(GEOSFunc('GEOSisSimple')) 32 geos_isvalid = unary_predicate(GEOSFunc('GEOSisValid')) 32 33 33 34 ## Binary Predicates ## 34 geos_contains = binary_predicate( lgeos.GEOSContains)35 geos_crosses = binary_predicate( lgeos.GEOSCrosses)36 geos_disjoint = binary_predicate( lgeos.GEOSDisjoint)37 geos_equals = binary_predicate( lgeos.GEOSEquals)38 geos_equalsexact = binary_predicate( lgeos.GEOSEqualsExact, c_double)39 geos_intersects = binary_predicate( lgeos.GEOSIntersects)40 geos_overlaps = binary_predicate( lgeos.GEOSOverlaps)41 geos_relatepattern = binary_predicate( lgeos.GEOSRelatePattern, c_char_p)42 geos_touches = binary_predicate( lgeos.GEOSTouches)43 geos_within = binary_predicate( lgeos.GEOSWithin)35 geos_contains = binary_predicate(GEOSFunc('GEOSContains')) 36 geos_crosses = binary_predicate(GEOSFunc('GEOSCrosses')) 37 geos_disjoint = binary_predicate(GEOSFunc('GEOSDisjoint')) 38 geos_equals = binary_predicate(GEOSFunc('GEOSEquals')) 39 geos_equalsexact = binary_predicate(GEOSFunc('GEOSEqualsExact'), c_double) 40 geos_intersects = binary_predicate(GEOSFunc('GEOSIntersects')) 41 geos_overlaps = binary_predicate(GEOSFunc('GEOSOverlaps')) 42 geos_relatepattern = binary_predicate(GEOSFunc('GEOSRelatePattern'), c_char_p) 43 geos_touches = binary_predicate(GEOSFunc('GEOSTouches')) 44 geos_within = binary_predicate(GEOSFunc('GEOSWithin')) -
django/contrib/gis/geos/prototypes/errcheck.py
3 3 """ 4 4 import os 5 5 from ctypes import c_void_p, string_at, CDLL 6 from ctypes.util import find_library 6 7 from django.contrib.gis.geos.error import GEOSException 7 8 from django.contrib.gis.geos.libgeos import lgeos, GEOS_VERSION 9 from django.contrib.gis.geos.prototypes.threadsafe import GEOSFunc 8 10 9 11 # Getting the `free` routine used to free the memory allocated for 10 12 # string pointers returned by GEOS. 11 13 if GEOS_VERSION >= (3, 1, 1): 12 14 # In versions 3.1.1 and above, `GEOSFree` was added to the C API 13 15 # because `free` isn't always available on all platforms. 14 free = lgeos.GEOSFree16 free = GEOSFunc('GEOSFree') 15 17 free.argtypes = [c_void_p] 16 18 free.restype = None 17 19 else: -
django/contrib/gis/geos/prototypes/threadsafe.py
1 import threading 2 from django.contrib.gis.geos.libgeos import lgeos, notice_h, error_h, CONTEXT_PTR 3 4 class GEOSContextHandle(object): 5 """ 6 Python object representing a GEOS context handle. 7 """ 8 def __init__(self): 9 self.ptr = lgeos.initGEOS_r(notice_h, error_h) 10 11 def __del__(self): 12 lgeos.finishGEOS_r(self.ptr) 13 14 # Defining a thread-local object and creating an instance 15 # to hold a reference to GEOSContextHandle for this thread. 16 class GEOSContext(threading.local): 17 handle = None 18 19 thread_context = GEOSContext() 20 21 def call_geos_threaded(cfunc, args): 22 """ 23 This module-level routine calls the specified GEOS C thread-safe 24 function with the context for this current thread. 25 """ 26 if not thread_context.handle: 27 thread_context.handle = GEOSContextHandle() 28 return cfunc(thread_context.handle.ptr, *args) 29 30 class GEOSFunc(object): 31 """ 32 Class that serves as a wrapper for GEOS C Functions, and will 33 use thread-safe function variants when available. 34 """ 35 def __init__(self, func_name): 36 try: 37 # GEOS thread-safe function signatures end with '_r'. 38 self.cfunc = getattr(lgeos, func_name + '_r') 39 self.threaded = True 40 except AttributeError: 41 # Otherwise, use usual function. 42 self.cfunc = getattr(lgeos, func_name) 43 self.threaded = False 44 45 def __call__(self, *args): 46 if self.threaded: 47 return call_geos_threaded(self.cfunc, args) 48 else: 49 return self.cfunc(*args) 50 51 def __str__(self): 52 return self.cfunc.__name__ 53 54 # argtypes property 55 def _get_argtypes(self): 56 return self.cfunc.argtypes 57 58 def _set_argtypes(self, argtypes): 59 if self.threaded: 60 new_argtypes = [CONTEXT_PTR] 61 new_argtypes.extend(argtypes) 62 self.cfunc.argtypes = new_argtypes 63 else: 64 self.cfunc.argtypes = argtypes 65 66 argtypes = property(_get_argtypes, _set_argtypes) 67 68 # restype property 69 def _get_restype(self): 70 return self.cfunc.restype 71 72 def _set_restype(self, restype): 73 self.cfunc.restype = restype 74 75 restype = property(_get_restype, _set_restype) 76 77 # errcheck property 78 def _get_errcheck(self): 79 return self.cfunc.errcheck 80 81 def _set_errcheck(self, errcheck): 82 self.cfunc.errcheck = errcheck 83 84 errcheck = property(_get_errcheck, _set_errcheck) -
django/contrib/gis/geos/prototypes/geom.py
1 1 from ctypes import c_char_p, c_int, c_size_t, c_ubyte, c_uint, POINTER 2 from django.contrib.gis.geos.libgeos import lgeos,CS_PTR, GEOM_PTR, PREPGEOM_PTR, GEOS_PREPARE2 from django.contrib.gis.geos.libgeos import CS_PTR, GEOM_PTR, PREPGEOM_PTR, GEOS_PREPARE 3 3 from django.contrib.gis.geos.prototypes.errcheck import \ 4 4 check_geom, check_minus_one, check_sized_string, check_string, check_zero 5 from django.contrib.gis.geos.prototypes.threadsafe import GEOSFunc 5 6 6 7 # This is the return type used by binary output (WKB, HEX) routines. 7 8 c_uchar_p = POINTER(c_ubyte) … … 62 63 63 64 ### ctypes prototypes ### 64 65 65 # Deprecated creation and outputroutines from WKB, HEX, WKT66 from_hex = bin_constructor( lgeos.GEOSGeomFromHEX_buf)67 from_wkb = bin_constructor( lgeos.GEOSGeomFromWKB_buf)68 from_wkt = geom_output( lgeos.GEOSGeomFromWKT, [c_char_p])66 # Deprecated creation routines from WKB, HEX, WKT 67 from_hex = bin_constructor(GEOSFunc('GEOSGeomFromHEX_buf')) 68 from_wkb = bin_constructor(GEOSFunc('GEOSGeomFromWKB_buf')) 69 from_wkt = geom_output(GEOSFunc('GEOSGeomFromWKT'), [c_char_p]) 69 70 70 to_hex = bin_output(lgeos.GEOSGeomToHEX_buf) 71 to_wkb = bin_output(lgeos.GEOSGeomToWKB_buf) 72 to_wkt = string_from_geom(lgeos.GEOSGeomToWKT) 71 # Deprecated output routines 72 to_hex = bin_output(GEOSFunc('GEOSGeomToHEX_buf')) 73 to_wkb = bin_output(GEOSFunc('GEOSGeomToWKB_buf')) 74 to_wkt = string_from_geom(GEOSFunc('GEOSGeomToWKT')) 73 75 74 # The GEOS geometry type, typeid, num_coordi nates and number of geometries75 geos_normalize = int_from_geom( lgeos.GEOSNormalize)76 geos_type = string_from_geom( lgeos.GEOSGeomType)77 geos_typeid = int_from_geom( lgeos.GEOSGeomTypeId)78 get_dims = int_from_geom( lgeos.GEOSGeom_getDimensions, zero=True)79 get_num_coords = int_from_geom( lgeos.GEOSGetNumCoordinates)80 get_num_geoms = int_from_geom( lgeos.GEOSGetNumGeometries)76 # The GEOS geometry type, typeid, num_coordites and number of geometries 77 geos_normalize = int_from_geom(GEOSFunc('GEOSNormalize')) 78 geos_type = string_from_geom(GEOSFunc('GEOSGeomType')) 79 geos_typeid = int_from_geom(GEOSFunc('GEOSGeomTypeId')) 80 get_dims = int_from_geom(GEOSFunc('GEOSGeom_getDimensions'), zero=True) 81 get_num_coords = int_from_geom(GEOSFunc('GEOSGetNumCoordinates')) 82 get_num_geoms = int_from_geom(GEOSFunc('GEOSGetNumGeometries')) 81 83 82 84 # Geometry creation factories 83 create_point = geom_output( lgeos.GEOSGeom_createPoint, [CS_PTR])84 create_linestring = geom_output( lgeos.GEOSGeom_createLineString, [CS_PTR])85 create_linearring = geom_output( lgeos.GEOSGeom_createLinearRing, [CS_PTR])85 create_point = geom_output(GEOSFunc('GEOSGeom_createPoint'), [CS_PTR]) 86 create_linestring = geom_output(GEOSFunc('GEOSGeom_createLineString'), [CS_PTR]) 87 create_linearring = geom_output(GEOSFunc('GEOSGeom_createLinearRing'), [CS_PTR]) 86 88 87 89 # Polygon and collection creation routines are special and will not 88 90 # have their argument types defined. 89 create_polygon = geom_output( lgeos.GEOSGeom_createPolygon, None)90 create_collection = geom_output( lgeos.GEOSGeom_createCollection, None)91 create_polygon = geom_output(GEOSFunc('GEOSGeom_createPolygon'), None) 92 create_collection = geom_output(GEOSFunc('GEOSGeom_createCollection'), None) 91 93 92 94 # Ring routines 93 get_extring = geom_output( lgeos.GEOSGetExteriorRing, [GEOM_PTR])94 get_intring = geom_index( lgeos.GEOSGetInteriorRingN)95 get_nrings = int_from_geom( lgeos.GEOSGetNumInteriorRings)95 get_extring = geom_output(GEOSFunc('GEOSGetExteriorRing'), [GEOM_PTR]) 96 get_intring = geom_index(GEOSFunc('GEOSGetInteriorRingN')) 97 get_nrings = int_from_geom(GEOSFunc('GEOSGetNumInteriorRings')) 96 98 97 99 # Collection Routines 98 get_geomn = geom_index( lgeos.GEOSGetGeometryN)100 get_geomn = geom_index(GEOSFunc('GEOSGetGeometryN')) 99 101 100 102 # Cloning 101 geom_clone = lgeos.GEOSGeom_clone103 geom_clone = GEOSFunc('GEOSGeom_clone') 102 104 geom_clone.argtypes = [GEOM_PTR] 103 105 geom_clone.restype = GEOM_PTR 104 106 105 107 # Destruction routine. 106 destroy_geom = lgeos.GEOSGeom_destroy108 destroy_geom = GEOSFunc('GEOSGeom_destroy') 107 109 destroy_geom.argtypes = [GEOM_PTR] 108 110 destroy_geom.restype = None 109 111 110 112 # SRID routines 111 geos_get_srid = lgeos.GEOSGetSRID113 geos_get_srid = GEOSFunc('GEOSGetSRID') 112 114 geos_get_srid.argtypes = [GEOM_PTR] 113 115 geos_get_srid.restype = c_int 114 116 115 geos_set_srid = lgeos.GEOSSetSRID117 geos_set_srid = GEOSFunc('GEOSSetSRID') 116 118 geos_set_srid.argtypes = [GEOM_PTR, c_int] 117 119 geos_set_srid.restype = None -
django/contrib/gis/geos/prototypes/io.py
1 from ctypes import c_char_p, c_int, c_char, c_size_t, Structure, POINTER 2 from django.contrib.gis.geos.libgeos import lgeos, GEOM_PTR 1 import threading 2 from ctypes import byref, c_char_p, c_int, c_char, c_size_t, Structure, POINTER 3 from django.contrib.gis.geos.base import GEOSBase 4 from django.contrib.gis.geos.libgeos import GEOM_PTR 3 5 from django.contrib.gis.geos.prototypes.errcheck import check_geom, check_string, check_sized_string 4 6 from django.contrib.gis.geos.prototypes.geom import c_uchar_p, geos_char_p 7 from django.contrib.gis.geos.prototypes.threadsafe import GEOSFunc 5 8 6 9 ### The WKB/WKT Reader/Writer structures and pointers ### 7 10 class WKTReader_st(Structure): pass … … 15 18 WKB_WRITE_PTR = POINTER(WKBReader_st) 16 19 17 20 ### WKTReader routines ### 18 wkt_reader_create = lgeos.GEOSWKTReader_create21 wkt_reader_create = GEOSFunc('GEOSWKTReader_create') 19 22 wkt_reader_create.restype = WKT_READ_PTR 20 23 21 wkt_reader_destroy = lgeos.GEOSWKTReader_destroy24 wkt_reader_destroy = GEOSFunc('GEOSWKTReader_destroy') 22 25 wkt_reader_destroy.argtypes = [WKT_READ_PTR] 23 26 24 wkt_reader_read = lgeos.GEOSWKTReader_read27 wkt_reader_read = GEOSFunc('GEOSWKTReader_read') 25 28 wkt_reader_read.argtypes = [WKT_READ_PTR, c_char_p] 26 29 wkt_reader_read.restype = GEOM_PTR 27 30 wkt_reader_read.errcheck = check_geom 28 31 29 32 ### WKTWriter routines ### 30 wkt_writer_create = lgeos.GEOSWKTWriter_create33 wkt_writer_create = GEOSFunc('GEOSWKTWriter_create') 31 34 wkt_writer_create.restype = WKT_WRITE_PTR 32 35 33 wkt_writer_destroy = lgeos.GEOSWKTWriter_destroy36 wkt_writer_destroy = GEOSFunc('GEOSWKTWriter_destroy') 34 37 wkt_writer_destroy.argtypes = [WKT_WRITE_PTR] 35 38 36 wkt_writer_write = lgeos.GEOSWKTWriter_write39 wkt_writer_write = GEOSFunc('GEOSWKTWriter_write') 37 40 wkt_writer_write.argtypes = [WKT_WRITE_PTR, GEOM_PTR] 38 41 wkt_writer_write.restype = geos_char_p 39 42 wkt_writer_write.errcheck = check_string 40 43 41 44 ### WKBReader routines ### 42 wkb_reader_create = lgeos.GEOSWKBReader_create45 wkb_reader_create = GEOSFunc('GEOSWKBReader_create') 43 46 wkb_reader_create.restype = WKB_READ_PTR 44 47 45 wkb_reader_destroy = lgeos.GEOSWKBReader_destroy48 wkb_reader_destroy = GEOSFunc('GEOSWKBReader_destroy') 46 49 wkb_reader_destroy.argtypes = [WKB_READ_PTR] 47 50 48 51 def wkb_read_func(func): … … 56 59 func.errcheck = check_geom 57 60 return func 58 61 59 wkb_reader_read = wkb_read_func( lgeos.GEOSWKBReader_read)60 wkb_reader_read_hex = wkb_read_func( lgeos.GEOSWKBReader_readHEX)62 wkb_reader_read = wkb_read_func(GEOSFunc('GEOSWKBReader_read')) 63 wkb_reader_read_hex = wkb_read_func(GEOSFunc('GEOSWKBReader_readHEX')) 61 64 62 65 ### WKBWriter routines ### 63 wkb_writer_create = lgeos.GEOSWKBWriter_create66 wkb_writer_create = GEOSFunc('GEOSWKBWriter_create') 64 67 wkb_writer_create.restype = WKB_WRITE_PTR 65 68 66 wkb_writer_destroy = lgeos.GEOSWKBWriter_destroy69 wkb_writer_destroy = GEOSFunc('GEOSWKBWriter_destroy') 67 70 wkb_writer_destroy.argtypes = [WKB_WRITE_PTR] 68 71 69 72 # WKB Writing prototypes. … … 73 76 func.errcheck = check_sized_string 74 77 return func 75 78 76 wkb_writer_write = wkb_write_func( lgeos.GEOSWKBWriter_write)77 wkb_writer_write_hex = wkb_write_func( lgeos.GEOSWKBWriter_writeHEX)79 wkb_writer_write = wkb_write_func(GEOSFunc('GEOSWKBWriter_write')) 80 wkb_writer_write_hex = wkb_write_func(GEOSFunc('GEOSWKBWriter_writeHEX')) 78 81 79 82 # WKBWriter property getter/setter prototypes. 80 83 def wkb_writer_get(func, restype=c_int): … … 86 89 func.argtypes = [WKB_WRITE_PTR, argtype] 87 90 return func 88 91 89 wkb_writer_get_byteorder = wkb_writer_get(lgeos.GEOSWKBWriter_getByteOrder) 90 wkb_writer_set_byteorder = wkb_writer_set(lgeos.GEOSWKBWriter_setByteOrder) 91 wkb_writer_get_outdim = wkb_writer_get(lgeos.GEOSWKBWriter_getOutputDimension) 92 wkb_writer_set_outdim = wkb_writer_set(lgeos.GEOSWKBWriter_setOutputDimension) 93 wkb_writer_get_include_srid = wkb_writer_get(lgeos.GEOSWKBWriter_getIncludeSRID, restype=c_char) 94 wkb_writer_set_include_srid = wkb_writer_set(lgeos.GEOSWKBWriter_setIncludeSRID, argtype=c_char) 92 wkb_writer_get_byteorder = wkb_writer_get(GEOSFunc('GEOSWKBWriter_getByteOrder')) 93 wkb_writer_set_byteorder = wkb_writer_set(GEOSFunc('GEOSWKBWriter_setByteOrder')) 94 wkb_writer_get_outdim = wkb_writer_get(GEOSFunc('GEOSWKBWriter_getOutputDimension')) 95 wkb_writer_set_outdim = wkb_writer_set(GEOSFunc('GEOSWKBWriter_setOutputDimension')) 96 wkb_writer_get_include_srid = wkb_writer_get(GEOSFunc('GEOSWKBWriter_getIncludeSRID'), restype=c_char) 97 wkb_writer_set_include_srid = wkb_writer_set(GEOSFunc('GEOSWKBWriter_setIncludeSRID'), argtype=c_char) 98 99 ### Base I/O Class ### 100 class IOBase(GEOSBase): 101 "Base class for GEOS I/O objects." 102 def __init__(self): 103 # Getting the pointer with the constructor. 104 self.ptr = self._constructor() 105 106 def __del__(self): 107 # Cleaning up with the appropriate destructor. 108 if self._ptr: self._destructor(self._ptr) 109 110 ### WKB/WKT Reading and Writing objects ### 111 112 # Non-public WKB/WKT reader classes for internal use because 113 # their `read` methods return _pointers_ instead of GEOSGeometry 114 # objects. 115 class _WKTReader(IOBase): 116 _constructor = wkt_reader_create 117 _destructor = wkt_reader_destroy 118 ptr_type = WKT_READ_PTR 119 120 def read(self, wkt): 121 if not isinstance(wkt, basestring): raise TypeError 122 return wkt_reader_read(self.ptr, wkt) 123 124 class _WKBReader(IOBase): 125 _constructor = wkb_reader_create 126 _destructor = wkb_reader_destroy 127 ptr_type = WKB_READ_PTR 128 129 def read(self, wkb): 130 "Returns a _pointer_ to C GEOS Geometry object from the given WKB." 131 if isinstance(wkb, buffer): 132 wkb_s = str(wkb) 133 return wkb_reader_read(self.ptr, wkb_s, len(wkb_s)) 134 elif isinstance(wkb, basestring): 135 return wkb_reader_read_hex(self.ptr, wkb, len(wkb)) 136 else: 137 raise TypeError 138 139 ### WKB/WKT Writer Classes ### 140 class WKTWriter(IOBase): 141 _constructor = wkt_writer_create 142 _destructor = wkt_writer_destroy 143 ptr_type = WKT_WRITE_PTR 144 145 def write(self, geom): 146 "Returns the WKT representation of the given geometry." 147 return wkt_writer_write(self.ptr, geom.ptr) 148 149 class WKBWriter(IOBase): 150 _constructor = wkb_writer_create 151 _destructor = wkb_writer_destroy 152 ptr_type = WKB_WRITE_PTR 153 154 def write(self, geom): 155 "Returns the WKB representation of the given geometry." 156 return buffer(wkb_writer_write(self.ptr, geom.ptr, byref(c_size_t()))) 157 158 def write_hex(self, geom): 159 "Returns the HEXEWKB representation of the given geometry." 160 return wkb_writer_write_hex(self.ptr, geom.ptr, byref(c_size_t())) 161 162 ### WKBWriter Properties ### 163 164 # Property for getting/setting the byteorder. 165 def _get_byteorder(self): 166 return wkb_writer_get_byteorder(self.ptr) 167 168 def _set_byteorder(self, order): 169 if not order in (0, 1): raise ValueError('Byte order parameter must be 0 (Big Endian) or 1 (Little Endian).') 170 wkb_writer_set_byteorder(self.ptr, order) 171 172 byteorder = property(_get_byteorder, _set_byteorder) 173 174 # Property for getting/setting the output dimension. 175 def _get_outdim(self): 176 return wkb_writer_get_outdim(self.ptr) 177 178 def _set_outdim(self, new_dim): 179 if not new_dim in (2, 3): raise ValueError('WKB output dimension must be 2 or 3') 180 wkb_writer_set_outdim(self.ptr, new_dim) 181 182 outdim = property(_get_outdim, _set_outdim) 183 184 # Property for getting/setting the include srid flag. 185 def _get_include_srid(self): 186 return bool(ord(wkb_writer_get_include_srid(self.ptr))) 187 188 def _set_include_srid(self, include): 189 if bool(include): flag = chr(1) 190 else: flag = chr(0) 191 wkb_writer_set_include_srid(self.ptr, flag) 192 193 srid = property(_get_include_srid, _set_include_srid) 194 195 # Thread-local instances of the WKT and WKB reader/writer objects, 196 # accessed by calling module-level function, defined below. 197 class ThreadLocalIO(threading.local): 198 wkt_r = None 199 wkt_w = None 200 wkb_r = None 201 wkb_w = None 202 ewkb_w = None 203 ewkb_w3d = None 204 205 thread_context = ThreadLocalIO() 206 207 def wkt_r(): 208 if not thread_context.wkt_r: 209 thread_context.wkt_r = _WKTReader() 210 return thread_context.wkt_r 211 212 def wkt_w(): 213 if not thread_context.wkt_w: 214 thread_context.wkt_w = WKTWriter() 215 return thread_context.wkt_w 216 217 def wkb_r(): 218 if not thread_context.wkb_r: 219 thread_context.wkb_r = _WKBReader() 220 return thread_context.wkb_r 221 222 def wkb_w(): 223 if not thread_context.wkb_w: 224 thread_context.wkb_w = WKBWriter() 225 return thread_context.wkb_w 226 227 def ewkb_w(): 228 if not thread_context.ewkb_w: 229 thread_context.ewkb_w = WKBWriter() 230 thread_context.ewkb_w.srid = True 231 return thread_context.ewkb_w 232 233 def ewkb_w3d(): 234 if not thread_context.ewkb_w3d: 235 thread_context.ewkb_w3d = WKBWriter() 236 thread_context.ewkb_w3d.srid = True 237 thread_context.ewkb_w3d.outdim = 3 238 return thread_context.ewkb_w3d -
django/contrib/gis/geos/io.py
3 3 objects. Specifically, this has Python implementations of WKB/WKT 4 4 reader and writer classes. 5 5 """ 6 from ctypes import byref, c_size_t7 from django.contrib.gis.geos.base import GEOSBase8 from django.contrib.gis.geos.error import GEOSException9 6 from django.contrib.gis.geos.geometry import GEOSGeometry 10 from django.contrib.gis.geos.libgeos import GEOM_PTR 11 from django.contrib.gis.geos.prototypes import io as capi 7 from django.contrib.gis.geos.prototypes.io import _WKTReader, _WKBReader, WKBWriter, WKTWriter 12 8 13 class IOBase(GEOSBase): 14 "Base class for GEOS I/O objects." 15 def __init__(self):16 # Getting the pointer with the constructor.17 self.ptr = self._constructor()9 # Public classes for (WKB|WKT)Reader, which return GEOSGeometry 10 class WKBReader(_WKBReader): 11 def read(self, wkb): 12 "Returns a GEOSGeometry for the given WKB buffer." 13 return GEOSGeometry(super(WKBReader, self).read(wkb)) 18 14 19 def __del__(self):20 # Cleaning up with the appropriate destructor.21 if self._ptr: self._destructor(self._ptr)22 23 ### WKT Reading and Writing objects ###24 25 # Non-public class for internal use because its `read` method returns26 # _pointers_ instead of a GEOSGeometry object.27 class _WKTReader(IOBase):28 _constructor = capi.wkt_reader_create29 _destructor = capi.wkt_reader_destroy30 ptr_type = capi.WKT_READ_PTR31 32 def read(self, wkt):33 if not isinstance(wkt, basestring): raise TypeError34 return capi.wkt_reader_read(self.ptr, wkt)35 36 15 class WKTReader(_WKTReader): 37 16 def read(self, wkt): 38 17 "Returns a GEOSGeometry for the given WKT string." 39 18 return GEOSGeometry(super(WKTReader, self).read(wkt)) 40 19 41 class WKTWriter(IOBase):42 _constructor = capi.wkt_writer_create43 _destructor = capi.wkt_writer_destroy44 ptr_type = capi.WKT_WRITE_PTR45 20 46 def write(self, geom):47 "Returns the WKT representation of the given geometry."48 return capi.wkt_writer_write(self.ptr, geom.ptr)49 50 ### WKB Reading and Writing objects ###51 52 # Non-public class for the same reason as _WKTReader above.53 class _WKBReader(IOBase):54 _constructor = capi.wkb_reader_create55 _destructor = capi.wkb_reader_destroy56 ptr_type = capi.WKB_READ_PTR57 58 def read(self, wkb):59 "Returns a _pointer_ to C GEOS Geometry object from the given WKB."60 if isinstance(wkb, buffer):61 wkb_s = str(wkb)62 return capi.wkb_reader_read(self.ptr, wkb_s, len(wkb_s))63 elif isinstance(wkb, basestring):64 return capi.wkb_reader_read_hex(self.ptr, wkb, len(wkb))65 else:66 raise TypeError67 68 class WKBReader(_WKBReader):69 def read(self, wkb):70 "Returns a GEOSGeometry for the given WKB buffer."71 return GEOSGeometry(super(WKBReader, self).read(wkb))72 73 class WKBWriter(IOBase):74 _constructor = capi.wkb_writer_create75 _destructor = capi.wkb_writer_destroy76 ptr_type = capi.WKB_WRITE_PTR77 78 def write(self, geom):79 "Returns the WKB representation of the given geometry."80 return buffer(capi.wkb_writer_write(self.ptr, geom.ptr, byref(c_size_t())))81 82 def write_hex(self, geom):83 "Returns the HEXEWKB representation of the given geometry."84 return capi.wkb_writer_write_hex(self.ptr, geom.ptr, byref(c_size_t()))85 86 ### WKBWriter Properties ###87 88 # Property for getting/setting the byteorder.89 def _get_byteorder(self):90 return capi.wkb_writer_get_byteorder(self.ptr)91 92 def _set_byteorder(self, order):93 if not order in (0, 1): raise ValueError('Byte order parameter must be 0 (Big Endian) or 1 (Little Endian).')94 capi.wkb_writer_set_byteorder(self.ptr, order)95 96 byteorder = property(_get_byteorder, _set_byteorder)97 98 # Property for getting/setting the output dimension.99 def _get_outdim(self):100 return capi.wkb_writer_get_outdim(self.ptr)101 102 def _set_outdim(self, new_dim):103 if not new_dim in (2, 3): raise ValueError('WKB output dimension must be 2 or 3')104 capi.wkb_writer_set_outdim(self.ptr, new_dim)105 106 outdim = property(_get_outdim, _set_outdim)107 108 # Property for getting/setting the include srid flag.109 def _get_include_srid(self):110 return bool(ord(capi.wkb_writer_get_include_srid(self.ptr)))111 112 def _set_include_srid(self, include):113 if bool(include): flag = chr(1)114 else: flag = chr(0)115 capi.wkb_writer_set_include_srid(self.ptr, flag)116 117 srid = property(_get_include_srid, _set_include_srid)118 119 # Instances of the WKT and WKB reader/writer objects.120 wkt_r = _WKTReader()121 wkt_w = WKTWriter()122 wkb_r = _WKBReader()123 wkb_w = WKBWriter()124 125 # These instances are for writing EWKB in 2D and 3D.126 ewkb_w = WKBWriter()127 ewkb_w.srid = True128 ewkb_w3d = WKBWriter()129 ewkb_w3d.srid = True130 ewkb_w3d.outdim = 3 -
django/contrib/gis/geos/libgeos.py
45 45 '", "'.join(lib_names)) 46 46 47 47 # Getting the GEOS C library. The C interface (CDLL) is used for 48 # 48 # both *NIX and Windows. 49 49 # See the GEOS C API source code for more details on the library function calls: 50 50 # http://geos.refractions.net/ro/doxygen_docs/html/geos__c_8h-source.html 51 51 lgeos = CDLL(lib_path) 52 52 53 53 # The notice and error handler C function callback definitions. 54 # 55 # "typedef void (*GEOSMessageHandler)(const char *fmt, ...);"54 # Supposed to mimic the GEOS message handler (C below): 55 # typedef void (*GEOSMessageHandler)(const char *fmt, ...); 56 56 NOTICEFUNC = CFUNCTYPE(None, c_char_p, c_char_p) 57 57 def notice_h(fmt, lst, output_h=sys.stdout): 58 58 try: … … 71 71 output_h.write('GEOS_ERROR: %s\n' % err_msg) 72 72 error_h = ERRORFUNC(error_h) 73 73 74 # The initGEOS routine should be called first, however, that routine takes75 # the notice and error functions as parameters. Here is the C code that76 # is wrapped:77 # "extern void GEOS_DLL initGEOS(GEOSMessageHandler notice_function, GEOSMessageHandler error_function);"78 lgeos.initGEOS(notice_h, error_h)79 80 74 #### GEOS Geometry C data structures, and utility functions. #### 81 75 82 76 # Opaque GEOS geometry structures, used for GEOM_PTR and CS_PTR 83 77 class GEOSGeom_t(Structure): pass 84 78 class GEOSPrepGeom_t(Structure): pass 85 79 class GEOSCoordSeq_t(Structure): pass 80 class GEOSContextHandle_t(Structure): pass 86 81 87 82 # Pointers to opaque GEOS geometry structures. 88 83 GEOM_PTR = POINTER(GEOSGeom_t) 89 84 PREPGEOM_PTR = POINTER(GEOSPrepGeom_t) 90 85 CS_PTR = POINTER(GEOSCoordSeq_t) 86 CONTEXT_PTR = POINTER(GEOSContextHandle_t) 91 87 92 88 # Used specifically by the GEOSGeom_createPolygon and GEOSGeom_createCollection 93 89 # GEOS routines … … 126 122 GEOS_VERSION = (GEOS_MAJOR_VERSION, GEOS_MINOR_VERSION, GEOS_SUBMINOR_VERSION) 127 123 GEOS_PREPARE = GEOS_VERSION >= (3, 1, 0) 128 124 129 # Calling the finishGEOS() upon exit of the interpreter. 130 atexit.register(lgeos.finishGEOS) 125 if GEOS_PREPARE: 126 # Here we set up the prototypes for the initGEOS_r and finishGEOS_r 127 # routines. These functions aren't actually called until they are 128 # attached to a GEOS context handle -- this actually occurs in 129 # geos/prototypes/threadsafe.py. 130 lgeos.initGEOS_r.restype = CONTEXT_PTR 131 lgeos.finishGEOS_r.argtypes = [CONTEXT_PTR] 132 else: 133 # When thread-safety isn't available, the initGEOS routine must be called 134 # first. This function takes the notice and error functions, defined 135 # as Python callbacks above, as parameters. Here is the C code that is 136 # wrapped: 137 # extern void GEOS_DLL initGEOS(GEOSMessageHandler notice_function, GEOSMessageHandler error_function); 138 lgeos.initGEOS(notice_h, error_h) 139 atexit.register(lgeos.finishGEOS)